From ee94d8e5297cc05c608aaab530a74b931eaa2ff3 Mon Sep 17 00:00:00 2001 From: kromskii2 <146603192+kromskii2@users.noreply.github.com> Date: Sat, 15 Mar 2025 09:36:28 +0700 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=BE=D1=80=D0=BA=D0=B5=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 1 + README.md | Bin 16 -> 2384 bytes main.py | 120 +- .../__pycache__/model_manager.cpython-310.pyc | Bin 4762 -> 7371 bytes .../sampler_manager.cpython-310.pyc | Bin 4178 -> 5798 bytes .../size_preset_manager.cpython-310.pyc | Bin 3274 -> 4636 bytes modules/data/negative_prompt_categories.py | 71 + modules/data/prompt_categories.py | 86 + modules/data/prompt_translations.py | 86 + modules/model_manager.py | 98 +- .../__pycache__/home_page.cpython-310.pyc | Bin 4655 -> 5813 bytes .../__pycache__/models_page.cpython-310.pyc | Bin 4672 -> 4379 bytes modules/pages/home_page.py | 378 +- modules/pages/models_page.py | 281 +- modules/sampler_manager.py | 65 +- modules/size_preset_manager.py | 32 +- .../__pycache__/base_window.cpython-310.pyc | Bin 2652 -> 2652 bytes .../styles/__pycache__/icons.cpython-310.pyc | Bin 2359 -> 2938 bytes .../styles/__pycache__/page.cpython-310.pyc | Bin 3362 -> 3876 bytes .../style_constants.cpython-310.pyc | Bin 0 -> 4688 bytes modules/styles/icons.py | 75 +- modules/styles/page.py | 63 +- modules/styles/style_constants.py | 181 + modules/windows/console_window.py | 91 + modules/windows/negative_prompt_window.py | 153 + modules/windows/prompt_window.py | 117 + requirements.txt | 16 +- resources/icons/add.svg | 1 + resources/icons/close.svg | 1 + resources/icons/delete.svg | 1 + resources/icons/generate.svg | 1 + resources/icons/home.svg | 1 + resources/icons/image.svg | 1 + resources/icons/models.svg | 1 + resources/icons/refresh.svg | 1 + resources/icons/save.svg | 1 + resources/icons/settings.svg | 1 + resources/icons/success.svg | 1 + .../download_resources.cpython-310.pyc | Bin 3169 -> 2044 bytes scripts/download_resources.py | 54 +- server.js | 105 +- .../INSTALLER | 0 .../dotenv-0.9.9.dist-info/LICENSE | 21 + .../dotenv-0.9.9.dist-info/METADATA | 14 + .../dotenv-0.9.9.dist-info/RECORD | 7 + .../REQUESTED | 0 .../dotenv-0.9.9.dist-info/WHEEL | 6 + .../dotenv-0.9.9.dist-info/top_level.txt | 1 + venv/Lib/site-packages/dotenv/__init__.py | 49 + venv/Lib/site-packages/dotenv/__main__.py | 6 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1239 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 306 bytes .../dotenv/__pycache__/cli.cpython-310.pyc | Bin 0 -> 5978 bytes .../__pycache__/ipython.cpython-310.pyc | Bin 0 -> 1464 bytes .../dotenv/__pycache__/main.cpython-310.pyc | Bin 0 -> 10244 bytes .../dotenv/__pycache__/parser.cpython-310.pyc | Bin 0 -> 6133 bytes .../__pycache__/variables.cpython-310.pyc | Bin 0 -> 3522 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 177 bytes venv/Lib/site-packages/dotenv/cli.py | 199 + venv/Lib/site-packages/dotenv/ipython.py | 39 + venv/Lib/site-packages/dotenv/main.py | 392 + venv/Lib/site-packages/dotenv/parser.py | 175 + venv/Lib/site-packages/dotenv/py.typed | 1 + venv/Lib/site-packages/dotenv/variables.py | 86 + venv/Lib/site-packages/dotenv/version.py | 1 + .../site-packages/pip-22.2.1.dist-info/RECORD | 992 - .../pip-25.0.1.dist-info/AUTHORS.txt | 806 + .../INSTALLER} | 0 .../LICENSE.txt | 0 .../METADATA | 38 +- .../site-packages/pip-25.0.1.dist-info/RECORD | 854 + .../REQUESTED} | 0 .../WHEEL | 2 +- .../entry_points.txt | 1 - .../pip-25.0.1.dist-info/top_level.txt | 1 + venv/Lib/site-packages/pip/__init__.py | 2 +- venv/Lib/site-packages/pip/__main__.py | 7 - venv/Lib/site-packages/pip/__pip-runner__.py | 37 +- .../pip/__pycache__/__init__.cpython-310.pyc | Bin 610 -> 610 bytes .../pip/__pycache__/__main__.cpython-310.pyc | Bin 572 -> 444 bytes .../__pip-runner__.cpython-310.pyc | Bin 1379 -> 1608 bytes .../site-packages/pip/_internal/__init__.py | 3 +- .../__pycache__/__init__.cpython-310.pyc | Bin 731 -> 672 bytes .../__pycache__/build_env.cpython-310.pyc | Bin 9162 -> 9872 bytes .../__pycache__/cache.cpython-310.pyc | Bin 9193 -> 9023 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 11191 -> 11625 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 23103 -> 28076 bytes .../__pycache__/main.cpython-310.pyc | Bin 596 -> 596 bytes .../__pycache__/pyproject.cpython-310.pyc | Bin 3600 -> 3739 bytes .../self_outdated_check.cpython-310.pyc | Bin 6552 -> 6842 bytes .../__pycache__/wheel_builder.cpython-310.pyc | Bin 9184 -> 8621 bytes .../site-packages/pip/_internal/build_env.py | 68 +- venv/Lib/site-packages/pip/_internal/cache.py | 87 +- .../cli/__pycache__/__init__.cpython-310.pyc | Bin 251 -> 251 bytes .../autocompletion.cpython-310.pyc | Bin 5286 -> 5428 bytes .../__pycache__/base_command.cpython-310.pyc | Bin 6320 -> 6553 bytes .../__pycache__/cmdoptions.cpython-310.pyc | Bin 23654 -> 23521 bytes .../command_context.cpython-310.pyc | Bin 1291 -> 1291 bytes .../__pycache__/index_command.cpython-310.pyc | Bin 0 -> 4940 bytes .../cli/__pycache__/main.cpython-310.pyc | Bin 1349 -> 1485 bytes .../__pycache__/main_parser.cpython-310.pyc | Bin 2135 -> 2974 bytes .../cli/__pycache__/parser.cpython-310.pyc | Bin 9933 -> 9956 bytes .../__pycache__/progress_bars.cpython-310.pyc | Bin 1875 -> 2614 bytes .../__pycache__/req_command.cpython-310.pyc | Bin 13070 -> 8689 bytes .../cli/__pycache__/spinners.cpython-310.pyc | Bin 4913 -> 4941 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 330 -> 330 bytes .../pip/_internal/cli/autocompletion.py | 9 +- .../pip/_internal/cli/base_command.py | 159 +- .../pip/_internal/cli/cmdoptions.py | 127 +- .../pip/_internal/cli/index_command.py | 171 + .../site-packages/pip/_internal/cli/main.py | 10 + .../pip/_internal/cli/main_parser.py | 49 +- .../site-packages/pip/_internal/cli/parser.py | 16 +- .../pip/_internal/cli/progress_bars.py | 30 +- .../pip/_internal/cli/req_command.py | 209 +- .../pip/_internal/cli/spinners.py | 4 +- .../__pycache__/__init__.cpython-310.pyc | Bin 3230 -> 3230 bytes .../__pycache__/cache.cpython-310.pyc | Bin 6213 -> 6523 bytes .../__pycache__/check.cpython-310.pyc | Bin 1548 -> 1950 bytes .../__pycache__/completion.cpython-310.pyc | Bin 4139 -> 4297 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 8804 -> 8914 bytes .../__pycache__/debug.cpython-310.pyc | Bin 6645 -> 6877 bytes .../__pycache__/download.cpython-310.pyc | Bin 4025 -> 4177 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 2613 -> 2978 bytes .../commands/__pycache__/hash.cpython-310.pyc | Bin 2127 -> 2127 bytes .../commands/__pycache__/help.cpython-310.pyc | Bin 1288 -> 1288 bytes .../__pycache__/index.cpython-310.pyc | Bin 4537 -> 4525 bytes .../__pycache__/inspect.cpython-310.pyc | Bin 3101 -> 2949 bytes .../__pycache__/install.cpython-310.pyc | Bin 19398 -> 17880 bytes .../commands/__pycache__/list.cpython-310.pyc | Bin 10169 -> 10627 bytes .../__pycache__/search.cpython-310.pyc | Bin 5341 -> 5291 bytes .../commands/__pycache__/show.cpython-310.pyc | Bin 6373 -> 7141 bytes .../__pycache__/uninstall.cpython-310.pyc | Bin 3201 -> 3311 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 4864 -> 4908 bytes .../pip/_internal/commands/cache.py | 41 +- .../pip/_internal/commands/check.py | 20 +- .../pip/_internal/commands/completion.py | 20 +- .../pip/_internal/commands/configuration.py | 18 +- .../pip/_internal/commands/debug.py | 36 +- .../pip/_internal/commands/download.py | 6 +- .../pip/_internal/commands/freeze.py | 20 +- .../pip/_internal/commands/index.py | 11 +- .../pip/_internal/commands/inspect.py | 9 +- .../pip/_internal/commands/install.py | 185 +- .../pip/_internal/commands/list.py | 39 +- .../pip/_internal/commands/search.py | 10 +- .../pip/_internal/commands/show.py | 53 +- .../pip/_internal/commands/uninstall.py | 12 +- .../pip/_internal/commands/wheel.py | 14 +- .../pip/_internal/configuration.py | 41 +- .../__pycache__/__init__.cpython-310.pyc | Bin 778 -> 778 bytes .../__pycache__/base.cpython-310.pyc | Bin 1866 -> 2490 bytes .../__pycache__/installed.cpython-310.pyc | Bin 1243 -> 1462 bytes .../__pycache__/sdist.cpython-310.pyc | Bin 4974 -> 5295 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 1610 -> 1857 bytes .../pip/_internal/distributions/base.py | 18 +- .../pip/_internal/distributions/installed.py | 6 + .../pip/_internal/distributions/sdist.py | 20 +- .../pip/_internal/distributions/wheel.py | 12 +- .../site-packages/pip/_internal/exceptions.py | 221 +- .../__pycache__/__init__.cpython-310.pyc | Bin 205 -> 205 bytes .../__pycache__/collector.cpython-310.pyc | Bin 17683 -> 15086 bytes .../package_finder.cpython-310.pyc | Bin 29042 -> 29594 bytes .../index/__pycache__/sources.cpython-310.pyc | Bin 7098 -> 8857 bytes .../pip/_internal/index/collector.py | 182 +- .../pip/_internal/index/package_finder.py | 200 +- .../pip/_internal/index/sources.py | 84 +- .../pip/_internal/locations/__init__.py | 88 +- .../__pycache__/__init__.cpython-310.pyc | Bin 12509 -> 10864 bytes .../__pycache__/_distutils.cpython-310.pyc | Bin 4734 -> 4541 bytes .../__pycache__/_sysconfig.cpython-310.pyc | Bin 6178 -> 5988 bytes .../__pycache__/base.cpython-310.pyc | Bin 2381 -> 2375 bytes .../pip/_internal/locations/_distutils.py | 26 +- .../pip/_internal/locations/_sysconfig.py | 10 +- .../pip/_internal/locations/base.py | 2 +- .../pip/_internal/metadata/__init__.py | 29 +- .../__pycache__/__init__.cpython-310.pyc | Bin 3986 -> 4780 bytes .../__pycache__/_json.cpython-310.pyc | Bin 2165 -> 2231 bytes .../metadata/__pycache__/base.cpython-310.pyc | Bin 25926 -> 26865 bytes .../__pycache__/pkg_resources.cpython-310.pyc | Bin 9788 -> 10967 bytes .../pip/_internal/metadata/_json.py | 10 +- .../pip/_internal/metadata/base.py | 82 +- .../_internal/metadata/importlib/__init__.py | 4 +- .../__pycache__/__init__.cpython-310.pyc | Bin 296 -> 326 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 2102 -> 3475 bytes .../__pycache__/_dists.cpython-310.pyc | Bin 8358 -> 8831 bytes .../__pycache__/_envs.cpython-310.pyc | Bin 7469 -> 7702 bytes .../_internal/metadata/importlib/_compat.py | 50 +- .../_internal/metadata/importlib/_dists.py | 78 +- .../pip/_internal/metadata/importlib/_envs.py | 27 +- .../pip/_internal/metadata/pkg_resources.py | 68 +- .../__pycache__/__init__.cpython-310.pyc | Bin 239 -> 239 bytes .../__pycache__/candidate.cpython-310.pyc | Bin 1391 -> 1211 bytes .../__pycache__/direct_url.cpython-310.pyc | Bin 7085 -> 7381 bytes .../format_control.cpython-310.pyc | Bin 2716 -> 2710 bytes .../models/__pycache__/index.cpython-310.pyc | Bin 1208 -> 1208 bytes .../installation_report.cpython-310.pyc | Bin 1718 -> 1729 bytes .../models/__pycache__/link.cpython-310.pyc | Bin 10514 -> 18664 bytes .../models/__pycache__/scheme.cpython-310.pyc | Bin 1007 -> 910 bytes .../__pycache__/search_scope.cpython-310.pyc | Bin 3462 -> 3448 bytes .../selection_prefs.cpython-310.pyc | Bin 1669 -> 1669 bytes .../__pycache__/target_python.cpython-310.pyc | Bin 3424 -> 3790 bytes .../models/__pycache__/wheel.cpython-310.pyc | Bin 4418 -> 5073 bytes .../pip/_internal/models/candidate.py | 35 +- .../pip/_internal/models/direct_url.py | 74 +- .../pip/_internal/models/format_control.py | 4 +- .../_internal/models/installation_report.py | 11 +- .../pip/_internal/models/link.py | 382 +- .../pip/_internal/models/scheme.py | 20 +- .../pip/_internal/models/search_scope.py | 20 +- .../pip/_internal/models/selection_prefs.py | 2 + .../pip/_internal/models/target_python.py | 19 +- .../pip/_internal/models/wheel.py | 36 +- .../__pycache__/__init__.cpython-310.pyc | Bin 227 -> 227 bytes .../network/__pycache__/auth.cpython-310.pyc | Bin 7507 -> 14486 bytes .../network/__pycache__/cache.cpython-310.pyc | Bin 2914 -> 4777 bytes .../__pycache__/download.cpython-310.pyc | Bin 5509 -> 5467 bytes .../__pycache__/lazy_wheel.cpython-310.pyc | Bin 8394 -> 8395 bytes .../__pycache__/session.cpython-310.pyc | Bin 12407 -> 12575 bytes .../network/__pycache__/utils.cpython-310.pyc | Bin 1430 -> 1433 bytes .../__pycache__/xmlrpc.cpython-310.pyc | Bin 2040 -> 2083 bytes .../pip/_internal/network/auth.py | 361 +- .../pip/_internal/network/cache.py | 69 +- .../pip/_internal/network/download.py | 9 +- .../pip/_internal/network/lazy_wheel.py | 8 +- .../pip/_internal/network/session.py | 19 +- .../pip/_internal/network/utils.py | 6 +- .../pip/_internal/network/xmlrpc.py | 4 +- .../__pycache__/__init__.cpython-310.pyc | Bin 175 -> 175 bytes .../__pycache__/check.cpython-310.pyc | Bin 3988 -> 4792 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 6180 -> 6318 bytes .../__pycache__/prepare.cpython-310.pyc | Bin 14032 -> 15723 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 181 -> 181 bytes .../__pycache__/build_tracker.cpython-310.pyc | Bin 4262 -> 4953 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 1408 -> 1414 bytes .../metadata_editable.cpython-310.pyc | Bin 1442 -> 1462 bytes .../metadata_legacy.cpython-310.pyc | Bin 2353 -> 2343 bytes .../build/__pycache__/wheel.cpython-310.pyc | Bin 1198 -> 1204 bytes .../wheel_editable.cpython-310.pyc | Bin 1422 -> 1428 bytes .../__pycache__/wheel_legacy.cpython-310.pyc | Bin 2738 -> 2710 bytes .../operations/build/build_tracker.py | 56 +- .../_internal/operations/build/metadata.py | 6 +- .../operations/build/metadata_editable.py | 7 +- .../operations/build/metadata_legacy.py | 2 +- .../pip/_internal/operations/build/wheel.py | 4 +- .../operations/build/wheel_editable.py | 4 +- .../operations/build/wheel_legacy.py | 8 +- .../pip/_internal/operations/check.py | 44 +- .../pip/_internal/operations/freeze.py | 36 +- .../__pycache__/__init__.cpython-310.pyc | Bin 239 -> 239 bytes .../editable_legacy.cpython-310.pyc | Bin 1526 -> 1468 bytes .../__pycache__/legacy.cpython-310.pyc | Bin 3324 -> 0 bytes .../install/__pycache__/wheel.cpython-310.pyc | Bin 21098 -> 21456 bytes .../operations/install/editable_legacy.py | 6 +- .../_internal/operations/install/legacy.py | 120 - .../pip/_internal/operations/install/wheel.py | 101 +- .../pip/_internal/operations/prepare.py | 230 +- .../site-packages/pip/_internal/pyproject.py | 36 +- .../pip/_internal/req/__init__.py | 10 +- .../req/__pycache__/__init__.cpython-310.pyc | Bin 2582 -> 2311 bytes .../__pycache__/constructors.cpython-310.pyc | Bin 12354 -> 13945 bytes .../req/__pycache__/req_file.cpython-310.pyc | Bin 13519 -> 15430 bytes .../__pycache__/req_install.cpython-310.pyc | Bin 22660 -> 24816 bytes .../req/__pycache__/req_set.cpython-310.pyc | Bin 3890 -> 3890 bytes .../__pycache__/req_uninstall.cpython-310.pyc | Bin 19041 -> 18735 bytes .../pip/_internal/req/constructors.py | 161 +- .../pip/_internal/req/req_file.py | 273 +- .../pip/_internal/req/req_install.py | 313 +- .../pip/_internal/req/req_uninstall.py | 55 +- .../__pycache__/__init__.cpython-310.pyc | Bin 175 -> 175 bytes .../__pycache__/base.cpython-310.pyc | Bin 1027 -> 1027 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 182 -> 182 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 14930 -> 14998 bytes .../_internal/resolution/legacy/resolver.py | 43 +- .../__pycache__/__init__.cpython-310.pyc | Bin 186 -> 186 bytes .../__pycache__/base.cpython-310.pyc | Bin 6429 -> 6078 bytes .../__pycache__/candidates.cpython-310.pyc | Bin 18570 -> 19448 bytes .../__pycache__/factory.cpython-310.pyc | Bin 19050 -> 21655 bytes .../found_candidates.cpython-310.pyc | Bin 4846 -> 5207 bytes .../__pycache__/provider.cpython-310.pyc | Bin 7687 -> 8001 bytes .../__pycache__/reporter.cpython-310.pyc | Bin 3155 -> 3760 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 7444 -> 10419 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 8159 -> 8731 bytes .../_internal/resolution/resolvelib/base.py | 26 +- .../resolution/resolvelib/candidates.py | 144 +- .../resolution/resolvelib/factory.py | 240 +- .../resolution/resolvelib/found_candidates.py | 29 +- .../resolution/resolvelib/provider.py | 50 +- .../resolution/resolvelib/reporter.py | 33 +- .../resolution/resolvelib/requirements.py | 113 +- .../resolution/resolvelib/resolver.py | 27 +- .../pip/_internal/self_outdated_check.py | 71 +- .../__pycache__/__init__.cpython-310.pyc | Bin 170 -> 170 bytes .../__pycache__/_jaraco_text.cpython-310.pyc | Bin 0 -> 3825 bytes .../utils/__pycache__/_log.cpython-310.pyc | Bin 1498 -> 1498 bytes .../utils/__pycache__/appdirs.cpython-310.pyc | Bin 1596 -> 1596 bytes .../utils/__pycache__/compat.cpython-310.pyc | Bin 1486 -> 1941 bytes .../compatibility_tags.cpython-310.pyc | Bin 4055 -> 4430 bytes .../__pycache__/datetime.cpython-310.pyc | Bin 493 -> 493 bytes .../__pycache__/deprecation.cpython-310.pyc | Bin 3315 -> 3295 bytes .../direct_url_helpers.cpython-310.pyc | Bin 2061 -> 2055 bytes .../distutils_args.cpython-310.pyc | Bin 1035 -> 0 bytes .../__pycache__/egg_link.cpython-310.pyc | Bin 2126 -> 2391 bytes .../__pycache__/encoding.cpython-310.pyc | Bin 1283 -> 0 bytes .../__pycache__/entrypoints.cpython-310.pyc | Bin 2621 -> 2676 bytes .../__pycache__/filesystem.cpython-310.pyc | Bin 4459 -> 4386 bytes .../__pycache__/filetypes.cpython-310.pyc | Bin 920 -> 920 bytes .../utils/__pycache__/glibc.cpython-310.pyc | Bin 1649 -> 1730 bytes .../utils/__pycache__/hashes.cpython-310.pyc | Bin 5172 -> 5599 bytes .../inject_securetransport.cpython-310.pyc | Bin 965 -> 0 bytes .../utils/__pycache__/logging.cpython-310.pyc | Bin 9697 -> 9947 bytes .../utils/__pycache__/misc.cpython-310.pyc | Bin 21576 -> 22846 bytes .../utils/__pycache__/models.cpython-310.pyc | Bin 1966 -> 0 bytes .../__pycache__/packaging.cpython-310.pyc | Bin 2058 -> 2077 bytes .../utils/__pycache__/retry.cpython-310.pyc | Bin 0 -> 1598 bytes .../setuptools_build.cpython-310.pyc | Bin 4573 -> 3794 bytes .../__pycache__/subprocess.cpython-310.pyc | Bin 5746 -> 5706 bytes .../__pycache__/temp_dir.cpython-310.pyc | Bin 7293 -> 8301 bytes .../__pycache__/unpacking.cpython-310.pyc | Bin 6644 -> 8065 bytes .../utils/__pycache__/urls.cpython-310.pyc | Bin 1571 -> 1349 bytes .../__pycache__/virtualenv.cpython-310.pyc | Bin 3266 -> 3266 bytes .../utils/__pycache__/wheel.cpython-310.pyc | Bin 4391 -> 4369 bytes .../pip/_internal/utils/_jaraco_text.py | 109 + .../pip/_internal/utils/compat.py | 16 + .../pip/_internal/utils/compatibility_tags.py | 27 +- .../pip/_internal/utils/deprecation.py | 18 +- .../pip/_internal/utils/direct_url_helpers.py | 4 +- .../pip/_internal/utils/distutils_args.py | 43 - .../pip/_internal/utils/egg_link.py | 35 +- .../pip/_internal/utils/encoding.py | 36 - .../pip/_internal/utils/entrypoints.py | 11 +- .../pip/_internal/utils/filesystem.py | 8 +- .../pip/_internal/utils/glibc.py | 25 +- .../pip/_internal/utils/hashes.py | 17 +- .../_internal/utils/inject_securetransport.py | 35 - .../pip/_internal/utils/logging.py | 16 +- .../site-packages/pip/_internal/utils/misc.py | 282 +- .../pip/_internal/utils/models.py | 39 - .../pip/_internal/utils/packaging.py | 3 +- .../pip/_internal/utils/retry.py | 42 + .../pip/_internal/utils/setuptools_build.py | 53 +- .../pip/_internal/utils/subprocess.py | 23 +- .../pip/_internal/utils/temp_dir.py | 54 +- .../pip/_internal/utils/unpacking.py | 180 +- .../site-packages/pip/_internal/utils/urls.py | 7 - .../pip/_internal/utils/virtualenv.py | 12 +- .../pip/_internal/utils/wheel.py | 6 +- .../vcs/__pycache__/__init__.cpython-310.pyc | Bin 493 -> 493 bytes .../vcs/__pycache__/bazaar.cpython-310.pyc | Bin 3320 -> 3490 bytes .../vcs/__pycache__/git.cpython-310.pyc | Bin 12523 -> 12424 bytes .../vcs/__pycache__/mercurial.cpython-310.pyc | Bin 5039 -> 5053 bytes .../__pycache__/subversion.cpython-310.pyc | Bin 8427 -> 8453 bytes .../versioncontrol.cpython-310.pyc | Bin 21122 -> 20960 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 23 +- .../site-packages/pip/_internal/vcs/git.py | 5 +- .../pip/_internal/vcs/mercurial.py | 2 +- .../pip/_internal/vcs/subversion.py | 10 +- .../pip/_internal/vcs/versioncontrol.py | 59 +- .../pip/_internal/wheel_builder.py | 49 +- .../Lib/site-packages/pip/_vendor/__init__.py | 12 +- .../__pycache__/__init__.cpython-310.pyc | Bin 3106 -> 3039 bytes .../_vendor/__pycache__/six.cpython-310.pyc | Bin 27564 -> 0 bytes .../typing_extensions.cpython-310.pyc | Bin 60704 -> 100388 bytes .../pip/_vendor/cachecontrol/__init__.py | 19 +- .../__pycache__/__init__.cpython-310.pyc | Bin 621 -> 741 bytes .../__pycache__/_cmd.cpython-310.pyc | Bin 1559 -> 1810 bytes .../__pycache__/adapter.cpython-310.pyc | Bin 3135 -> 4393 bytes .../__pycache__/cache.cpython-310.pyc | Bin 2669 -> 3254 bytes .../__pycache__/compat.cpython-310.pyc | Bin 735 -> 0 bytes .../__pycache__/controller.cpython-310.pyc | Bin 8575 -> 10142 bytes .../__pycache__/filewrapper.cpython-310.pyc | Bin 2771 -> 3194 bytes .../__pycache__/heuristics.cpython-310.pyc | Bin 4695 -> 5375 bytes .../__pycache__/serialize.cpython-310.pyc | Bin 4310 -> 3328 bytes .../__pycache__/wrapper.cpython-310.pyc | Bin 666 -> 1445 bytes .../pip/_vendor/cachecontrol/_cmd.py | 25 +- .../pip/_vendor/cachecontrol/adapter.py | 80 +- .../pip/_vendor/cachecontrol/cache.py | 36 +- .../_vendor/cachecontrol/caches/__init__.py | 5 +- .../__pycache__/__init__.cpython-310.pyc | Bin 340 -> 404 bytes .../__pycache__/file_cache.cpython-310.pyc | Bin 4940 -> 5623 bytes .../__pycache__/redis_cache.cpython-310.pyc | Bin 1598 -> 2019 bytes .../_vendor/cachecontrol/caches/file_cache.py | 84 +- .../cachecontrol/caches/redis_cache.py | 31 +- .../pip/_vendor/cachecontrol/compat.py | 32 - .../pip/_vendor/cachecontrol/controller.py | 175 +- .../pip/_vendor/cachecontrol/filewrapper.py | 34 +- .../pip/_vendor/cachecontrol/heuristics.py | 60 +- .../__init__.py => cachecontrol/py.typed} | 0 .../pip/_vendor/cachecontrol/serialize.py | 184 +- .../pip/_vendor/cachecontrol/wrapper.py | 34 +- .../pip/_vendor/certifi/__init__.py | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 283 -> 283 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 433 -> 433 bytes .../certifi/__pycache__/core.cpython-310.pyc | Bin 1777 -> 2126 bytes .../pip/_vendor/certifi/cacert.pem | 1172 +- .../site-packages/pip/_vendor/certifi/core.py | 78 +- .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/chardet/__init__.py | 93 - .../__pycache__/__init__.cpython-310.pyc | Bin 2360 -> 0 bytes .../__pycache__/big5freq.cpython-310.pyc | Bin 27157 -> 0 bytes .../__pycache__/big5prober.cpython-310.pyc | Bin 1099 -> 0 bytes .../chardistribution.cpython-310.pyc | Bin 6202 -> 0 bytes .../charsetgroupprober.cpython-310.pyc | Bin 2193 -> 0 bytes .../__pycache__/charsetprober.cpython-310.pyc | Bin 3381 -> 0 bytes .../codingstatemachine.cpython-310.pyc | Bin 2866 -> 0 bytes .../__pycache__/cp949prober.cpython-310.pyc | Bin 1106 -> 0 bytes .../chardet/__pycache__/enums.cpython-310.pyc | Bin 2542 -> 0 bytes .../__pycache__/escprober.cpython-310.pyc | Bin 2587 -> 0 bytes .../chardet/__pycache__/escsm.cpython-310.pyc | Bin 8356 -> 0 bytes .../__pycache__/eucjpprober.cpython-310.pyc | Bin 2390 -> 0 bytes .../__pycache__/euckrfreq.cpython-310.pyc | Bin 12041 -> 0 bytes .../__pycache__/euckrprober.cpython-310.pyc | Bin 1107 -> 0 bytes .../__pycache__/euctwfreq.cpython-310.pyc | Bin 27161 -> 0 bytes .../__pycache__/euctwprober.cpython-310.pyc | Bin 1107 -> 0 bytes .../__pycache__/gb2312freq.cpython-310.pyc | Bin 19085 -> 0 bytes .../__pycache__/gb2312prober.cpython-310.pyc | Bin 1115 -> 0 bytes .../__pycache__/hebrewprober.cpython-310.pyc | Bin 2998 -> 0 bytes .../__pycache__/jisfreq.cpython-310.pyc | Bin 22113 -> 0 bytes .../__pycache__/johabfreq.cpython-310.pyc | Bin 138737 -> 0 bytes .../__pycache__/johabprober.cpython-310.pyc | Bin 1106 -> 0 bytes .../__pycache__/jpcntx.cpython-310.pyc | Bin 37609 -> 0 bytes .../langbulgarianmodel.cpython-310.pyc | Bin 47905 -> 0 bytes .../langgreekmodel.cpython-310.pyc | Bin 46095 -> 0 bytes .../langhebrewmodel.cpython-310.pyc | Bin 44542 -> 0 bytes .../langhungarianmodel.cpython-310.pyc | Bin 47865 -> 0 bytes .../langrussianmodel.cpython-310.pyc | Bin 61006 -> 0 bytes .../__pycache__/langthaimodel.cpython-310.pyc | Bin 44718 -> 0 bytes .../langturkishmodel.cpython-310.pyc | Bin 44559 -> 0 bytes .../__pycache__/latin1prober.cpython-310.pyc | Bin 4383 -> 0 bytes .../mbcharsetprober.cpython-310.pyc | Bin 2209 -> 0 bytes .../mbcsgroupprober.cpython-310.pyc | Bin 1160 -> 0 bytes .../__pycache__/mbcssm.cpython-310.pyc | Bin 20683 -> 0 bytes .../sbcharsetprober.cpython-310.pyc | Bin 3176 -> 0 bytes .../sbcsgroupprober.cpython-310.pyc | Bin 1699 -> 0 bytes .../__pycache__/sjisprober.cpython-310.pyc | Bin 2428 -> 0 bytes .../universaldetector.cpython-310.pyc | Bin 6445 -> 0 bytes .../__pycache__/utf1632prober.cpython-310.pyc | Bin 5859 -> 0 bytes .../__pycache__/utf8prober.cpython-310.pyc | Bin 1942 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 417 -> 0 bytes .../pip/_vendor/chardet/big5freq.py | 386 - .../pip/_vendor/chardet/big5prober.py | 47 - .../pip/_vendor/chardet/chardistribution.py | 259 - .../pip/_vendor/chardet/charsetgroupprober.py | 109 - .../pip/_vendor/chardet/charsetprober.py | 138 - .../cli/__pycache__/__init__.cpython-310.pyc | Bin 174 -> 0 bytes .../__pycache__/chardetect.cpython-310.pyc | Bin 2382 -> 0 bytes .../pip/_vendor/chardet/cli/chardetect.py | 86 - .../pip/_vendor/chardet/codingstatemachine.py | 88 - .../pip/_vendor/chardet/cp949prober.py | 49 - .../pip/_vendor/chardet/enums.py | 82 - .../pip/_vendor/chardet/escprober.py | 102 - .../pip/_vendor/chardet/escsm.py | 260 - .../pip/_vendor/chardet/eucjpprober.py | 95 - .../pip/_vendor/chardet/euckrfreq.py | 196 - .../pip/_vendor/chardet/euckrprober.py | 47 - .../pip/_vendor/chardet/euctwfreq.py | 388 - .../pip/_vendor/chardet/euctwprober.py | 47 - .../pip/_vendor/chardet/gb2312freq.py | 284 - .../pip/_vendor/chardet/gb2312prober.py | 47 - .../pip/_vendor/chardet/hebrewprober.py | 302 - .../pip/_vendor/chardet/jisfreq.py | 325 - .../pip/_vendor/chardet/johabfreq.py | 2382 --- .../pip/_vendor/chardet/johabprober.py | 47 - .../pip/_vendor/chardet/jpcntx.py | 237 - .../pip/_vendor/chardet/langbulgarianmodel.py | 4649 ----- .../pip/_vendor/chardet/langgreekmodel.py | 4397 ----- .../pip/_vendor/chardet/langhebrewmodel.py | 4380 ----- .../pip/_vendor/chardet/langhungarianmodel.py | 4649 ----- .../pip/_vendor/chardet/langrussianmodel.py | 5725 ------ .../pip/_vendor/chardet/langthaimodel.py | 4380 ----- .../pip/_vendor/chardet/langturkishmodel.py | 4380 ----- .../pip/_vendor/chardet/latin1prober.py | 145 - .../pip/_vendor/chardet/mbcharsetprober.py | 95 - .../pip/_vendor/chardet/mbcsgroupprober.py | 56 - .../pip/_vendor/chardet/mbcssm.py | 660 - .../__pycache__/__init__.cpython-310.pyc | Bin 179 -> 0 bytes .../__pycache__/languages.cpython-310.pyc | Bin 7937 -> 0 bytes .../pip/_vendor/chardet/metadata/languages.py | 351 - .../pip/_vendor/chardet/sbcharsetprober.py | 160 - .../pip/_vendor/chardet/sbcsgroupprober.py | 88 - .../pip/_vendor/chardet/sjisprober.py | 98 - .../pip/_vendor/chardet/universaldetector.py | 328 - .../pip/_vendor/chardet/utf1632prober.py | 223 - .../pip/_vendor/chardet/utf8prober.py | 80 - .../pip/_vendor/chardet/version.py | 9 - .../pip/_vendor/colorama/__init__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 422 -> 0 bytes .../colorama/__pycache__/ansi.cpython-310.pyc | Bin 2983 -> 0 bytes .../__pycache__/ansitowin32.cpython-310.pyc | Bin 8185 -> 0 bytes .../__pycache__/initialise.cpython-310.pyc | Bin 1669 -> 0 bytes .../__pycache__/win32.cpython-310.pyc | Bin 3929 -> 0 bytes .../__pycache__/winterm.cpython-310.pyc | Bin 4546 -> 0 bytes .../pip/_vendor/colorama/ansi.py | 102 - .../pip/_vendor/colorama/ansitowin32.py | 266 - .../pip/_vendor/colorama/initialise.py | 80 - .../pip/_vendor/colorama/win32.py | 152 - .../pip/_vendor/colorama/winterm.py | 169 - .../pip/_vendor/distlib/__init__.py | 22 +- .../__pycache__/__init__.cpython-310.pyc | Bin 1041 -> 1041 bytes .../__pycache__/compat.cpython-310.pyc | Bin 31387 -> 31414 bytes .../__pycache__/database.cpython-310.pyc | Bin 43127 -> 43051 bytes .../distlib/__pycache__/index.cpython-310.pyc | Bin 17292 -> 17278 bytes .../__pycache__/locators.cpython-310.pyc | Bin 38349 -> 38229 bytes .../__pycache__/manifest.cpython-310.pyc | Bin 10209 -> 10206 bytes .../__pycache__/markers.cpython-310.pyc | Bin 5015 -> 5276 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 26766 -> 26905 bytes .../__pycache__/resources.cpython-310.pyc | Bin 11015 -> 11015 bytes .../__pycache__/scripts.cpython-310.pyc | Bin 11481 -> 11644 bytes .../distlib/__pycache__/util.cpython-310.pyc | Bin 51676 -> 52052 bytes .../__pycache__/version.cpython-310.pyc | Bin 20130 -> 20260 bytes .../distlib/__pycache__/wheel.cpython-310.pyc | Bin 28110 -> 28461 bytes .../pip/_vendor/distlib/compat.py | 179 +- .../pip/_vendor/distlib/database.py | 139 +- .../pip/_vendor/distlib/index.py | 8 +- .../pip/_vendor/distlib/locators.py | 147 +- .../pip/_vendor/distlib/manifest.py | 25 +- .../pip/_vendor/distlib/markers.py | 44 +- .../pip/_vendor/distlib/metadata.py | 191 +- .../pip/_vendor/distlib/scripts.py | 108 +- .../site-packages/pip/_vendor/distlib/t32.exe | Bin 97792 -> 97792 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 182784 -> 182784 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 107520 -> 108032 bytes .../site-packages/pip/_vendor/distlib/util.py | 250 +- .../pip/_vendor/distlib/version.py | 39 +- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 91648 -> 91648 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 168448 -> 168448 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 101888 -> 101888 bytes .../pip/_vendor/distlib/wheel.py | 174 +- .../__pycache__/__init__.cpython-310.pyc | Bin 894 -> 894 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 248 -> 248 bytes .../distro/__pycache__/distro.cpython-310.pyc | Bin 41311 -> 42133 bytes .../pip/_vendor/distro/distro.py | 111 +- .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 3 +- .../idna/__pycache__/__init__.cpython-310.pyc | Bin 826 -> 831 bytes .../idna/__pycache__/codec.cpython-310.pyc | Bin 2797 -> 3252 bytes .../idna/__pycache__/compat.cpython-310.pyc | Bin 726 -> 734 bytes .../idna/__pycache__/core.cpython-310.pyc | Bin 9569 -> 9686 bytes .../idna/__pycache__/idnadata.cpython-310.pyc | Bin 38204 -> 194427 bytes .../__pycache__/intranges.cpython-310.pyc | Bin 1963 -> 1963 bytes .../__pycache__/package_data.cpython-310.pyc | Bin 190 -> 191 bytes .../__pycache__/uts46data.cpython-310.pyc | Bin 150925 -> 152355 bytes .../site-packages/pip/_vendor/idna/codec.py | 86 +- .../site-packages/pip/_vendor/idna/compat.py | 10 +- .../site-packages/pip/_vendor/idna/core.py | 296 +- .../pip/_vendor/idna/idnadata.py | 5586 ++++-- .../pip/_vendor/idna/intranges.py | 11 +- .../pip/_vendor/idna/package_data.py | 3 +- .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 16363 ++++++++-------- .../pip/_vendor/msgpack/__init__.py | 22 +- .../__pycache__/__init__.cpython-310.pyc | Bin 1424 -> 1376 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 1787 -> 1787 bytes .../msgpack/__pycache__/ext.cpython-310.pyc | Bin 6295 -> 6068 bytes .../__pycache__/fallback.cpython-310.pyc | Bin 25462 -> 23750 bytes .../site-packages/pip/_vendor/msgpack/ext.py | 61 +- .../pip/_vendor/msgpack/fallback.py | 227 +- .../pip/_vendor/packaging/__about__.py | 26 - .../pip/_vendor/packaging/__init__.py | 30 +- .../__pycache__/__about__.cpython-310.pyc | Bin 569 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 425 -> 502 bytes .../__pycache__/_elffile.cpython-310.pyc | Bin 0 -> 3377 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 7279 -> 6567 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 4591 -> 3426 bytes .../__pycache__/_parser.cpython-310.pyc | Bin 0 -> 9242 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 2684 -> 2684 bytes .../__pycache__/_tokenizer.cpython-310.pyc | Bin 0 -> 5898 bytes .../__pycache__/markers.cpython-310.pyc | Bin 9268 -> 7865 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 0 -> 18727 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 3954 -> 2896 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 21506 -> 31394 bytes .../__pycache__/tags.cpython-310.pyc | Bin 12175 -> 15202 bytes .../__pycache__/utils.cpython-310.pyc | Bin 3554 -> 4630 bytes .../__pycache__/version.cpython-310.pyc | Bin 12904 -> 15031 bytes .../pip/_vendor/packaging/_elffile.py | 110 + .../pip/_vendor/packaging/_manylinux.py | 230 +- .../pip/_vendor/packaging/_musllinux.py | 97 +- .../pip/_vendor/packaging/_parser.py | 354 + .../pip/_vendor/packaging/_tokenizer.py | 194 + .../_vendor/packaging/licenses/__init__.py | 145 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2601 bytes .../__pycache__/_spdx.cpython-310.pyc | Bin 0 -> 40961 bytes .../pip/_vendor/packaging/licenses/_spdx.py | 759 + .../pip/_vendor/packaging/markers.py | 301 +- .../pip/_vendor/packaging/metadata.py | 863 + .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 149 +- .../pip/_vendor/packaging/specifiers.py | 1000 +- .../pip/_vendor/packaging/tags.py | 276 +- .../pip/_vendor/packaging/utils.py | 129 +- .../pip/_vendor/packaging/version.py | 452 +- .../pip/_vendor/pep517/__init__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 292 -> 0 bytes .../pep517/__pycache__/build.cpython-310.pyc | Bin 3575 -> 0 bytes .../pep517/__pycache__/check.cpython-310.pyc | Bin 4539 -> 0 bytes .../__pycache__/colorlog.cpython-310.pyc | Bin 2943 -> 0 bytes .../pep517/__pycache__/compat.cpython-310.pyc | Bin 1516 -> 0 bytes .../__pycache__/dirtools.cpython-310.pyc | Bin 1334 -> 0 bytes .../__pycache__/envbuild.cpython-310.pyc | Bin 4357 -> 0 bytes .../pep517/__pycache__/meta.cpython-310.pyc | Bin 2939 -> 0 bytes .../__pycache__/wrappers.cpython-310.pyc | Bin 12285 -> 0 bytes .../site-packages/pip/_vendor/pep517/build.py | 127 - .../site-packages/pip/_vendor/pep517/check.py | 207 - .../pip/_vendor/pep517/colorlog.py | 115 - .../pip/_vendor/pep517/compat.py | 51 - .../pip/_vendor/pep517/dirtools.py | 44 - .../pip/_vendor/pep517/envbuild.py | 171 - .../pip/_vendor/pep517/in_process/__init__.py | 17 - .../__pycache__/__init__.cpython-310.pyc | Bin 900 -> 0 bytes .../__pycache__/_in_process.cpython-310.pyc | Bin 10047 -> 0 bytes .../site-packages/pip/_vendor/pep517/meta.py | 92 - .../pip/_vendor/pep517/wrappers.py | 375 - .../pip/_vendor/pkg_resources/__init__.py | 1806 +- .../__pycache__/__init__.cpython-310.pyc | Bin 99869 -> 113943 bytes .../__pycache__/py31compat.cpython-310.pyc | Bin 639 -> 0 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 - .../pip/_vendor/platformdirs/__init__.py | 553 +- .../pip/_vendor/platformdirs/__main__.py | 27 +- .../__pycache__/__init__.cpython-310.pyc | Bin 10507 -> 15836 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 1215 -> 1382 bytes .../__pycache__/android.cpython-310.pyc | Bin 4305 -> 7390 bytes .../__pycache__/api.cpython-310.pyc | Bin 5181 -> 10186 bytes .../__pycache__/macos.cpython-310.pyc | Bin 3169 -> 6504 bytes .../__pycache__/unix.cpython-310.pyc | Bin 6870 -> 10500 bytes .../__pycache__/version.cpython-310.pyc | Bin 272 -> 497 bytes .../__pycache__/windows.cpython-310.pyc | Bin 6413 -> 9070 bytes .../pip/_vendor/platformdirs/android.py | 179 +- .../pip/_vendor/platformdirs/api.py | 188 +- .../pip/_vendor/platformdirs/macos.py | 112 +- .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 218 +- .../pip/_vendor/platformdirs/version.py | 18 +- .../pip/_vendor/platformdirs/windows.py | 162 +- .../pip/_vendor/pygments/__init__.py | 41 +- .../pip/_vendor/pygments/__main__.py | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 2979 -> 2914 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 567 -> 567 bytes .../__pycache__/cmdline.cpython-310.pyc | Bin 15432 -> 15533 bytes .../__pycache__/console.cpython-310.pyc | Bin 1862 -> 1869 bytes .../__pycache__/filter.cpython-310.pyc | Bin 2633 -> 2629 bytes .../__pycache__/formatter.cpython-310.pyc | Bin 2989 -> 4080 bytes .../__pycache__/lexer.cpython-310.pyc | Bin 24352 -> 26505 bytes .../__pycache__/modeline.cpython-310.pyc | Bin 1171 -> 1172 bytes .../__pycache__/plugin.cpython-310.pyc | Bin 2023 -> 1928 bytes .../__pycache__/regexopt.cpython-310.pyc | Bin 2935 -> 2935 bytes .../__pycache__/scanner.cpython-310.pyc | Bin 3537 -> 3537 bytes .../__pycache__/sphinxext.cpython-310.pyc | Bin 4521 -> 7746 bytes .../__pycache__/style.cpython-310.pyc | Bin 4558 -> 4593 bytes .../__pycache__/token.cpython-310.pyc | Bin 4630 -> 4675 bytes .../__pycache__/unistring.cpython-310.pyc | Bin 31184 -> 31209 bytes .../pygments/__pycache__/util.cpython-310.pyc | Bin 9126 -> 10041 bytes .../pip/_vendor/pygments/cmdline.py | 37 +- .../pip/_vendor/pygments/console.py | 10 +- .../pip/_vendor/pygments/filter.py | 5 +- .../pip/_vendor/pygments/filters/__init__.py | 15 +- .../__pycache__/__init__.cpython-310.pyc | Bin 29496 -> 29605 bytes .../pip/_vendor/pygments/formatter.py | 57 +- .../_vendor/pygments/formatters/__init__.py | 50 +- .../__pycache__/__init__.cpython-310.pyc | Bin 4647 -> 4998 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 5515 -> 3979 bytes .../__pycache__/bbcode.cpython-310.pyc | Bin 3064 -> 3074 bytes .../__pycache__/groff.cpython-310.pyc | Bin 4377 -> 4401 bytes .../__pycache__/html.cpython-310.pyc | Bin 29111 -> 29355 bytes .../__pycache__/img.cpython-310.pyc | Bin 17476 -> 18383 bytes .../__pycache__/irc.cpython-310.pyc | Bin 4567 -> 4077 bytes .../__pycache__/latex.cpython-310.pyc | Bin 13777 -> 13871 bytes .../__pycache__/other.cpython-310.pyc | Bin 4783 -> 4789 bytes .../__pycache__/pangomarkup.cpython-310.pyc | Bin 2083 -> 2093 bytes .../__pycache__/rtf.cpython-310.pyc | Bin 4113 -> 8839 bytes .../__pycache__/svg.cpython-310.pyc | Bin 6311 -> 6298 bytes .../__pycache__/terminal.cpython-310.pyc | Bin 3978 -> 3978 bytes .../__pycache__/terminal256.cpython-310.pyc | Bin 9228 -> 9228 bytes .../_vendor/pygments/formatters/_mapping.py | 69 +- .../pip/_vendor/pygments/formatters/bbcode.py | 4 +- .../pip/_vendor/pygments/formatters/groff.py | 8 +- .../pip/_vendor/pygments/formatters/html.py | 104 +- .../pip/_vendor/pygments/formatters/img.py | 74 +- .../pip/_vendor/pygments/formatters/irc.py | 37 +- .../pip/_vendor/pygments/formatters/latex.py | 51 +- .../pip/_vendor/pygments/formatters/other.py | 7 +- .../pygments/formatters/pangomarkup.py | 4 +- .../pip/_vendor/pygments/formatters/rtf.py | 251 +- .../pip/_vendor/pygments/formatters/svg.py | 37 +- .../_vendor/pygments/formatters/terminal.py | 2 +- .../pygments/formatters/terminal256.py | 2 +- .../pip/_vendor/pygments/lexer.py | 175 +- .../pip/_vendor/pygments/lexers/__init__.py | 89 +- .../__pycache__/__init__.cpython-310.pyc | Bin 9333 -> 10040 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 60128 -> 64883 bytes .../lexers/__pycache__/python.cpython-310.pyc | Bin 29336 -> 30192 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 147 +- .../pip/_vendor/pygments/lexers/python.py | 271 +- .../pip/_vendor/pygments/modeline.py | 8 +- .../pip/_vendor/pygments/plugin.py | 23 +- .../pip/_vendor/pygments/regexopt.py | 2 +- .../pip/_vendor/pygments/scanner.py | 2 +- .../pip/_vendor/pygments/sphinxext.py | 100 +- .../pip/_vendor/pygments/style.py | 10 +- .../pip/_vendor/pygments/styles/__init__.py | 84 +- .../__pycache__/__init__.cpython-310.pyc | Bin 3199 -> 2041 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 0 -> 3291 bytes .../pip/_vendor/pygments/styles/_mapping.py | 54 + .../pip/_vendor/pygments/token.py | 4 +- .../pip/_vendor/pygments/unistring.py | 14 +- .../pip/_vendor/pygments/util.py | 60 +- .../pip/_vendor/pyparsing/__init__.py | 331 - .../__pycache__/__init__.cpython-310.pyc | Bin 7108 -> 0 bytes .../__pycache__/actions.cpython-310.pyc | Bin 7158 -> 0 bytes .../__pycache__/common.cpython-310.pyc | Bin 10084 -> 0 bytes .../__pycache__/core.cpython-310.pyc | Bin 176499 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 9042 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 35319 -> 0 bytes .../__pycache__/results.cpython-310.pyc | Bin 24766 -> 0 bytes .../__pycache__/testing.cpython-310.pyc | Bin 12078 -> 0 bytes .../__pycache__/unicode.cpython-310.pyc | Bin 10037 -> 0 bytes .../__pycache__/util.cpython-310.pyc | Bin 8584 -> 0 bytes .../pip/_vendor/pyparsing/actions.py | 207 - .../pip/_vendor/pyparsing/common.py | 424 - .../pip/_vendor/pyparsing/core.py | 5814 ------ .../pip/_vendor/pyparsing/diagram/__init__.py | 642 - .../__pycache__/__init__.cpython-310.pyc | Bin 16572 -> 0 bytes .../pip/_vendor/pyparsing/exceptions.py | 267 - .../pip/_vendor/pyparsing/helpers.py | 1088 - .../pip/_vendor/pyparsing/results.py | 760 - .../pip/_vendor/pyparsing/testing.py | 331 - .../pip/_vendor/pyparsing/unicode.py | 352 - .../pip/_vendor/pyparsing/util.py | 235 - .../pip/_vendor/pyproject_hooks/__init__.py | 31 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 679 bytes .../__pycache__/_impl.cpython-310.pyc | Bin 0 -> 14073 bytes .../pip/_vendor/pyproject_hooks/_impl.py | 410 + .../pyproject_hooks/_in_process/__init__.py | 21 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 803 bytes .../__pycache__/_in_process.cpython-310.pyc | Bin 0 -> 10464 bytes .../_in_process}/_in_process.py | 226 +- .../pip/_vendor/pyproject_hooks/py.typed | 0 .../pip/_vendor/requests/__init__.py | 21 +- .../__pycache__/__init__.cpython-310.pyc | Bin 3995 -> 3851 bytes .../__pycache__/__version__.cpython-310.pyc | Bin 534 -> 529 bytes .../_internal_utils.cpython-310.pyc | Bin 1544 -> 1605 bytes .../__pycache__/adapters.cpython-310.pyc | Bin 16878 -> 22091 bytes .../requests/__pycache__/api.cpython-310.pyc | Bin 6633 -> 6705 bytes .../requests/__pycache__/auth.cpython-310.pyc | Bin 8101 -> 8101 bytes .../__pycache__/certs.cpython-310.pyc | Bin 618 -> 618 bytes .../__pycache__/compat.cpython-310.pyc | Bin 1350 -> 1497 bytes .../__pycache__/cookies.cpython-310.pyc | Bin 18676 -> 18706 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 5720 -> 6220 bytes .../requests/__pycache__/help.cpython-310.pyc | Bin 2846 -> 2795 bytes .../__pycache__/hooks.cpython-310.pyc | Bin 973 -> 973 bytes .../__pycache__/models.cpython-310.pyc | Bin 24246 -> 24269 bytes .../__pycache__/packages.cpython-310.pyc | Bin 487 -> 719 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 19565 -> 19715 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 4652 -> 4723 bytes .../__pycache__/structures.cpython-310.pyc | Bin 4417 -> 4417 bytes .../__pycache__/utils.cpython-310.pyc | Bin 24315 -> 24617 bytes .../pip/_vendor/requests/__version__.py | 8 +- .../pip/_vendor/requests/_internal_utils.py | 6 +- .../pip/_vendor/requests/adapters.py | 297 +- .../site-packages/pip/_vendor/requests/api.py | 8 +- .../pip/_vendor/requests/auth.py | 1 - .../pip/_vendor/requests/compat.py | 15 +- .../pip/_vendor/requests/cookies.py | 16 +- .../pip/_vendor/requests/exceptions.py | 10 + .../pip/_vendor/requests/help.py | 6 +- .../pip/_vendor/requests/models.py | 15 +- .../pip/_vendor/requests/packages.py | 13 +- .../pip/_vendor/requests/sessions.py | 14 +- .../pip/_vendor/requests/status_codes.py | 10 +- .../pip/_vendor/requests/utils.py | 50 +- .../pip/_vendor/resolvelib/__init__.py | 2 +- .../__pycache__/__init__.cpython-310.pyc | Bin 585 -> 585 bytes .../__pycache__/providers.cpython-310.pyc | Bin 6636 -> 6635 bytes .../__pycache__/reporters.cpython-310.pyc | Bin 2556 -> 2588 bytes .../__pycache__/resolvers.cpython-310.pyc | Bin 15109 -> 17422 bytes .../__pycache__/structs.cpython-310.pyc | Bin 7142 -> 7244 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 180 bytes .../collections_abc.cpython-310.pyc | Bin 356 -> 356 bytes .../pip/_vendor/resolvelib/providers.py | 14 +- .../pip/_vendor/resolvelib/py.typed | 0 .../pip/_vendor/resolvelib/reporters.py | 2 +- .../pip/_vendor/resolvelib/resolvers.py | 93 +- .../pip/_vendor/resolvelib/structs.py | 11 +- .../pip/_vendor/rich/__init__.py | 7 +- .../pip/_vendor/rich/__main__.py | 9 - .../rich/__pycache__/__init__.cpython-310.pyc | Bin 5953 -> 6092 bytes .../rich/__pycache__/__main__.cpython-310.pyc | Bin 7275 -> 7162 bytes .../__pycache__/_cell_widths.cpython-310.pyc | Bin 7793 -> 7844 bytes .../__pycache__/_emoji_codes.cpython-310.pyc | Bin 360033 -> 360033 bytes .../_emoji_replace.cpython-310.pyc | Bin 1173 -> 1173 bytes .../_export_format.cpython-310.pyc | Bin 2290 -> 2304 bytes .../__pycache__/_extension.cpython-310.pyc | Bin 474 -> 474 bytes .../rich/__pycache__/_fileno.cpython-310.pyc | Bin 0 -> 767 bytes .../rich/__pycache__/_inspect.cpython-310.pyc | Bin 8651 -> 8601 bytes .../__pycache__/_log_render.cpython-310.pyc | Bin 2619 -> 2619 bytes .../rich/__pycache__/_loop.cpython-310.pyc | Bin 1271 -> 1271 bytes .../__pycache__/_null_file.cpython-310.pyc | Bin 0 -> 3222 bytes .../__pycache__/_palettes.cpython-310.pyc | Bin 5076 -> 5076 bytes .../rich/__pycache__/_pick.cpython-310.pyc | Bin 619 -> 619 bytes .../rich/__pycache__/_ratio.cpython-310.pyc | Bin 5138 -> 5138 bytes .../__pycache__/_spinners.cpython-310.pyc | Bin 12250 -> 12250 bytes .../rich/__pycache__/_stack.cpython-310.pyc | Bin 817 -> 817 bytes .../rich/__pycache__/_timer.cpython-310.pyc | Bin 666 -> 666 bytes .../_win32_console.cpython-310.pyc | Bin 18986 -> 18946 bytes .../rich/__pycache__/_windows.cpython-310.pyc | Bin 1768 -> 1768 bytes .../_windows_renderer.cpython-310.pyc | Bin 2022 -> 2022 bytes .../rich/__pycache__/_wrap.cpython-310.pyc | Bin 1530 -> 2452 bytes .../rich/__pycache__/abc.cpython-310.pyc | Bin 1293 -> 1293 bytes .../rich/__pycache__/align.cpython-310.pyc | Bin 7928 -> 8025 bytes .../rich/__pycache__/ansi.cpython-310.pyc | Bin 5935 -> 5976 bytes .../rich/__pycache__/bar.cpython-310.pyc | Bin 2962 -> 2962 bytes .../rich/__pycache__/box.cpython-310.pyc | Bin 8382 -> 8382 bytes .../rich/__pycache__/cells.cpython-310.pyc | Bin 3952 -> 4253 bytes .../rich/__pycache__/color.cpython-310.pyc | Bin 17440 -> 17695 bytes .../__pycache__/color_triplet.cpython-310.pyc | Bin 1416 -> 1416 bytes .../rich/__pycache__/columns.cpython-310.pyc | Bin 6176 -> 6176 bytes .../rich/__pycache__/console.cpython-310.pyc | Bin 80936 -> 83544 bytes .../__pycache__/constrain.cpython-310.pyc | Bin 1733 -> 1733 bytes .../__pycache__/containers.cpython-310.pyc | Bin 6465 -> 6470 bytes .../rich/__pycache__/control.cpython-310.pyc | Bin 8138 -> 8138 bytes .../default_styles.cpython-310.pyc | Bin 6177 -> 6276 bytes .../rich/__pycache__/diagnose.cpython-310.pyc | Bin 1200 -> 1200 bytes .../rich/__pycache__/emoji.cpython-310.pyc | Bin 3246 -> 3246 bytes .../rich/__pycache__/errors.cpython-310.pyc | Bin 1506 -> 1506 bytes .../__pycache__/file_proxy.cpython-310.pyc | Bin 2239 -> 2379 bytes .../rich/__pycache__/filesize.cpython-310.pyc | Bin 2595 -> 2597 bytes .../__pycache__/highlighter.cpython-310.pyc | Bin 8039 -> 8040 bytes .../rich/__pycache__/json.cpython-310.pyc | Bin 4726 -> 4710 bytes .../rich/__pycache__/jupyter.cpython-310.pyc | Bin 3978 -> 3978 bytes .../rich/__pycache__/layout.cpython-310.pyc | Bin 14665 -> 14626 bytes .../rich/__pycache__/live.cpython-310.pyc | Bin 11603 -> 11655 bytes .../__pycache__/live_render.cpython-310.pyc | Bin 3381 -> 3381 bytes .../rich/__pycache__/logging.cpython-310.pyc | Bin 9752 -> 10305 bytes .../rich/__pycache__/markup.cpython-310.pyc | Bin 5920 -> 6135 bytes .../rich/__pycache__/measure.cpython-310.pyc | Bin 5055 -> 5055 bytes .../rich/__pycache__/padding.cpython-310.pyc | Bin 4461 -> 4404 bytes .../rich/__pycache__/pager.cpython-310.pyc | Bin 1455 -> 1455 bytes .../rich/__pycache__/palette.cpython-310.pyc | Bin 3687 -> 3687 bytes .../rich/__pycache__/panel.cpython-310.pyc | Bin 6398 -> 7928 bytes .../rich/__pycache__/pretty.cpython-310.pyc | Bin 27382 -> 27792 bytes .../rich/__pycache__/progress.cpython-310.pyc | Bin 53881 -> 54530 bytes .../__pycache__/progress_bar.cpython-310.pyc | Bin 6886 -> 6890 bytes .../rich/__pycache__/prompt.cpython-310.pyc | Bin 11280 -> 12176 bytes .../rich/__pycache__/protocol.cpython-310.pyc | Bin 1331 -> 1331 bytes .../rich/__pycache__/region.cpython-310.pyc | Bin 506 -> 506 bytes .../rich/__pycache__/repr.cpython-310.pyc | Bin 4094 -> 4075 bytes .../rich/__pycache__/rule.cpython-310.pyc | Bin 4288 -> 3922 bytes .../rich/__pycache__/scope.cpython-310.pyc | Bin 2967 -> 2968 bytes .../rich/__pycache__/screen.cpython-310.pyc | Bin 1858 -> 1858 bytes .../rich/__pycache__/segment.cpython-310.pyc | Bin 20736 -> 21192 bytes .../rich/__pycache__/spinner.cpython-310.pyc | Bin 4396 -> 4392 bytes .../rich/__pycache__/status.cpython-310.pyc | Bin 4572 -> 4572 bytes .../rich/__pycache__/style.cpython-310.pyc | Bin 20768 -> 21307 bytes .../rich/__pycache__/styled.cpython-310.pyc | Bin 1742 -> 1742 bytes .../rich/__pycache__/syntax.cpython-310.pyc | Bin 25341 -> 26147 bytes .../rich/__pycache__/table.cpython-310.pyc | Bin 29708 -> 30173 bytes .../terminal_theme.cpython-310.pyc | Bin 2995 -> 2995 bytes .../rich/__pycache__/text.cpython-310.pyc | Bin 39399 -> 41770 bytes .../rich/__pycache__/theme.cpython-310.pyc | Bin 4679 -> 4811 bytes .../rich/__pycache__/themes.cpython-310.pyc | Bin 272 -> 272 bytes .../__pycache__/traceback.cpython-310.pyc | Bin 19628 -> 22642 bytes .../rich/__pycache__/tree.cpython-310.pyc | Bin 7313 -> 7620 bytes .../pip/_vendor/rich/_cell_widths.py | 367 +- .../pip/_vendor/rich/_export_format.py | 6 +- .../site-packages/pip/_vendor/rich/_fileno.py | 24 + .../pip/_vendor/rich/_inspect.py | 2 - .../pip/_vendor/rich/_null_file.py | 69 + .../site-packages/pip/_vendor/rich/_ratio.py | 1 - .../pip/_vendor/rich/_win32_console.py | 7 +- .../pip/_vendor/rich/_windows.py | 1 - .../site-packages/pip/_vendor/rich/_wrap.py | 73 +- .../site-packages/pip/_vendor/rich/align.py | 5 +- .../site-packages/pip/_vendor/rich/ansi.py | 6 +- .../Lib/site-packages/pip/_vendor/rich/bar.py | 1 - .../Lib/site-packages/pip/_vendor/rich/box.py | 347 +- .../site-packages/pip/_vendor/rich/cells.py | 108 +- .../site-packages/pip/_vendor/rich/color.py | 26 +- .../site-packages/pip/_vendor/rich/console.py | 213 +- .../pip/_vendor/rich/containers.py | 8 +- .../pip/_vendor/rich/default_styles.py | 13 +- .../pip/_vendor/rich/file_proxy.py | 5 +- .../pip/_vendor/rich/filesize.py | 5 +- .../pip/_vendor/rich/highlighter.py | 4 +- .../site-packages/pip/_vendor/rich/json.py | 9 +- .../site-packages/pip/_vendor/rich/layout.py | 7 +- .../site-packages/pip/_vendor/rich/live.py | 6 +- .../pip/_vendor/rich/live_render.py | 1 - .../site-packages/pip/_vendor/rich/logging.py | 31 +- .../site-packages/pip/_vendor/rich/markup.py | 7 +- .../site-packages/pip/_vendor/rich/padding.py | 10 +- .../site-packages/pip/_vendor/rich/panel.py | 87 +- .../site-packages/pip/_vendor/rich/pretty.py | 212 +- .../pip/_vendor/rich/progress.py | 70 +- .../pip/_vendor/rich/progress_bar.py | 5 +- .../site-packages/pip/_vendor/rich/prompt.py | 34 +- .../site-packages/pip/_vendor/rich/py.typed | 0 .../site-packages/pip/_vendor/rich/repr.py | 13 +- .../site-packages/pip/_vendor/rich/rule.py | 6 +- .../site-packages/pip/_vendor/rich/scope.py | 2 +- .../site-packages/pip/_vendor/rich/segment.py | 55 +- .../site-packages/pip/_vendor/rich/spinner.py | 24 +- .../site-packages/pip/_vendor/rich/status.py | 1 - .../site-packages/pip/_vendor/rich/style.py | 29 +- .../site-packages/pip/_vendor/rich/syntax.py | 64 +- .../site-packages/pip/_vendor/rich/table.py | 33 +- .../site-packages/pip/_vendor/rich/text.py | 167 +- .../site-packages/pip/_vendor/rich/theme.py | 9 +- .../pip/_vendor/rich/traceback.py | 248 +- .../site-packages/pip/_vendor/rich/tree.py | 26 +- venv/Lib/site-packages/pip/_vendor/six.py | 998 - .../pip/_vendor/tenacity/__init__.py | 517 - .../__pycache__/__init__.cpython-310.pyc | Bin 16353 -> 0 bytes .../__pycache__/_asyncio.cpython-310.pyc | Bin 2593 -> 0 bytes .../__pycache__/_utils.cpython-310.pyc | Bin 1206 -> 0 bytes .../__pycache__/after.cpython-310.pyc | Bin 1210 -> 0 bytes .../__pycache__/before.cpython-310.pyc | Bin 1088 -> 0 bytes .../__pycache__/before_sleep.cpython-310.pyc | Bin 1390 -> 0 bytes .../tenacity/__pycache__/nap.cpython-310.pyc | Bin 1178 -> 0 bytes .../__pycache__/retry.cpython-310.pyc | Bin 8408 -> 0 bytes .../tenacity/__pycache__/stop.cpython-310.pyc | Bin 3996 -> 0 bytes .../__pycache__/tornadoweb.cpython-310.pyc | Bin 1743 -> 0 bytes .../tenacity/__pycache__/wait.cpython-310.pyc | Bin 7940 -> 0 bytes .../pip/_vendor/tenacity/_asyncio.py | 92 - .../pip/_vendor/tenacity/_utils.py | 68 - .../pip/_vendor/tenacity/after.py | 46 - .../pip/_vendor/tenacity/before.py | 41 - .../pip/_vendor/tenacity/before_sleep.py | 58 - .../site-packages/pip/_vendor/tenacity/nap.py | 43 - .../pip/_vendor/tenacity/retry.py | 213 - .../pip/_vendor/tenacity/stop.py | 96 - .../pip/_vendor/tenacity/tornadoweb.py | 59 - .../pip/_vendor/tenacity/wait.py | 191 - .../pip/_vendor/tomli/__init__.py | 5 +- .../__pycache__/__init__.cpython-310.pyc | Bin 334 -> 304 bytes .../tomli/__pycache__/_parser.cpython-310.pyc | Bin 17048 -> 18578 bytes .../tomli/__pycache__/_re.cpython-310.pyc | Bin 2880 -> 2974 bytes .../tomli/__pycache__/_types.cpython-310.pyc | Bin 304 -> 304 bytes .../pip/_vendor/tomli/_parser.py | 237 +- .../site-packages/pip/_vendor/tomli/_re.py | 15 +- .../site-packages/pip/_vendor/tomli/py.typed | 1 + .../pip/_vendor/truststore/__init__.py | 36 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 948 bytes .../__pycache__/_api.cpython-310.pyc | Bin 0 -> 10381 bytes .../__pycache__/_macos.cpython-310.pyc | Bin 0 -> 10079 bytes .../__pycache__/_openssl.cpython-310.pyc | Bin 0 -> 1461 bytes .../_ssl_constants.cpython-310.pyc | Bin 0 -> 775 bytes .../__pycache__/_windows.cpython-310.pyc | Bin 0 -> 10555 bytes .../pip/_vendor/truststore/_api.py | 316 + .../pip/_vendor/truststore/_macos.py | 571 + .../pip/_vendor/truststore/_openssl.py | 66 + .../pip/_vendor/truststore/_ssl_constants.py | 31 + .../pip/_vendor/truststore/_windows.py | 567 + .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/typing_extensions.py | 2688 ++- .../pip/_vendor/urllib3/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 2168 -> 2488 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 10842 -> 11333 bytes .../__pycache__/_version.cpython-310.pyc | Bin 193 -> 193 bytes .../__pycache__/connection.cpython-310.pyc | Bin 13622 -> 13688 bytes .../connectionpool.cpython-310.pyc | Bin 25384 -> 25922 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 10973 -> 10973 bytes .../__pycache__/fields.cpython-310.pyc | Bin 8164 -> 8164 bytes .../__pycache__/filepost.cpython-310.pyc | Bin 2729 -> 2729 bytes .../__pycache__/poolmanager.cpython-310.pyc | Bin 15198 -> 15139 bytes .../__pycache__/request.cpython-310.pyc | Bin 5605 -> 6361 bytes .../__pycache__/response.cpython-310.pyc | Bin 20853 -> 22495 bytes .../pip/_vendor/urllib3/_collections.py | 18 + .../pip/_vendor/urllib3/_version.py | 2 +- .../pip/_vendor/urllib3/connection.py | 9 +- .../pip/_vendor/urllib3/connectionpool.py | 54 +- .../__pycache__/__init__.cpython-310.pyc | Bin 178 -> 178 bytes .../_appengine_environ.cpython-310.pyc | Bin 1358 -> 1358 bytes .../__pycache__/appengine.cpython-310.pyc | Bin 8174 -> 8175 bytes .../__pycache__/ntlmpool.cpython-310.pyc | Bin 3613 -> 3602 bytes .../__pycache__/pyopenssl.cpython-310.pyc | Bin 15517 -> 15790 bytes .../securetransport.cpython-310.pyc | Bin 21920 -> 21917 bytes .../contrib/__pycache__/socks.cpython-310.pyc | Bin 5580 -> 5580 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 195 -> 195 bytes .../__pycache__/bindings.cpython-310.pyc | Bin 10691 -> 10691 bytes .../__pycache__/low_level.cpython-310.pyc | Bin 9078 -> 9078 bytes .../pip/_vendor/urllib3/contrib/appengine.py | 2 +- .../pip/_vendor/urllib3/contrib/ntlmpool.py | 4 +- .../pip/_vendor/urllib3/contrib/pyopenssl.py | 16 +- .../urllib3/contrib/securetransport.py | 3 +- .../__pycache__/__init__.cpython-310.pyc | Bin 179 -> 179 bytes .../packages/__pycache__/six.cpython-310.pyc | Bin 27639 -> 27639 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 189 -> 189 bytes .../__pycache__/makefile.cpython-310.pyc | Bin 1289 -> 1289 bytes .../weakref_finalize.cpython-310.pyc | Bin 0 -> 4887 bytes .../packages/backports/weakref_finalize.py | 155 + .../pip/_vendor/urllib3/poolmanager.py | 9 +- .../pip/_vendor/urllib3/request.py | 21 + .../pip/_vendor/urllib3/response.py | 67 +- .../util/__pycache__/__init__.cpython-310.pyc | Bin 1088 -> 1088 bytes .../__pycache__/connection.cpython-310.pyc | Bin 3416 -> 3416 bytes .../util/__pycache__/proxy.cpython-310.pyc | Bin 1323 -> 1323 bytes .../util/__pycache__/queue.cpython-310.pyc | Bin 1043 -> 1043 bytes .../util/__pycache__/request.cpython-310.pyc | Bin 3350 -> 3350 bytes .../util/__pycache__/response.cpython-310.pyc | Bin 2336 -> 2336 bytes .../util/__pycache__/retry.cpython-310.pyc | Bin 16121 -> 16163 bytes .../util/__pycache__/ssl_.cpython-310.pyc | Bin 11290 -> 11532 bytes .../ssl_match_hostname.cpython-310.pyc | Bin 3240 -> 3240 bytes .../__pycache__/ssltransport.cpython-310.pyc | Bin 7378 -> 7378 bytes .../util/__pycache__/timeout.cpython-310.pyc | Bin 8920 -> 9123 bytes .../util/__pycache__/url.cpython-310.pyc | Bin 10676 -> 10698 bytes .../util/__pycache__/wait.cpython-310.pyc | Bin 3072 -> 3072 bytes .../pip/_vendor/urllib3/util/retry.py | 6 +- .../pip/_vendor/urllib3/util/ssl_.py | 17 +- .../pip/_vendor/urllib3/util/timeout.py | 9 +- .../pip/_vendor/urllib3/util/url.py | 6 +- venv/Lib/site-packages/pip/_vendor/vendor.txt | 41 +- .../pip/_vendor/webencodings/__init__.py | 342 - .../__pycache__/__init__.cpython-310.pyc | Bin 9725 -> 0 bytes .../__pycache__/labels.cpython-310.pyc | Bin 5215 -> 0 bytes .../__pycache__/mklabels.cpython-310.pyc | Bin 1920 -> 0 bytes .../__pycache__/tests.cpython-310.pyc | Bin 5022 -> 0 bytes .../x_user_defined.cpython-310.pyc | Bin 2571 -> 0 bytes .../pip/_vendor/webencodings/labels.py | 231 - .../pip/_vendor/webencodings/mklabels.py | 59 - .../pip/_vendor/webencodings/tests.py | 153 - .../_vendor/webencodings/x_user_defined.py | 325 - .../python_dotenv-1.0.1.dist-info/INSTALLER | 1 + .../python_dotenv-1.0.1.dist-info/LICENSE | 27 + .../python_dotenv-1.0.1.dist-info/METADATA | 692 + .../python_dotenv-1.0.1.dist-info/RECORD | 25 + .../python_dotenv-1.0.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../top_level.txt | 1 + .../websockets-15.0.1.dist-info/INSTALLER | 1 + .../websockets-15.0.1.dist-info/LICENSE | 24 + .../websockets-15.0.1.dist-info/METADATA | 179 + .../websockets-15.0.1.dist-info/RECORD | 107 + .../websockets-15.0.1.dist-info/REQUESTED | 0 .../websockets-15.0.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../websockets-15.0.1.dist-info/top_level.txt | 1 + venv/Lib/site-packages/websockets/__init__.py | 236 + venv/Lib/site-packages/websockets/__main__.py | 5 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 3772 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 237 bytes .../__pycache__/auth.cpython-310.pyc | Bin 0 -> 606 bytes .../__pycache__/cli.cpython-310.pyc | Bin 0 -> 4854 bytes .../__pycache__/client.cpython-310.pyc | Bin 0 -> 11546 bytes .../__pycache__/connection.cpython-310.pyc | Bin 0 -> 480 bytes .../datastructures.cpython-310.pyc | Bin 0 -> 7088 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 14785 bytes .../__pycache__/frames.cpython-310.pyc | Bin 0 -> 10089 bytes .../__pycache__/headers.cpython-310.pyc | Bin 0 -> 13608 bytes .../__pycache__/http.cpython-310.pyc | Bin 0 -> 720 bytes .../__pycache__/http11.cpython-310.pyc | Bin 0 -> 10465 bytes .../__pycache__/imports.cpython-310.pyc | Bin 0 -> 2689 bytes .../__pycache__/protocol.cpython-310.pyc | Bin 0 -> 16880 bytes .../__pycache__/server.cpython-310.pyc | Bin 0 -> 17102 bytes .../__pycache__/streams.cpython-310.pyc | Bin 0 -> 4241 bytes .../__pycache__/typing.cpython-310.pyc | Bin 0 -> 862 bytes .../__pycache__/uri.cpython-310.pyc | Bin 0 -> 5290 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 1490 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 1996 bytes .../websockets/asyncio/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 169 bytes .../__pycache__/async_timeout.cpython-310.pyc | Bin 0 -> 7455 bytes .../__pycache__/client.cpython-310.pyc | Bin 0 -> 23619 bytes .../__pycache__/compatibility.cpython-310.pyc | Bin 0 -> 809 bytes .../__pycache__/connection.cpython-310.pyc | Bin 0 -> 32833 bytes .../__pycache__/messages.cpython-310.pyc | Bin 0 -> 9352 bytes .../__pycache__/router.cpython-310.pyc | Bin 0 -> 6528 bytes .../__pycache__/server.cpython-310.pyc | Bin 0 -> 29971 bytes .../websockets/asyncio/async_timeout.py | 282 + .../websockets/asyncio/client.py | 820 + .../websockets/asyncio/compatibility.py | 30 + .../websockets/asyncio/connection.py | 1237 ++ .../websockets/asyncio/messages.py | 314 + .../websockets/asyncio/router.py | 198 + .../websockets/asyncio/server.py | 981 + venv/Lib/site-packages/websockets/auth.py | 18 + venv/Lib/site-packages/websockets/cli.py | 178 + venv/Lib/site-packages/websockets/client.py | 389 + .../site-packages/websockets/connection.py | 12 + .../websockets/datastructures.py | 187 + .../site-packages/websockets/exceptions.py | 473 + .../websockets/extensions/__init__.py | 4 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 273 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 3702 bytes .../permessage_deflate.cpython-310.pyc | Bin 0 -> 13473 bytes .../websockets/extensions/base.py | 123 + .../extensions/permessage_deflate.py | 697 + venv/Lib/site-packages/websockets/frames.py | 430 + venv/Lib/site-packages/websockets/headers.py | 586 + venv/Lib/site-packages/websockets/http.py | 20 + venv/Lib/site-packages/websockets/http11.py | 427 + venv/Lib/site-packages/websockets/imports.py | 100 + .../websockets/legacy/__init__.py | 11 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 406 bytes .../legacy/__pycache__/auth.cpython-310.pyc | Bin 0 -> 5884 bytes .../legacy/__pycache__/client.cpython-310.pyc | Bin 0 -> 19861 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 2702 bytes .../__pycache__/framing.cpython-310.pyc | Bin 0 -> 5952 bytes .../__pycache__/handshake.cpython-310.pyc | Bin 0 -> 4707 bytes .../legacy/__pycache__/http.cpython-310.pyc | Bin 0 -> 5181 bytes .../__pycache__/protocol.cpython-310.pyc | Bin 0 -> 41778 bytes .../legacy/__pycache__/server.cpython-310.pyc | Bin 0 -> 34644 bytes .../site-packages/websockets/legacy/auth.py | 190 + .../site-packages/websockets/legacy/client.py | 705 + .../websockets/legacy/exceptions.py | 71 + .../websockets/legacy/framing.py | 225 + .../websockets/legacy/handshake.py | 158 + .../site-packages/websockets/legacy/http.py | 201 + .../websockets/legacy/protocol.py | 1641 ++ .../site-packages/websockets/legacy/server.py | 1191 ++ venv/Lib/site-packages/websockets/protocol.py | 758 + venv/Lib/site-packages/websockets/py.typed | 0 venv/Lib/site-packages/websockets/server.py | 587 + venv/Lib/site-packages/websockets/speedups.c | 222 + .../websockets/speedups.cp310-win_amd64.pyd | Bin 0 -> 11776 bytes .../Lib/site-packages/websockets/speedups.pyi | 1 + venv/Lib/site-packages/websockets/streams.py | 151 + .../site-packages/websockets/sync/__init__.py | 0 .../sync/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 166 bytes .../sync/__pycache__/client.cpython-310.pyc | Bin 0 -> 17098 bytes .../__pycache__/connection.cpython-310.pyc | Bin 0 -> 26898 bytes .../sync/__pycache__/messages.cpython-310.pyc | Bin 0 -> 9119 bytes .../sync/__pycache__/router.cpython-310.pyc | Bin 0 -> 6324 bytes .../sync/__pycache__/server.cpython-310.pyc | Bin 0 -> 21747 bytes .../sync/__pycache__/utils.cpython-310.pyc | Bin 0 -> 1427 bytes .../site-packages/websockets/sync/client.py | 648 + .../websockets/sync/connection.py | 1072 + .../site-packages/websockets/sync/messages.py | 345 + .../site-packages/websockets/sync/router.py | 192 + .../site-packages/websockets/sync/server.py | 763 + .../site-packages/websockets/sync/utils.py | 45 + venv/Lib/site-packages/websockets/typing.py | 74 + venv/Lib/site-packages/websockets/uri.py | 225 + venv/Lib/site-packages/websockets/utils.py | 51 + venv/Lib/site-packages/websockets/version.py | 92 + venv/Scripts/dotenv.exe | Bin 0 -> 107884 bytes venv/Scripts/pip.exe | Bin 107893 -> 108405 bytes venv/Scripts/pip3.10.exe | Bin 107893 -> 108405 bytes venv/Scripts/pip3.exe | Bin 107893 -> 108405 bytes venv/Scripts/websockets.exe | Bin 0 -> 108395 bytes 1138 files changed, 55771 insertions(+), 77901 deletions(-) create mode 100644 .env create mode 100644 modules/data/negative_prompt_categories.py create mode 100644 modules/data/prompt_categories.py create mode 100644 modules/data/prompt_translations.py create mode 100644 modules/styles/__pycache__/style_constants.cpython-310.pyc create mode 100644 modules/styles/style_constants.py create mode 100644 modules/windows/console_window.py create mode 100644 modules/windows/negative_prompt_window.py create mode 100644 modules/windows/prompt_window.py create mode 100644 resources/icons/add.svg create mode 100644 resources/icons/close.svg create mode 100644 resources/icons/delete.svg create mode 100644 resources/icons/generate.svg create mode 100644 resources/icons/home.svg create mode 100644 resources/icons/image.svg create mode 100644 resources/icons/models.svg create mode 100644 resources/icons/refresh.svg create mode 100644 resources/icons/save.svg create mode 100644 resources/icons/settings.svg create mode 100644 resources/icons/success.svg rename venv/Lib/site-packages/{pip-22.2.1.dist-info => dotenv-0.9.9.dist-info}/INSTALLER (100%) create mode 100644 venv/Lib/site-packages/dotenv-0.9.9.dist-info/LICENSE create mode 100644 venv/Lib/site-packages/dotenv-0.9.9.dist-info/METADATA create mode 100644 venv/Lib/site-packages/dotenv-0.9.9.dist-info/RECORD rename venv/Lib/site-packages/{pip-22.2.1.dist-info => dotenv-0.9.9.dist-info}/REQUESTED (100%) create mode 100644 venv/Lib/site-packages/dotenv-0.9.9.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/dotenv-0.9.9.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/dotenv/__init__.py create mode 100644 venv/Lib/site-packages/dotenv/__main__.py create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/main.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/__pycache__/version.cpython-310.pyc create mode 100644 venv/Lib/site-packages/dotenv/cli.py create mode 100644 venv/Lib/site-packages/dotenv/ipython.py create mode 100644 venv/Lib/site-packages/dotenv/main.py create mode 100644 venv/Lib/site-packages/dotenv/parser.py create mode 100644 venv/Lib/site-packages/dotenv/py.typed create mode 100644 venv/Lib/site-packages/dotenv/variables.py create mode 100644 venv/Lib/site-packages/dotenv/version.py delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/RECORD create mode 100644 venv/Lib/site-packages/pip-25.0.1.dist-info/AUTHORS.txt rename venv/Lib/site-packages/{pip-22.2.1.dist-info/top_level.txt => pip-25.0.1.dist-info/INSTALLER} (100%) rename venv/Lib/site-packages/{pip-22.2.1.dist-info => pip-25.0.1.dist-info}/LICENSE.txt (100%) rename venv/Lib/site-packages/{pip-22.2.1.dist-info => pip-25.0.1.dist-info}/METADATA (70%) create mode 100644 venv/Lib/site-packages/pip-25.0.1.dist-info/RECORD rename venv/Lib/site-packages/{pip/_vendor/chardet/cli/__init__.py => pip-25.0.1.dist-info/REQUESTED} (100%) rename venv/Lib/site-packages/{pip-22.2.1.dist-info => pip-25.0.1.dist-info}/WHEEL (65%) rename venv/Lib/site-packages/{pip-22.2.1.dist-info => pip-25.0.1.dist-info}/entry_points.txt (70%) create mode 100644 venv/Lib/site-packages/pip-25.0.1.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/index_command.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/distutils_args.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/encoding.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/models.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/retry.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py rename venv/Lib/site-packages/pip/_vendor/{chardet/metadata/__init__.py => cachecontrol/py.typed} (100%) create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/py.typed delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5freq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/enums.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escsm.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/johabfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/johabprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/utf1632prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/py.typed delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_elffile.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_parser.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/licenses/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/licenses/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/licenses/__pycache__/_spdx.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/licenses/_spdx.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/metadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/py.typed delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/build.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/check.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/colorlog.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/dirtools.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/envbuild.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/meta.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/wrappers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/common.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/core.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/helpers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/results.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/testing.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/unicode.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-310.pyc rename venv/Lib/site-packages/pip/_vendor/{pep517/in_process => pyproject_hooks/_in_process}/_in_process.py (57%) create mode 100644 venv/Lib/site-packages/pip/_vendor/pyproject_hooks/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_fileno.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_null_file.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/py.typed delete mode 100644 venv/Lib/site-packages/pip/_vendor/six.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_utils.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/after.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/nap.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/retry.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/stop.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/wait.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_macos.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/_windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/truststore/py.typed create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-310.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/labels.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/tests.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/LICENSE create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/METADATA create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/RECORD create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/python_dotenv-1.0.1.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/LICENSE create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/METADATA create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/RECORD create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/REQUESTED create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/websockets-15.0.1.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/websockets/__init__.py create mode 100644 venv/Lib/site-packages/websockets/__main__.py create mode 100644 venv/Lib/site-packages/websockets/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/__main__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/auth.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/cli.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/client.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/connection.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/datastructures.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/exceptions.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/frames.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/headers.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/http.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/http11.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/imports.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/protocol.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/server.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/streams.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/typing.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/uri.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/utils.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/__pycache__/version.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__init__.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/async_timeout.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/client.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/compatibility.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/connection.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/messages.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/router.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/__pycache__/server.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/asyncio/async_timeout.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/client.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/compatibility.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/connection.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/messages.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/router.py create mode 100644 venv/Lib/site-packages/websockets/asyncio/server.py create mode 100644 venv/Lib/site-packages/websockets/auth.py create mode 100644 venv/Lib/site-packages/websockets/cli.py create mode 100644 venv/Lib/site-packages/websockets/client.py create mode 100644 venv/Lib/site-packages/websockets/connection.py create mode 100644 venv/Lib/site-packages/websockets/datastructures.py create mode 100644 venv/Lib/site-packages/websockets/exceptions.py create mode 100644 venv/Lib/site-packages/websockets/extensions/__init__.py create mode 100644 venv/Lib/site-packages/websockets/extensions/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/extensions/__pycache__/base.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/extensions/__pycache__/permessage_deflate.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/extensions/base.py create mode 100644 venv/Lib/site-packages/websockets/extensions/permessage_deflate.py create mode 100644 venv/Lib/site-packages/websockets/frames.py create mode 100644 venv/Lib/site-packages/websockets/headers.py create mode 100644 venv/Lib/site-packages/websockets/http.py create mode 100644 venv/Lib/site-packages/websockets/http11.py create mode 100644 venv/Lib/site-packages/websockets/imports.py create mode 100644 venv/Lib/site-packages/websockets/legacy/__init__.py create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/auth.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/client.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/exceptions.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/framing.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/handshake.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/http.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/protocol.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/__pycache__/server.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/legacy/auth.py create mode 100644 venv/Lib/site-packages/websockets/legacy/client.py create mode 100644 venv/Lib/site-packages/websockets/legacy/exceptions.py create mode 100644 venv/Lib/site-packages/websockets/legacy/framing.py create mode 100644 venv/Lib/site-packages/websockets/legacy/handshake.py create mode 100644 venv/Lib/site-packages/websockets/legacy/http.py create mode 100644 venv/Lib/site-packages/websockets/legacy/protocol.py create mode 100644 venv/Lib/site-packages/websockets/legacy/server.py create mode 100644 venv/Lib/site-packages/websockets/protocol.py create mode 100644 venv/Lib/site-packages/websockets/py.typed create mode 100644 venv/Lib/site-packages/websockets/server.py create mode 100644 venv/Lib/site-packages/websockets/speedups.c create mode 100644 venv/Lib/site-packages/websockets/speedups.cp310-win_amd64.pyd create mode 100644 venv/Lib/site-packages/websockets/speedups.pyi create mode 100644 venv/Lib/site-packages/websockets/streams.py create mode 100644 venv/Lib/site-packages/websockets/sync/__init__.py create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/__init__.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/client.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/connection.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/messages.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/router.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/server.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/__pycache__/utils.cpython-310.pyc create mode 100644 venv/Lib/site-packages/websockets/sync/client.py create mode 100644 venv/Lib/site-packages/websockets/sync/connection.py create mode 100644 venv/Lib/site-packages/websockets/sync/messages.py create mode 100644 venv/Lib/site-packages/websockets/sync/router.py create mode 100644 venv/Lib/site-packages/websockets/sync/server.py create mode 100644 venv/Lib/site-packages/websockets/sync/utils.py create mode 100644 venv/Lib/site-packages/websockets/typing.py create mode 100644 venv/Lib/site-packages/websockets/uri.py create mode 100644 venv/Lib/site-packages/websockets/utils.py create mode 100644 venv/Lib/site-packages/websockets/version.py create mode 100644 venv/Scripts/dotenv.exe create mode 100644 venv/Scripts/websockets.exe diff --git a/.env b/.env new file mode 100644 index 0000000..2c7e668 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +SD_API_URL=http://localhost:7860 \ No newline at end of file diff --git a/README.md b/README.md index b87ae058c445ac0fb85fb45a35c80ff08c0ecd92..a8a569cdf79a3540acfedf56dbf6ff01631bf71a 100644 GIT binary patch literal 2384 zcma);+fNfw5XR@>Jel|c4;mBWD$j*d3N58wT0o5ffj|r|BwPwg6)Hjz_~+H%H>b-2 zr9zs$bj~?5-+Xi1zkkLou}$mQp6%PQ9rACCg%_-eyB$)zAnFNSdroBWWQkhq3F`=2 zDxuDO274)17OkY?I3?EpN{VHct5D3SNuSd-DND~w4nrli!2}wOHB2B|Q zr(2w8@LY8p(m#e=dP?{vOI7ZP2~n9h`CCW!xQD_leXr3aFPdnW1xJyy^W0^lj>foB zLOSL4#BlU1`Yj#rSgC`h*!NZ(m;CHpUnU>x&VEXKQgqaB@UPwQ7daktJn~z72vNrG zB=Jb>6(>{oya`jYAQS^l?&7n8_X}=89M?R4yQbehS$1wmF8M}o_0ZKO>y%^4ydxw% zJ7rJJCiulYM`YqYcH8VbL3+*e!p=ND4|#Ucdcye$&gFSru!Dg-E^wxUrl?mwwb_+C z@tpQYKQcB-&c<8!xeQAg6D1gE!oec4xv=6qilG!P#aNbsWZe*UPVuq_AF=uh_?Osk zeC%@1--P45&qmuB%=S#cSclycaMMOphjV*8#WESpwc_g+cEz60zDwG&^V`&C8*V#9 zqlb;{2lYr-)VAf?4#0BB?m?!eoT#RzdXu%Q&w~x|2X$6u0dqw{~%k%p96G^+jqPghBWVTE&OSE-Kj!{dC&#F;;H!L z9tmI!MjyQr%H~PF=g~xvKt`)ok?+@_1hM zHkk}N7Q6Be6JdiKYTVRptXS1@n_M~e+?97Vt60@$toQ);v3_2Fcb=+IzdtM3`ky-C6Tg{UfW9`yAC+)9lgI9fs&`A31>uW!*S@Tt5(x$V-CN z3J9`^eY^i_*1RNA>htPs6>#TWPqRv219?Tn39=mCBU@r`gLTd1r_6;T*lXJl?{AtE z1>&9XU2=#QJ)Z#T`I;P;tlgClvMuCqK;7yyDwbo$Y3`QrR+C)c3N8LunB{ptU&mVP TG8wEZjWw0ADx3cRpVU9~ literal 16 XcmezWPnki1A(5eop@e~#fr|kEET#jW diff --git a/main.py b/main.py index 99298a3..7718820 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import sys import json import base64 import requests +import os from time import sleep from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, @@ -12,8 +13,12 @@ from PyQt6.QtGui import QPixmap, QImage, QAction, QFontDatabase, QFont from PIL import Image from io import BytesIO from pathlib import Path +from dotenv import load_dotenv -# Импортируем новые модули +# Загружаем переменные окружения +load_dotenv() + +# Импортируем модули from modules.console_window import ConsoleWindow from modules.model_manager import ModelManager from modules.sampler_manager import SamplerManager @@ -74,17 +79,22 @@ class MainWindow(BaseWindow): super().__init__() self.setWindowTitle("Stable Diffusion UI") self.setMinimumSize(1200, 800) + + # Получаем URL API из переменных окружения + self.api_url = os.getenv('SD_API_URL', 'http://localhost:3000') + + # Инициализируем менеджеры + self.model_manager = ModelManager(api_url=self.api_url) + self.sampler_manager = SamplerManager(api_url=self.api_url) + self.size_preset_manager = SizePresetManager() + + # Инициализируем окна + self.prompt_window = PromptWindow() + self.negative_prompt_window = NegativePromptWindow() + self.console_window = ConsoleWindow() + self.setup_ui() - def create_horizontal_layout(self): - """Создает горизонтальный layout для главного окна""" - central_widget = QWidget() - self.setCentralWidget(central_widget) - layout = QHBoxLayout(central_widget) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - return layout - def setup_ui(self): # Загружаем шрифт font_path = Path("resources/fonts/InterVariable.ttf") @@ -96,20 +106,59 @@ class MainWindow(BaseWindow): app_font = QFont(font_family) QApplication.setFont(app_font) - # Создаем горизонтальный layout - layout = self.create_horizontal_layout() + # Создаем центральный виджет + central_widget = QWidget() + self.setCentralWidget(central_widget) + main_layout = QVBoxLayout(central_widget) + main_layout.setContentsMargins(0, 0, 0, 0) + main_layout.setSpacing(0) + + # Создаем верхнюю панель + top_panel = QHBoxLayout() + + # Кнопки для окон промптов + prompt_btn = QPushButton("Библиотека промптов") + prompt_btn.clicked.connect(self.show_prompt_window) + top_panel.addWidget(prompt_btn) + + negative_prompt_btn = QPushButton("Негативные промпты") + negative_prompt_btn.clicked.connect(self.show_negative_prompt_window) + top_panel.addWidget(negative_prompt_btn) + + # Пресеты разрешения + resolution_combo = QComboBox() + resolution_combo.addItems(self.size_preset_manager.get_preset_names()) + resolution_combo.currentTextChanged.connect(self.on_resolution_changed) + top_panel.addWidget(resolution_combo) + + # Кнопка консоли + console_btn = QPushButton("Консоль") + console_btn.clicked.connect(self.show_console) + top_panel.addWidget(console_btn) + + top_panel.addStretch() + main_layout.addLayout(top_panel) + + # Создаем горизонтальный layout для навигации и контента + content_layout = QHBoxLayout() # Добавляем навигационную панель self.nav_panel = NavigationPanel() - layout.addWidget(self.nav_panel) + content_layout.addWidget(self.nav_panel) # Создаем контейнер для страниц self.page_container = PageContainer() - layout.addWidget(self.page_container) + content_layout.addWidget(self.page_container) + + main_layout.addLayout(content_layout) # Добавляем страницы - self.home_page = HomePage() - self.models_page = ModelsPage() + self.home_page = HomePage( + model_manager=self.model_manager, + sampler_manager=self.sampler_manager, + size_preset_manager=self.size_preset_manager + ) + self.models_page = ModelsPage(self.model_manager) self.settings_page = SettingsPage() self.page_container.add_page("home", self.home_page) @@ -121,7 +170,44 @@ class MainWindow(BaseWindow): # Показываем домашнюю страницу по умолчанию self.page_container.show_page("home") - + + # Загружаем данные + self.load_data() + + def load_data(self): + """Загрузка данных с сервера""" + try: + # Загружаем список моделей + self.model_manager.load_models() + + # Загружаем список сэмплеров + self.sampler_manager.load_samplers() + + # Обновляем интерфейс + self.home_page.update_ui() + self.models_page.update_ui() + + except Exception as e: + self.console_window.log(f"Ошибка загрузки данных: {str(e)}", "ERROR") + + def show_prompt_window(self): + """Показать окно промптов""" + self.prompt_window.show() + + def show_negative_prompt_window(self): + """Показать окно негативных промптов""" + self.negative_prompt_window.show() + + def show_console(self): + """Показать консоль""" + self.console_window.show() + + def on_resolution_changed(self, preset_name: str): + """Обработка изменения пресета разрешения""" + preset = self.size_preset_manager.get_preset(preset_name) + if preset: + self.home_page.set_resolution(preset.width, preset.height) + def switch_page(self, page_name): self.page_container.show_page(page_name) diff --git a/modules/__pycache__/model_manager.cpython-310.pyc b/modules/__pycache__/model_manager.cpython-310.pyc index a4b83e9b3b71f7274074c81c15ac1bf84cce72a5..6c803bdce6ba196257aa4da896c1a49613e37867 100644 GIT binary patch literal 7371 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 Qd%6tFAK)x0VUktpzxosz0ssI2 diff --git a/modules/__pycache__/sampler_manager.cpython-310.pyc b/modules/__pycache__/sampler_manager.cpython-310.pyc index 68863b4d954a66e378b656ae087e06a25da725b5..8c3ec12ca9abac659f0e0a9adb21781354502665 100644 GIT binary patch literal 5798 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 delta 1395 zcmZ8hO=w(29G`jL`<*X?kYZP<(zV*44aL@?lqN`^1WOg|qCTEGld{R??RMt9=7YCx z>5XG2#@|51Am%5Cm=t&QYKG_+QN`N$?mVt-43AAH3qA)x zQ56$Z)u>L5F0PuS7~j#Rve%J;s(COe#UuLL<6C&HVoH;TEy|?hx^=%ExNf|rA9-3D zoHpiJ9(+lw&tQ5n9l0AcAjdJ>13-UeJlQsIf~C z-ZXlst%2O!w1Co6%I+bIB5fMIpKlu}$BB$hOmt%Ozyn5C4yW8qq=P>*GKslpvezTj z0XNymR4VTv;#@?jTCNAxT{PHxeIsIlkri2~k(=_e5%3<{^ey+Jfr9*M8>6<3(b`Z@ zAa+oU>@L26Zff1s?h-_6+aDdZRnU~Qm+>;HWWpIJg7`{oi@V8s(iPu}-Q-&GMXV2> zcz11Nk`u30pS=3gB=?qD4a)c*KZCwBd~bLeBCFhq{L}(uCF=k6S@Mb&Cm~IW@e>ETS2|)OS8r5 zekYJR4_L)v>HI(@yw&tMtvZiyS}hGCx&uzt9uU%mXmq7oAavdf8v#tQiiGLGxhq2A zvvBwe0Gc*}v)F-?)g1iPIL_-19>GPNhu;xw{b}Vby{MJ3v#$LUPn2#QOEb$4g1V~Y z2Ll`izn%&Z|6YntsnuaBW<~4Y%J%898?uA@Ad6v(cmZ{xw@OUouZPZbG%!rpLhT1k z9jrwU!Q$fZEHK13;s z?L6riLnc$wN>-NMT)hySJbodFo$;wxo&#no+2=5QeUwA#oLOoT*pAoKqHyKl5K`?P G)BXizoQL=T diff --git a/modules/__pycache__/size_preset_manager.cpython-310.pyc b/modules/__pycache__/size_preset_manager.cpython-310.pyc index 7adb455db10b6217b7b25eb90bc267d3f5c6ca76..a139b90364775d7da7ee9dee8f7a036021ef5924 100644 GIT binary patch delta 1943 zcmZuy-ESL35Z~Q9+voFV(m+X?QmceYr%GuOXv&9c5CnLjSd{`ioP;d*cH_7?pVPey zxK@f&9I1eK3HJ(rKpv2yRw)sJ_8kf7A|W2`ng0Qv5HokN<3`!j&dtuu&dmL0XYcpP zA7=9HTuvu23T^ie`}#k^6w~6xX&1 z*ZQna%`sS~xejYx(7s}h^UN|avO8N&&!AzN*S)%B*In0Op?ag~dZD`1v^)#Ljt&JD zZ^Lvi0TINcoS5trA{3!=S|%a^Z+7%n%7m*BBoXS%&91m9g)6|XQ*Vhd@kNt+t6_3g zG?R^0uWBUyz0Ay|P;osO7HYM+eIu^lW-4JBw`YLRUuLnk9LSQ-icM|v(FK^Ugiqe{8{0X;t#gFXcxE)mxv zBJcu`EY+yabb8|X=TV7$r_hrBQ{uyG@&Xu|>T2Cyk+@NgAsGh}CU0$cUfUU#l*lN= zi=eyk==EerQFdw7f1EZZOSmVhJX(ZW*{-*4@p@&=|2KW(eLRL?%Cei*n&7~+9YF|E=G&lhIB>1Hi z90b1x`@wIe;3*jGgA`0a^YAEM54^y@V0avtVY&!u1A={)xJNhXZL-7eu;m!FT^d2Z z%R)9g7bfGFWb=aR=c%c@z5VSA1B?#!O`w16kfdx)-u84d>WaQfr!#G-oS0a>9@ z1vIDt#R_nx50Dt@#yl9DT7^-(0sP>}uoS_;NUZ_?0rszeD;JOKeZ*dmvHzN^G08UR zr-YI_4BJ>@NO>JeWyl?$=ybUu9MM^qmAjyI@k`j&H0fSB9gJR#{s``a?Nz+H!IKxE zZ?KUbh@wRqL`|e07vXb^iPtD&UJf1(JD9^x4P9S*>Ng4^>3-S#l zcvVP5Mq+|62^A!>E~OLus6&TvUD2>dX9~Uzyfk zT~(t(&4R~Ym_yb<%k#JV*mhI^TwhJa-SD3p!=DVY;hxAgU+b>_@_83djoTaKz4uZ8 z85M=>Rk5QQ*%E3agk^+>2u;sbWKGWpz_#=^|6-|8To?a$w-u;+qdy00ZgVvl<5wCj zs#}mYc3xC!4J~gY;4>8ZsudlE)9cqx)0k}9`oJ8B5(y_BZCjl2_0BzoiJdsm@51D9 dv$-*)#tHQ>hT%xm1G!1j1V3bvbf`~ftUpG{cPsz^ diff --git a/modules/data/negative_prompt_categories.py b/modules/data/negative_prompt_categories.py new file mode 100644 index 0000000..8174a06 --- /dev/null +++ b/modules/data/negative_prompt_categories.py @@ -0,0 +1,71 @@ +from enum import Enum, auto +from typing import List, Dict + +class NegativePromptCategory(Enum): + """Категории негативных промптов""" + QUALITY = auto() + ARTIFACTS = auto() + COMPOSITION = auto() + ANATOMY = auto() + STYLE = auto() + +class NegativePromptData: + """Класс для хранения данных о негативном промпте""" + def __init__(self, text: str, description: str = "", weight: float = 1.0): + self.text = text + self.description = description + self.weight = weight + +class NegativePromptCategories: + """Класс для работы с категориями негативных промптов""" + + @staticmethod + def get_prompts() -> Dict[NegativePromptCategory, List[NegativePromptData]]: + """Возвращает словарь с негативными промптами по категориям""" + return { + NegativePromptCategory.QUALITY: [ + NegativePromptData("low quality", "Низкое качество"), + NegativePromptData("blurry", "Размытое изображение"), + NegativePromptData("pixelated", "Пикселизация"), + NegativePromptData("jpeg artifacts", "JPEG артефакты"), + NegativePromptData("compression artifacts", "Артефакты сжатия"), + ], + NegativePromptCategory.ARTIFACTS: [ + NegativePromptData("watermark", "Водяные знаки"), + NegativePromptData("signature", "Подписи"), + NegativePromptData("text", "Текст на изображении"), + NegativePromptData("frame", "Рамки"), + NegativePromptData("duplicate", "Дубликаты элементов"), + ], + NegativePromptCategory.COMPOSITION: [ + NegativePromptData("bad composition", "Плохая композиция"), + NegativePromptData("unbalanced", "Несбалансированная композиция"), + NegativePromptData("cropped", "Обрезанное изображение"), + NegativePromptData("out of frame", "Выход за пределы кадра"), + ], + NegativePromptCategory.ANATOMY: [ + NegativePromptData("bad anatomy", "Неправильная анатомия"), + NegativePromptData("extra limbs", "Лишние конечности"), + NegativePromptData("missing limbs", "Отсутствующие конечности"), + NegativePromptData("deformed", "Деформации"), + NegativePromptData("mutated", "Мутации"), + ], + NegativePromptCategory.STYLE: [ + NegativePromptData("3d render", "3D рендер"), + NegativePromptData("cartoon", "Мультяшный стиль"), + NegativePromptData("painting", "Живопись"), + NegativePromptData("sketch", "Набросок"), + NegativePromptData("anime", "Аниме"), + ], + } + + @staticmethod + def get_category_name(category: NegativePromptCategory) -> str: + """Возвращает название категории на русском""" + return { + NegativePromptCategory.QUALITY: "Качество", + NegativePromptCategory.ARTIFACTS: "Артефакты", + NegativePromptCategory.COMPOSITION: "Композиция", + NegativePromptCategory.ANATOMY: "Анатомия", + NegativePromptCategory.STYLE: "Стиль", + }[category] \ No newline at end of file diff --git a/modules/data/prompt_categories.py b/modules/data/prompt_categories.py new file mode 100644 index 0000000..1a8aa2c --- /dev/null +++ b/modules/data/prompt_categories.py @@ -0,0 +1,86 @@ +from enum import Enum, auto +from typing import List, Dict + +class PromptCategory(Enum): + """Категории промптов""" + STYLE = auto() + LIGHTING = auto() + COMPOSITION = auto() + CAMERA = auto() + COLORS = auto() + MOOD = auto() + QUALITY = auto() + +class PromptData: + """Класс для хранения данных о промпте""" + def __init__(self, text: str, description: str = "", weight: float = 1.0): + self.text = text + self.description = description + self.weight = weight + +class PromptCategories: + """Класс для работы с категориями промптов""" + + @staticmethod + def get_prompts() -> Dict[PromptCategory, List[PromptData]]: + """Возвращает словарь с промптами по категориям""" + return { + PromptCategory.STYLE: [ + PromptData("digital art", "Цифровое искусство"), + PromptData("oil painting", "Масляная живопись"), + PromptData("watercolor", "Акварель"), + PromptData("pencil sketch", "Карандашный набросок"), + PromptData("anime style", "Аниме стиль"), + PromptData("photorealistic", "Фотореалистичный"), + ], + PromptCategory.LIGHTING: [ + PromptData("soft lighting", "Мягкое освещение"), + PromptData("dramatic lighting", "Драматическое освещение"), + PromptData("cinematic lighting", "Кинематографическое освещение"), + PromptData("natural light", "Естественное освещение"), + PromptData("studio lighting", "Студийное освещение"), + ], + PromptCategory.COMPOSITION: [ + PromptData("rule of thirds", "Правило третей"), + PromptData("symmetrical", "Симметричная композиция"), + PromptData("centered composition", "Центральная композиция"), + PromptData("dynamic pose", "Динамичная поза"), + ], + PromptCategory.CAMERA: [ + PromptData("close-up shot", "Крупный план"), + PromptData("wide angle", "Широкий угол"), + PromptData("bokeh", "Боке"), + PromptData("depth of field", "Глубина резкости"), + ], + PromptCategory.COLORS: [ + PromptData("vibrant colors", "Яркие цвета"), + PromptData("pastel colors", "Пастельные цвета"), + PromptData("monochrome", "Монохром"), + PromptData("high contrast", "Высокий контраст"), + ], + PromptCategory.MOOD: [ + PromptData("peaceful", "Умиротворенное"), + PromptData("mysterious", "Таинственное"), + PromptData("energetic", "Энергичное"), + PromptData("melancholic", "Меланхоличное"), + ], + PromptCategory.QUALITY: [ + PromptData("highly detailed", "Высокая детализация"), + PromptData("8k uhd", "Высокое разрешение"), + PromptData("masterpiece", "Шедевр"), + PromptData("best quality", "Лучшее качество"), + ], + } + + @staticmethod + def get_category_name(category: PromptCategory) -> str: + """Возвращает название категории на русском""" + return { + PromptCategory.STYLE: "Стили", + PromptCategory.LIGHTING: "Освещение", + PromptCategory.COMPOSITION: "Композиция", + PromptCategory.CAMERA: "Камера", + PromptCategory.COLORS: "Цвета", + PromptCategory.MOOD: "Настроение", + PromptCategory.QUALITY: "Качество", + }[category] \ No newline at end of file diff --git a/modules/data/prompt_translations.py b/modules/data/prompt_translations.py new file mode 100644 index 0000000..667ba36 --- /dev/null +++ b/modules/data/prompt_translations.py @@ -0,0 +1,86 @@ +from typing import Dict + +class PromptTranslations: + """Класс для работы с переводами промптов""" + + @staticmethod + def get_translations() -> Dict[str, str]: + """Возвращает словарь с переводами промптов""" + return { + # Стили + "digital art": "цифровое искусство", + "oil painting": "масляная живопись", + "watercolor": "акварель", + "pencil sketch": "карандашный набросок", + "anime style": "аниме стиль", + "photorealistic": "фотореалистичный", + + # Освещение + "soft lighting": "мягкое освещение", + "dramatic lighting": "драматическое освещение", + "cinematic lighting": "кинематографическое освещение", + "natural light": "естественное освещение", + "studio lighting": "студийное освещение", + + # Композиция + "rule of thirds": "правило третей", + "symmetrical": "симметричный", + "centered composition": "центральная композиция", + "dynamic pose": "динамичная поза", + + # Камера + "close-up shot": "крупный план", + "wide angle": "широкий угол", + "bokeh": "боке", + "depth of field": "глубина резкости", + + # Цвета + "vibrant colors": "яркие цвета", + "pastel colors": "пастельные цвета", + "monochrome": "монохром", + "high contrast": "высокий контраст", + + # Настроение + "peaceful": "умиротворенный", + "mysterious": "таинственный", + "energetic": "энергичный", + "melancholic": "меланхоличный", + + # Качество + "highly detailed": "высокая детализация", + "8k uhd": "8k uhd", + "masterpiece": "шедевр", + "best quality": "лучшее качество", + + # Негативные промпты + "low quality": "низкое качество", + "blurry": "размытый", + "pixelated": "пикселизированный", + "jpeg artifacts": "jpeg артефакты", + "compression artifacts": "артефакты сжатия", + "watermark": "водяной знак", + "signature": "подпись", + "text": "текст", + "frame": "рамка", + "duplicate": "дубликат", + "bad composition": "плохая композиция", + "unbalanced": "несбалансированный", + "cropped": "обрезанный", + "out of frame": "за пределами кадра", + "bad anatomy": "плохая анатомия", + "extra limbs": "лишние конечности", + "missing limbs": "отсутствующие конечности", + "deformed": "деформированный", + "mutated": "мутированный", + "3d render": "3d рендер", + "cartoon": "мультяшный", + "painting": "живопись", + "sketch": "набросок", + "anime": "аниме", + } + + @staticmethod + def translate(text: str) -> str: + """Переводит промпт на русский язык""" + translations = PromptTranslations.get_translations() + return translations.get(text.lower(), text) \ No newline at end of file diff --git a/modules/model_manager.py b/modules/model_manager.py index a8551e9..bbaea95 100644 --- a/modules/model_manager.py +++ b/modules/model_manager.py @@ -2,6 +2,17 @@ from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QPushButton, QLabel) from PyQt6.QtCore import pyqtSignal import requests +from typing import List, Dict +import os +from dotenv import load_dotenv + +# Загружаем переменные окружения +load_dotenv() + +class Model: + def __init__(self, name: str, title: str = None): + self.name = name + self.title = title or name class ModelManager(QWidget): model_changed = pyqtSignal(str) @@ -9,6 +20,8 @@ class ModelManager(QWidget): def __init__(self, api_url, parent=None): super().__init__(parent) self.api_url = api_url + self.models = [] + self.current_model = None self.setup_ui() self.load_models() @@ -97,33 +110,86 @@ class ModelManager(QWidget): try: response = requests.get(f"{self.api_url}/sdapi/v1/sd-models") if response.status_code == 200: - models = response.json() - current_model = self.model_combo.currentText() + models_data = response.json() + self.models = [ + Model(model.get('title', ''), model.get('model_name', '')) + for model in models_data + ] + # Получаем текущую модель + options_response = requests.get(f"{self.api_url}/sdapi/v1/options") + if options_response.status_code == 200: + current_model_name = options_response.json().get('sd_model_checkpoint') + self.current_model = next( + (model for model in self.models if model.name == current_model_name), + self.models[0] if self.models else None + ) + + # Обновляем UI self.model_combo.clear() - for model in models: - self.model_combo.addItem(model.get('title', '')) + for model in self.models: + self.model_combo.addItem(model.title) + + # Устанавливаем текущую модель + if self.current_model: + index = self.model_combo.findText(self.current_model.title) + if index >= 0: + self.model_combo.setCurrentIndex(index) - # Восстанавливаем выбранную модель, если она всё ещё доступна - index = self.model_combo.findText(current_model) - if index >= 0: - self.model_combo.setCurrentIndex(index) except Exception as e: print(f"Ошибка при загрузке моделей: {str(e)}") + self.models = [] + self.current_model = None - def on_model_changed(self, model_name): + def on_model_changed(self, model_title): """Обработка смены модели""" + model = next( + (m for m in self.models if m.title == model_title), + None + ) + if model: + try: + response = requests.post( + f"{self.api_url}/sdapi/v1/options", + json={"sd_model_checkpoint": model.name} + ) + if response.status_code == 200: + self.current_model = model + self.model_changed.emit(model.name) + except Exception as e: + print(f"Ошибка при смене модели: {str(e)}") + + def update_api_url(self, new_url): + """Обновить URL API""" + self.api_url = new_url + self.load_models() + + def get_models(self): + """Возвращает список доступных моделей""" + return self.models + + def get_model_names(self): + """Возвращает список имен моделей""" + return [model.name for model in self.models] + + def get_current_model(self): + """Возвращает текущую модель""" + return self.current_model + + def switch_model(self, model_name: str) -> bool: + """Переключение на другую модель""" try: response = requests.post( f"{self.api_url}/sdapi/v1/options", json={"sd_model_checkpoint": model_name} ) if response.status_code == 200: - self.model_changed.emit(model_name) + self.current_model = next( + (model for model in self.models if model.name == model_name), + None + ) + return True + return False except Exception as e: - print(f"Ошибка при смене модели: {str(e)}") - - def update_api_url(self, new_url): - """Обновить URL API""" - self.api_url = new_url - self.load_models() \ No newline at end of file + print(f"Ошибка переключения модели: {str(e)}") + return False \ No newline at end of file diff --git a/modules/pages/__pycache__/home_page.cpython-310.pyc b/modules/pages/__pycache__/home_page.cpython-310.pyc index e10b6fc7349312fd1048299132422e06a8028af1..62a3b61215cb9a72acadf87d01b514d81abe7b7d 100644 GIT binary patch literal 5813 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

v$0Hn6)`v3p{ literal 4655 zcmcIo-EZ606(=Q%q9{tT9LI68d@yO(&1+*MLDLo5&~|asCTJYQbJk&;2aXmQNf{|= zB-J>o0<3Y?3}}l!4A{$%PVQ6lmNoP0Y)$enP{5w}FcjERp0+*gVciGzJC~Fq)$&>l zD*;l6_ndov=j-y`qed<#bGW3B|4_NLm*f6KFTYg}ox z=;idI7jf~dv0~X6Jm2!FCtAMWsE3)wv$eW)%B=YyFIcNSBc;WqX048?VSe#sqqSmN z{rAk`e8X93fHlj9iADcmg7EoJI$?O$d81;@CPQ()VK-baOfNN!a;;toQ!h5^z6UAg zLe+At1)~l@w@juFUldllyeIImIE^2$+k$mhyrOaCG|8Qjz&hwm~=qA^>4yOwpuA5rtC@V|cE&klB7^b{d z({e*e*K75fuj}q4CWi`QiviC!>SZg;`Q(T0M2>_x&+=PMy$mm{x<8u;1<$fChGNrj z@qUXBGrC^34bRi{Tiho{=S#~?w{giT``$7XBD%WKtSvhYvt?V}audPvmaFheCvvWN z#hr!;RFa;Ehr-Le!ncckzvudvmU(dd7g=4zJ&)Ua50U6_m$*xOH?huLqO~9CRxk zWvuQUO!pLKPjz>id9$#dU@@QSPMZ@SWdA6VV z6VV4_`Vf6-fJQz>)j~8IHD~cL`&z4n)f(IkZuegAUF-cMxF6gNeiz(Ud#{81O|XHX z-v*n(M|isv+{ZAJx*gmLHhXXM-fYd%^q&VC7$Di(y*I#kN5zy6G3D1Z1O>$24DPlM z%j(b-?GEZ|BZI^*)7QMDhJugnp}qW#Edm$u-8<~n+Ez(D`fPJ`8-dGKty1+%>Po{l zM@6mHX9C_Q)wixu3+PguxD&LYw7)$3 z1wE$lXv_02zN9Xd4cjVJ@Q&**&&R}bFT}*&KJoGMtpX&1_1@d$ES!k&+v!u-^<34^ zQjBO9PM%+Q@=5jBg8H)Ix`x-WvR`}EYR_y3)taExzuUWk3dg4|s`K{Rh!_9=g!`^h_oAcQs9_YaIN|Nbx3c=# zK8i$n4ZCKl?StD%J<9scts?(xQGEe9YG3#w%sV&xm^*{ihPiUfr6aP=&eNexhivA( z7iNh@8mNJAQ%o4A>?QvSdXcJyMn|-x9w&np67@bVo%dY{4^6=V+iB8?y@@tx5;M=+ zM%k)j@3CBJbHWLXE#QRjw4BpyX9`JC)Hi86>sG~}+SG^jxYVGyS+Yf@?GC1*6$&NH zJL6l9=hD|wlRe*RdN93K4<&$n+o)G8M!jO#Ez6~Iye5?|R+xxJy~7fGgj<-0R>E+a z_#Vc(W#YzNl(=x}64v$Z;u1p@0&65Up4@=VMxbeOQ zB`GEe8I~l4e+i=SiI5ilPPdp9{w5aWzsftn6NG>joN4J(P7lYCu6Ny8h#qVMiR+e6pB@xwwrjTegkH_)%E#Ckf}W z*zN#D%Yb#N5|`&EQZ9|1o1G2|=dUdK&&)0Q(Q@@%>d~V`%T^Yxa#r1LnkZVxY)P>t z6RkU?uVTL8TCM^K4fTR=f;UIKvYV$7)Ds(F9~GA}?b1f#Qah|o4Kw>4JnQk9okLDB c_sFSG`eqcG=jZ_B5$X|6L5`-7$En1B0JL>ScK`qY diff --git a/modules/pages/__pycache__/models_page.cpython-310.pyc b/modules/pages/__pycache__/models_page.cpython-310.pyc index 2935d0d661659d4924680d61bcac292513c9b410..f8eccf08d8211058f4ae78aad566d13d72fb7108 100644 GIT binary patch literal 4379 zcma)A-ESOM6`${&{qTC@uh{u$UHY_0vG@q3N=sYEcA9|W*jcxrQL52+XKb%Cv$MH# zm&D6P3Ux#ts8oUaL{(Uer@SQv(7=r{MY1AAi5`lLJxsxqLd4t!Xl-d7nzms*8Giti~P!) zXX6`--gexi%K5{JwX*1~1tA)jo5|+cCg*WoWLFkz^m|W5nya*j{)hZcPx56Hf#RsX;%L6==zivovaXT`Z)Y9D zH+}22;+S_7Lvbv4!xq_#u^)tU9`lXDQ z?r*vuEmd_|r1y}#|9}wiQ=vD;<4Tp|4p{?y5^=LzqdkLA!F@ zTD`_ySC|p4FYF}X&4$~om33hxLAcH)F{7{=9t-OHt}3#wTMfM=aoxMhKfXS9=1POb zTS1j4SKzm`FmSy_?F!~s%^ECt_m&Lo@pyv_Er{sT3ds?BhbzH zqp){O>W|C%1nNg+eewe{{brqf`t^7^Ljg1BZGB*d)UqjQ4SC?$6Eo=2hM^throoH; zam-=1&CW0{b&l*Roe@5|HMXnD^$e^hSH`##7-zMufpOU7!8ofYO;9{x$4A=+wNPZ0 zPcF4y%uV+_={cMJ!9XMRuX)w08!T?t{ZrLAjMoZppjRFrbaPCALJu76=~ zpAVC$r8jO&w^sj$6Am|UW;6bN!2Z8&WRn1}i7&g|njAFs&_Auo0e7#*b$%+TwE~I> z`W0HZ(KY8#sz!>m*i##$Wut=!?z*7%{^=Q&ZNFXkTD)+_>6x_pZ#ZZsTszDf{<8WsuFfEhY z8-ax9qyWB{Kzk&`r-P-@Y90h4rh z5qOBm?(YzSKSCC;x6}PZHhhSvd?1_O?Mn^z-bI@5U(y3MhDlSO84UTNB7Gr-BtyGV zn(9c`lyw;O^dT99537le|NL&*5n;>vXQY2-nTm$K< zQ_2_p?i!M44A~E=Bf8<{4pIQu0>N6Hj4!DUWMora_Gf*gN4q(m?-W3IL%g^(+#@n= z3nYlKBQ#d($z+LVeX~ck{aT|vEt-FSr7=l=%GP*iqAkghA0?t~8=XmipCYIDv904< zC!{?mrM=JaXR+!tJCu}7Lz?a!?B35jzJIxI8e{kwX{XV7ja?0FPT`efZ-AaDF=?}y!w`{D$l^Xr+JnI@gv?$5jT5l9caAEq#uHok|3`v|;V z<0_+Uto$VjO=1McZw@exj4-(<$uyBz$i9L>?5kAJw|4SL;IZna8&Hx?O3NXreG?!Z zuvH*1J556g=om%21UdFil3t`Dg|*8I=PoZ)&WlVntW~cDK7_bl2QZ0jv*CLHrDjd& zv-9)pB~tnp6)#gkIi_4S#n#IK$b>RfaRQc{k6EpSEqGyiFTfpPImQCpY>3o`A8QpO z2Mx2~b#FVlw7$;h;^36z*-2a&#XVd|Sc?1Uk=n;n0UqS38D%rY-z<+CNQvt~=;T?j zj(f_cMA{5cTMGF^URYct-d-Ov9boPyte%`hVQGeH_x_AWCCkRhcGMkpUU{p8 zBTX#^9g2>*t5D|4rjY$w6r$I%=*@KOT?JzcH+7zE>o{S zf|R#xvvitK`%?L+7+&69;V;ar^ujWc(JW&(O+RF^B9A5=Wk&4BhzA+XC(jluKoW)h zdFEmk$iw4IBy^KbX5LFaUm;*hD1kez6cF3UD%6rT_UeBC4W)io literal 4672 zcmbtY-H#kc5%2k)otyo*58LN2v4H?t!7g?ZLO3UZ_!5ZW?&QNAl#FJln$iosMs(NPkcJKDAlbF-g zRCiZbS5^1culkzVtU=)U=|BIm`OZ8c|H8)TBSYi6@CFeOm$-sQe8CcY(Gq>hl6={c zeZ^9I)lz-U(tO?01(XxLjBi*5=Ou5-H!YL%vX}L9R*v(Em-h=+K_K5JuIg&HiK|h4 zOR}b+t-Bd$XQ&D78P`}NrKyKt0V(ORy1L}7Q!k!cz1R+F=i6b}Y(V3c^UWJe&dp{! zgvO6{8=2LmdV{{~*0F!79)v%xyPGtO^COK5A@xD;_n70;k`RllAyECi6VQv!CibX{ zO|QuU;LJ-k>eFSX0RyaxCXGHy+6cZ53?-J}5=(S7SESO0_$Jv9T*;MhXD!)PT=h1w zlsAb?EEU|-8H5*t49b_49GN+Sy(KX`*Dpb?TS(iI|cTM$SjM8prnl2gvWXogd+0`f|vbWK;~BMQvaV5ZJzW+L%w7Bm>}&B1pHzIphXAd%$~ zIpFe~E8NKrS5c4y?bD!LjntubHPt@ze`!xFC7^2-R-fa#jsSO*bH`Gf=kI7}g?k)M zOgu z-G7K%*wL!^lUXRna!7B4ec@a?hw9$hd8_w6D7yzL-+t&qSO0mVIP#4As*ArE8$qFU zr~30v)@(Q2@<6}VVs+nPH~X)i+b5pNT(8wbx_@-N$y^F1HkyqCN6XA{>+N8n*gxI6 zv0p{Yaou`j6NaVMjbh)~D|2hiq_M_`qYJg>HOda>uEJ&e&bTdyT&Klo5K#AUE2&O3 ztY4%3`Gb~9cJz<1@Aq)uaYti?GS+0BXUARTne}k1YC)TAI91wze0*8H`{{5>6?SQX{ZWkvpv ztjc|SRYU$%%^CkTrgibrC$EE-)gq138``|%-2-07KMhembPw-+F014n3 z0I91C;5i9|%BDd&aS}n9%_2$8WfHP#a@tBFKML#^j&p~1w-kZ&GQ8YtGl9|BT~jCH zD28c>qwhTuM_plvqx;d4TvfYT#E~=9x5zCy%xs~v2B56b1?1#thdk6jfIb>WA04;^ zbu+*jybn>+S*U7^=GsBs)dvwl0 zdm7dl#X-THpRh_k)u(o6l4>BF<$le>=OJt(FKey{flr0HMnywx^w`n$WB-6@YJY+hndNZ2W$vePiX zb7gzlQ3p}5}k+;JVdIMzOeCjK5wybn%&G+JSN z(EG4bsdUC?4$J%rR`0JG*w@g3pb4Jvu-G3l;)H^l!El_p|YGw8Jg|6BW%;u~0iqhlr)Jg|jt}}r3lnqN z6m`jj>!Y64RVZYH9PkBUM(oTlb2|~TE8s3%X;VNQ;P3Nb4SNB}caR{KGBlOFh=hYI zC%Z+)c^J3^Z(3yJgo47bZ>2OF=P%w|4WFs3rvGwCi$mPgPG2(MfjCV1=Aq@lsBp5OcV+296`c*kAD bZHo2h5)Cgv{vZJsPfrk&#}*= 0: + self.model_combo.setCurrentIndex(index) + + # Обновляем список сэмплеров + self.sampler_combo.clear() + for sampler in self.sampler_manager.get_samplers(): + self.sampler_combo.addItem(sampler.title, sampler.name) + + # Устанавливаем текущий сэмплер + current_sampler = self.sampler_manager.get_current_sampler() + if current_sampler: + index = self.sampler_combo.findData(current_sampler.name) + if index >= 0: + self.sampler_combo.setCurrentIndex(index) + + def on_model_changed(self, model_title): + """Обработка изменения модели""" + model_name = self.model_combo.currentData() + if model_name: + self.model_manager.switch_model(model_name) + + def on_sampler_changed(self, sampler_title): + """Обработка изменения сэмплера""" + sampler_name = self.sampler_combo.currentData() + if sampler_name: + self.sampler_manager.set_current_sampler(sampler_name) + + def set_resolution(self, width: int, height: int): + """Установка разрешения""" + self.width_spin.setValue(width) + self.height_spin.setValue(height) + + def generate_images(self): + """Генерация изображений""" + try: + # Получаем параметры + params = { + "prompt": self.prompt_edit.text(), + "negative_prompt": self.negative_prompt_edit.text(), + "steps": self.steps_spin.value(), + "cfg_scale": self.cfg_spin.value(), + "batch_size": self.batch_size_spin.value(), + "width": self.width_spin.value(), + "height": self.height_spin.value(), + "sampler_name": self.sampler_combo.currentData(), + } - QPushButton:hover {{ - background-color: {colors['hover']}; - }} + # Отправляем запрос + response = requests.post( + f"{self.model_manager.api_url}/sdapi/v1/txt2img", + json=params + ) - QPushButton:pressed {{ - background-color: {colors['active']}; - }} - """) + if response.status_code == 200: + result = response.json() + # TODO: Отобразить сгенерированные изображения + print("Изображения успешно сгенерированы") + else: + print(f"Ошибка генерации: {response.status_code}") - self.clear_button = QPushButton("Очистить") - self.clear_button.setStyleSheet(f""" - QPushButton {{ - min-width: 150px; - background-color: transparent; - color: {colors['primary']}; - border: 1px solid {colors['primary']}; - border-radius: {spacing.TINY}px; - padding: {spacing.SMALL}px {spacing.MEDIUM}px; - }} - - QPushButton:hover {{ - background-color: {colors['hover']}; - color: white; - border: none; - }} - - QPushButton:pressed {{ - background-color: {colors['active']}; - color: white; - border: none; - }} - """) - - buttons_layout.addWidget(self.generate_button) - buttons_layout.addWidget(self.clear_button) - buttons_layout.addStretch() - - self.layout.addLayout(buttons_layout) - - # Растягиваем пространство - self.layout.addStretch() \ No newline at end of file + except Exception as e: + print(f"Ошибка при генерации: {str(e)}") \ No newline at end of file diff --git a/modules/pages/models_page.py b/modules/pages/models_page.py index 8e06925..aa46252 100644 --- a/modules/pages/models_page.py +++ b/modules/pages/models_page.py @@ -1,178 +1,145 @@ -from PyQt6.QtWidgets import (QLabel, QPushButton, QHBoxLayout, - QVBoxLayout, QLineEdit, QListWidget, - QListWidgetItem, QFrame) +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QLabel, QPushButton, QLineEdit, QSpinBox, + QComboBox, QProgressBar, QScrollArea, QFrame) from PyQt6.QtCore import Qt -from modules.styles.page import BasePage -from modules.styles.theme import Colors -from modules.styles.theme_manager import ThemeManager +from ..styles.style_constants import StyleConstants +from ..styles.icons import IconManager, IconType +from ..styles.page import BasePage -class ModelItem(QFrame): - def __init__(self, model_name: str, parent=None): +class ModelCard(QFrame): + """Карточка модели""" + def __init__(self, model, parent=None): super().__init__(parent) - self.model_name = model_name - self.theme_manager = ThemeManager.get_instance() + self.model = model self.setup_ui() def setup_ui(self): - """Настройка UI элемента модели""" - colors = self.theme_manager.current_theme.get_colors() - spacing = self.theme_manager.current_theme.get_spacing() - - layout = QHBoxLayout(self) - layout.setContentsMargins(8, 8, 8, 8) - - # Название модели - name_label = QLabel(self.model_name) - name_label.setStyleSheet(f"color: {colors['text']};") - layout.addWidget(name_label) - - # Растягиваем пространство - layout.addStretch() - - # Кнопки управления - select_btn = QPushButton("Выбрать") - select_btn.setMinimumWidth(100) - select_btn.setStyleSheet(f""" - QPushButton {{ - background-color: {colors['primary']}; - color: white; - border: none; - border-radius: {spacing.TINY}px; - padding: {spacing.SMALL}px {spacing.MEDIUM}px; - }} - - QPushButton:hover {{ - background-color: {colors['hover']}; - }} - - QPushButton:pressed {{ - background-color: {colors['active']}; - }} - """) - layout.addWidget(select_btn) - - delete_btn = QPushButton("Удалить") - delete_btn.setMinimumWidth(100) - delete_btn.setStyleSheet(f""" - QPushButton {{ - background-color: {colors['error']}; - color: white; - border: none; - border-radius: {spacing.TINY}px; - padding: {spacing.SMALL}px {spacing.MEDIUM}px; - }} - - QPushButton:hover {{ - background-color: {colors['hover']}; - }} - - QPushButton:pressed {{ - background-color: {colors['active']}; - }} - """) - layout.addWidget(delete_btn) - - # Стили self.setStyleSheet(f""" QFrame {{ - background-color: {colors['surface']}; - border: 1px solid {colors['border']}; - border-radius: {spacing.TINY}px; + background-color: {StyleConstants.COLORS['dark']['surface']}; + border-radius: {StyleConstants.RADIUS['md']}px; + padding: {StyleConstants.SPACING['md']}px; + margin-bottom: {StyleConstants.SPACING['md']}px; }} - """) - -class ModelsPage(BasePage): - def __init__(self, parent=None): - super().__init__(parent) - self.theme_manager = ThemeManager.get_instance() - self.setup_content() - - def setup_content(self): - """Настройка содержимого страницы""" - colors = self.theme_manager.current_theme.get_colors() - spacing = self.theme_manager.current_theme.get_spacing() - - # Заголовок - header = QLabel("Модели") - header.setStyleSheet(f""" QLabel {{ - color: {colors['text']}; - font-size: 24px; - font-weight: bold; + color: {StyleConstants.COLORS['dark']['text']}; }} - """) - self.layout.addWidget(header) - - # Поиск и добавление - search_layout = QHBoxLayout() - - self.search_input = QLineEdit() - self.search_input.setPlaceholderText("Поиск моделей...") - self.search_input.setStyleSheet(f""" - QLineEdit {{ - background-color: {colors['surface']}; - color: {colors['text']}; - border: 1px solid {colors['border']}; - border-radius: {spacing.TINY}px; - padding: {spacing.SMALL}px; - }} - - QLineEdit:focus {{ - border: 1px solid {colors['primary']}; - }} - """) - search_layout.addWidget(self.search_input) - - self.add_btn = QPushButton("Добавить модель") - self.add_btn.setMinimumWidth(150) - self.add_btn.setStyleSheet(f""" QPushButton {{ - background-color: {colors['primary']}; + background-color: {StyleConstants.COLORS['primary']}; color: white; border: none; - border-radius: {spacing.TINY}px; - padding: {spacing.SMALL}px {spacing.MEDIUM}px; + border-radius: {StyleConstants.RADIUS['sm']}px; + padding: {StyleConstants.SPACING['sm']}px {StyleConstants.SPACING['md']}px; }} - QPushButton:hover {{ - background-color: {colors['hover']}; - }} - - QPushButton:pressed {{ - background-color: {colors['active']}; - }} - """) - search_layout.addWidget(self.add_btn) - - self.layout.addLayout(search_layout) - - # Список моделей - self.models_list = QListWidget() - self.models_list.setSpacing(8) - self.models_list.setStyleSheet(f""" - QListWidget {{ - background-color: transparent; - border: none; - }} - - QListWidget::item {{ - padding: 0; - background-color: transparent; + background-color: {StyleConstants.COLORS['secondary']}; }} """) - # Добавляем тестовые модели - test_models = [ - "stable-diffusion-v1-5", - "stable-diffusion-v2-1", - "stable-diffusion-xl-base-1.0" - ] + layout = QVBoxLayout(self) + layout.setSpacing(StyleConstants.SPACING['sm']) - for model in test_models: - item = QListWidgetItem(self.models_list) - model_widget = ModelItem(model) - item.setSizeHint(model_widget.sizeHint()) - self.models_list.addItem(item) - self.models_list.setItemWidget(item, model_widget) + # Название модели + title = QLabel(self.model.title) + title.setStyleSheet(f""" + font-size: {StyleConstants.FONTS['size']['lg']}; + font-weight: {StyleConstants.FONTS['weight']['bold']}; + """) + layout.addWidget(title) - self.layout.addWidget(self.models_list) \ No newline at end of file + # Имя файла модели + name = QLabel(self.model.name) + name.setStyleSheet(f""" + font-size: {StyleConstants.FONTS['size']['sm']}; + color: {StyleConstants.COLORS['dark']['text_secondary']}; + """) + layout.addWidget(name) + + # Кнопки управления + buttons_layout = QHBoxLayout() + + select_btn = QPushButton("Выбрать") + select_btn.setIcon(IconManager.get_instance().get_icon(IconType.SUCCESS)) + buttons_layout.addWidget(select_btn) + + delete_btn = QPushButton("Удалить") + delete_btn.setIcon(IconManager.get_instance().get_icon(IconType.DELETE)) + buttons_layout.addWidget(delete_btn) + + buttons_layout.addStretch() + layout.addLayout(buttons_layout) + +class ModelsPage(BasePage): + """Страница управления моделями""" + def __init__(self, model_manager, parent=None): + super().__init__(parent) + self.model_manager = model_manager + self.setup_ui() + + def setup_ui(self): + # Верхняя панель + top_panel = QHBoxLayout() + top_panel.setContentsMargins( + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'] + ) + top_panel.setSpacing(StyleConstants.SPACING['md']) + + # Поиск + self.search_edit = QLineEdit() + self.search_edit.setPlaceholderText("Поиск моделей...") + top_panel.addWidget(self.search_edit) + + # Кнопка обновления + refresh_btn = QPushButton("Обновить") + refresh_btn.setIcon(IconManager.get_instance().get_icon(IconType.REFRESH)) + refresh_btn.clicked.connect(self.update_ui) + top_panel.addWidget(refresh_btn) + + # Кнопка добавления + add_btn = QPushButton("Добавить") + add_btn.setIcon(IconManager.get_instance().get_icon(IconType.ADD)) + top_panel.addWidget(add_btn) + + top_panel.addStretch() + self.layout.addLayout(top_panel) + + # Область прокрутки для моделей + scroll_area = QScrollArea() + scroll_area.setWidgetResizable(True) + scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + + # Контейнер для карточек моделей + self.models_container = QWidget() + self.models_layout = QVBoxLayout(self.models_container) + self.models_layout.setContentsMargins( + StyleConstants.SPACING['lg'], + 0, + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'] + ) + self.models_layout.setSpacing(0) + + scroll_area.setWidget(self.models_container) + self.layout.addWidget(scroll_area) + + # Обновляем UI + self.update_ui() + + def update_ui(self): + """Обновление списка моделей""" + # Очищаем контейнер + for i in reversed(range(self.models_layout.count())): + widget = self.models_layout.itemAt(i).widget() + if widget: + widget.deleteLater() + + # Добавляем карточки моделей + for model in self.model_manager.get_models(): + card = ModelCard(model) + self.models_layout.addWidget(card) + + # Добавляем растягивающийся элемент в конец + self.models_layout.addStretch() \ No newline at end of file diff --git a/modules/sampler_manager.py b/modules/sampler_manager.py index 78d1ce3..0029755 100644 --- a/modules/sampler_manager.py +++ b/modules/sampler_manager.py @@ -2,6 +2,17 @@ from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QLabel) from PyQt6.QtCore import pyqtSignal import requests +from typing import List, Dict +import os +from dotenv import load_dotenv + +# Загружаем переменные окружения +load_dotenv() + +class Sampler: + def __init__(self, name: str, title: str = None): + self.name = name + self.title = title or name class SamplerManager(QWidget): sampler_changed = pyqtSignal(str) @@ -71,28 +82,25 @@ class SamplerManager(QWidget): layout.addStretch() def load_samplers(self): - """Загрузить список доступных сэмплеров""" + """Загрузка списка сэмплеров с сервера""" try: response = requests.get(f"{self.api_url}/sdapi/v1/samplers") if response.status_code == 200: - samplers = response.json() - current_sampler = self.sampler_combo.currentText() + samplers_data = response.json() + self.samplers = [ + Sampler(sampler['name'], sampler.get('title')) + for sampler in samplers_data + ] - self.sampler_combo.clear() - for sampler in samplers: - self.sampler_combo.addItem(sampler.get('name', '')) - - # Восстанавливаем выбранный сэмплер, если он всё ещё доступен - index = self.sampler_combo.findText(current_sampler) - if index >= 0: - self.sampler_combo.setCurrentIndex(index) - elif self.sampler_combo.count() > 0: - # По умолчанию выбираем Euler a - default_index = self.sampler_combo.findText("Euler a") - if default_index >= 0: - self.sampler_combo.setCurrentIndex(default_index) + # По умолчанию выбираем Euler a + self.current_sampler = next( + (sampler for sampler in self.samplers if sampler.name == "Euler a"), + self.samplers[0] if self.samplers else None + ) except Exception as e: - print(f"Ошибка при загрузке сэмплеров: {str(e)}") + print(f"Ошибка загрузки сэмплеров: {str(e)}") + self.samplers = [] + self.current_sampler = None def on_sampler_changed(self, sampler_name): """Обработка смены сэмплера""" @@ -103,6 +111,25 @@ class SamplerManager(QWidget): self.api_url = new_url self.load_samplers() + def get_samplers(self): + """Возвращает список доступных сэмплеров""" + return self.samplers + + def get_sampler_names(self): + """Возвращает список имен сэмплеров""" + return [sampler.name for sampler in self.samplers] + def get_current_sampler(self): - """Получить текущий выбранный сэмплер""" - return self.sampler_combo.currentText() \ No newline at end of file + """Возвращает текущий сэмплер""" + return self.current_sampler + + def set_current_sampler(self, sampler_name: str) -> bool: + """Установка текущего сэмплера""" + sampler = next( + (s for s in self.samplers if s.name == sampler_name), + None + ) + if sampler: + self.current_sampler = sampler + return True + return False \ No newline at end of file diff --git a/modules/size_preset_manager.py b/modules/size_preset_manager.py index ee83568..03da8a9 100644 --- a/modules/size_preset_manager.py +++ b/modules/size_preset_manager.py @@ -1,6 +1,14 @@ from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame from PyQt6.QtCore import Qt, pyqtSignal from .size_presets import SIZE_PRESETS +from dataclasses import dataclass +from typing import List, Dict + +@dataclass +class SizePreset: + name: str + width: int + height: int class SizePresetManager(QWidget): size_changed = pyqtSignal(int, int) # Сигнал для изменения размера @@ -8,6 +16,17 @@ class SizePresetManager(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setup_ui() + self.presets = [ + SizePreset("512x512", 512, 512), + SizePreset("768x768", 768, 768), + SizePreset("1024x1024", 1024, 1024), + SizePreset("512x768", 512, 768), + SizePreset("768x512", 768, 512), + SizePreset("512x1024", 512, 1024), + SizePreset("1024x512", 1024, 512), + SizePreset("768x1024", 768, 1024), + SizePreset("1024x768", 1024, 768), + ] def setup_ui(self): layout = QVBoxLayout(self) @@ -90,4 +109,15 @@ class SizePresetManager(QWidget): def on_preset_clicked(self, width, height): """Обработчик нажатия на кнопку пресета""" - self.size_changed.emit(width, height) \ No newline at end of file + self.size_changed.emit(width, height) + + def get_preset_names(self) -> List[str]: + """Возвращает список имен пресетов""" + return [preset.name for preset in self.presets] + + def get_preset(self, name: str) -> SizePreset: + """Возвращает пресет по имени""" + return next( + (preset for preset in self.presets if preset.name == name), + None + ) \ No newline at end of file diff --git a/modules/styles/__pycache__/base_window.cpython-310.pyc b/modules/styles/__pycache__/base_window.cpython-310.pyc index c94048119800d8d468efeb17efc552db26167ec7..da85ea38456379af48459c905d6903611eea94a0 100644 GIT binary patch delta 264 zcmca3az}(KpO=@50SMY3Zsg);7QDrmoSIisl$aA=o|%%KT5@Z%7V{NGZW*A8B3Te2 zx0#bwgHcu;#O47Kw^)iZ^2;@uiv-|GWH$S;c``<7fCLypggl6l1`>XnB1M`Y4m*g@ z0ukCELI*_Xf(SMcp#UNjL4*>BPzDhyAc7S{s80UCt}UbnWWsEPxNfp8$8}LDkO~nv fAqrv{PnP7=XOy1o$!RA5cDFuA)CeLqo%1LF7dbCK delta 264 zcmca3az}(KpO=@50SM;Y+Q`MvEEvU?oSIisl$aA=o|%%KS`xKci}?y8w-iuCku->q z+04nR!6>T=V)ForTP(#H`Q@6-MFMaoQk(tQJQ*X^Kmv>)LKZ|w0tr7&ks@^vhaE&{ zfCxteK?EC!kOL9&AVL8|D1rzj5Wxx}lqY{+*A`L%GGVqtTsK*lNQDTT f5CyReCrfhbGfGbOEGWun*qM9?bgn}SDF9QL8Yo?rs$Gq0D)zNN?-EL+ ztOrKdq^6WfkfS-6CxJz+C50Kxe4sFst0SG}p`T+G^sSLbZARKkHUA%2U#V&-ae8q# zC0-o$t7>Z8u6O!95Xg!bZ8kcnH2J8|xehJ-9ROFT$`q~6lzE`CFUer67v#m zi3N#8i6x0sOrz6Gr)5Uy8D`KKX411PM`z{iIcCv0mZvW;o1SL{`XVdR3#>#hvMKsC zHcc4^{@i{Oz`9tzJ`DFZI1^y0`r^!E| z9a7Tey?9`ILiFFgde7^;Gbm;9dSATj36`3Icl$e>63+Z6HAC)+&L%Z>e8&6K@M7lo zDcKIZU21H5amZ5=M*ZzH2QT;h-bQM0SX!jS@2&T#)%AOR*B@|@y!SFGCpf$z_`nYQ zjm_w4x6k+>&ph#t6dTpcspYyoughIGwOtqH;{fHN>)wyO;Akf2x~$)EU7>@oDY@BP zc2aY>x#-+#r&ilpU9C5kKw5GdPOG-+q}F*RY@fljXF+-N!Nn<;76?mDTlaI4vd z(e|B%1*hGnWZ7xlq2x!kg*R#LMzi(fT5FM-EoZrT*P+B&tglkD?bKQeH&dg&Tw8Le zakswcG^tU$vsiCZvU02T6Kbr~?zBO_z1mz!bFfAOOiB%>)oQj;vy2_7ki{}rsm1a<&unh56INiw2ZR>nNQoEasL7_-G>n#* z24pX%1tj~j*Yh^Gh%doj$#0WKK=Mb)Uy{EjkH+tx;C-WmseJsPtU+6V7R~_p%208k z?W+e0))&}8Z9ug!WaLsi=zGkSGS-Ta2kT!Rf~dd(NLiqIF1>4319JrS!gouzXBlwPeiwDZ0^7f@QZBO4LLv=_lDtpGz*e@L@;*Dr3njRV>*bAat z9_rVW`&XhftT;42Qa;v3stSEpf*4O_RQh%DF!}TN{qYC_dw42(Ura**>&K$Q!|zB+ z46Mz5m(Pbg8v`4QSrAIO81g8BI3M*kc#jJ&%Jgy`W7!L!&W{EQg0I8Un{vVmy`4-q z-wFC*CKkfD1KY|K<5wVl$#0HIyEGEWUx5sGnEV}b0CVBt>y<`zMi`(elU1BS2?;OG zBH&pFyeq^U!V3sULGdEO1pvr^ht6#Q%c7xnQ5mXR>PPU^^fAbL`cU83fc~CX@GluE`NL4+? zS~cM#Qsyyo==g)-FnL@V|Fj~D%_H#iY4QXehEg;BP*maN0YS3D`6I#XE@pdMNP=QRsTs;v$#PM-HE?dp^$fv%WB zm`1?!6|W+E6Cf>g0xt}^JlgCtaRrAjBVcLDj7EDi%YT5i_@% literal 2359 zcmZuzUvC>l5Wl_K`(wxX(==(5hSGq9z@Vgn5TL3;HSskujqTJ<3alcXuD6@`k~^Q- zJEx76K2TTU0r3eCYWv6=FOjNJ+OOb9JgvkNPkaR=BxdiL)U>R%b2GEEv$MaOnR7Hc znpa@#|MC0w{hXrwDTU#ILAU}l{sIV9C<>Gi5frLKMN(D+EyM(;ycX!8K@6lUD-=`x zo|@sBKn?BSwwWVOZ|x8PT=knz2kOcxg&`>y@J1KKEP>8!*jF2NbA=d9yVO`(5qhOsTDFOP zqf)l(L@#ZWD|Ld`R!d(KeXX?71UJp~`kFAC8%s-evnfnCs0I-T-EK7M4S_4QtFUot zwGOscwNk58D@1aouQCpf1P=|H%?uc++7DQ~=|fJ$i=BOLz)l@zdXj`@?P zg;GDS6oYhrMLJ&va$F2h02;$orP@8EkBFWXA{2$eOlmS~3sZ~c?#a@Snmo&=T7!!1~dZI+xEejq)|%jH!I8K^fi6wBhU;VW^;O=(=0fk_mK z`Uv8Ixr268zywhF0oqog?O=+5>Qn~`*!UXQnZAtPq6)-r)_UVm98s5hEWVh&&vm$s z*>O2*C$X^DZ9h(&Xt!szqL3}dd)vL79|Bw{TZmbbKqbafD(1M%0g+4HIMnAt4|m~_ zzE(a3Yg_`!r=?Y1S~(r)e(`hObD_#*ON?2t^)hl$pHSC{<9q^}<1rw4G=U6k0CL7Z zd9yb)jNY+v7K@WW-;y0E>GHNGU+VFY6)k59rcAE`38J!x_!|;TnCbzVRpyjC>Vf(| zd#Lca1Sk4|+D{?h0sG5J+eolXh)l|!vl3j?eGgm??hl?0em&|ReK+`JaCmfge(-4U z7*xLv9v}7R2hRpi=a24!?%7elXz+Jn2Y*YFw}A*F#Xsiq^CYx5;YE!X<*M{dQlwK1 zUx6#lA3)d!ySM-(uTCHfO`(F8NB;%u*i`6Ai-pXSfE*8b?g>C2fskHLor8<-pdTUg zeggiEcAz~_0i5YXOYngv!D)i!1N{I!ly#5x;9-jtJ4D(%hUZ1cncA$Yma9pQMqs{p-oc wi`SFouAgNJ)Nj%X{F`Y(W&y~q^nWJ`>vGoBKa(9Vmj99_lmcKdp-vY61zQkU&;S4c diff --git a/modules/styles/__pycache__/page.cpython-310.pyc b/modules/styles/__pycache__/page.cpython-310.pyc index 6ce58bbf4ef479ffd560acb1f6702b191d2020fa..3f8a083442485b66d8eb005e42a10b22fc8813f3 100644 GIT binary patch delta 2013 zcmaJ?O>7%Q6rP#=@p|LGI>w=GR2ftOrlQb4{#u&0L6k@kej48cpT28112XWzm2>lT$CE>(SGzLJblN8HYySGn)YZabW|+1Y_q?{BYuv17XL3%Cl9PldxOJIu%cJv}vkm4+ zZo}O67|ip0V1krWi`{F3Wg2BBf)DH7XtUu5l}6xK7q=BUXy1Pxz#|Uj#9^E|8Xveq zCMo#QFDD(H8{E8193%GRn6U>ZafRr_vCw{Gov8TU>y;_5^(2^*i*i|hFW2Oa-pBGz zN&X=3%H`h0-o=uT;#G5MHC_2GYJ4v}WB?U??1BZyI?plni}# zn0_99%U*)Z8Dwg+T29B8V>}i>GX7Fi(VGivK#cW-3@v?0pVM% zM=61 z04Zitli7dUW}c>KN=wlkO|cX$&~wFmx!>E*;LTU{ebf-UU}v~sjBFQ=!bm)ZkU%IS zJPr{4X*^7a!X4)B!WQ?KlilHn_2A7p^C0a!fjjVW#a@J`5YW8Xhk*GQFK2{_ll=&o z1#tl3Ai{n8M~Shbe5UN2O5UK?GKKly==}z2f^-uU-e0zV+>>qLQA45oX9w0a!$*8EP3; zF}G9TN}n+&VD^8E@qja)IjJko=uUzgo-xT3b9Bd2%t(j1$)Hkec%t3%|0Uni*L~=#`2*tYqZ`e|jKj9vDJ_0+pkcL38ogF-1 zK;}u8wkdL?2CQ)zN7Oi(AVTF)7u!Hjr7tpOAvQlsRa-(pJ-av+MO;=1Q~6U_!(_h; zkB|4Cq9(PWEH@o&uN(fJe5LvjtjkX!BxKeNIK!ph)eYSM57nC=2Vxut#VA?f{OuZ_ z@`AFas3Jx|EM7$DUmivfS)i)otAyX!hdNk&sOzr)v?;UzGDk&%(+O-9AlXjNLlc>% zZT0~ZgR#8JmdJSxrQ#6cwAR%FgEP+N*?N;fnHd;uZGdc%CYA`aA=b6p8fTp)h7;&d zU;qW{22cXqH<(08yp?qAcI*bb8^w^yS_`=#zkq~6KZ2IJeBXrqrw%%*5XKcP%L6Kz z0xLE$&eV8tTI_*wOisl*#ZdGV=`+naPcg>HK{pwVFMj5<{5P%ld$ZU0BojHn;}}7sTEjJHL^U-L$%l%RLs!kiuu<s%2P@}jQkIXcAtL`1ew&>%A0vX1J4gVY~O#B1w92}qk delta 1492 zcmZ{kUuYaf9LHy7|8MX1E@_OKRyifKU8~Vrt7vO#8%_TpXKD~}LC*Dd60cnL!t7oP zVaurr_Q3}U>!V;Iee@x=l-82iYfI3nHlaD*k?RsYzR0nD5Q}X6ARlKcC%8 z4}US{b;@Oz!1Lp;KhK}4u6n!a;_Cj__M9M*8CfeNvN&DVf(oqd$bq%P8LX?3J4^f> zt6zSW|KW^HKMM{x31~zD7P%M69F16{tvG=e>5;KQ0)5~uFa}-%^CHnnV4;t~J{~4~ zCY>jAiXs|r&0ZLu?-(Sy@I6Qf`# z%x0(E5s4Us#Xxr9Yy_kPBk^#;OlmUsAJ-bDRk}2EJNyY1`IWbg1JwRYgM*8mB+t#G z`49TR{5SIvI+}adc-kucE-;LY>}#tcn)XJ+tnXJ)_B4DkTNk$qhBC|xOR5gLDs8kDM5xgeiJ~XIwR5w*lSc)?+ z5*?(JPwsf9hYgUQ0*zk*sF&q8@+yKTuOg~QEns>NqIE#=DBLTYFpA!6Me{uMH3g@5 z3C!Xc%3TcEaI}Guy#br*|6S(MrQ9p+>tT*lXg&#&(TtoW=ZJVTgM8P?1(vdmrP?wR z!x>xC*9nE>&%(I}$psD07@3AO$+R^S_aZv0hR?dlq5K?DfcH#ZyC;pB{9fLy$?HA& z?I7#AZ>hY3aa9c?$PSP-La)DSVhJq@*OH*6GBhxc55*q}GAJ#_=f!4Y|lrMO1P49%cD5Iz{;MO)*%BgxO c?IR1FsN3d~_z_6(t29D(!-uFut8C=-zcqPtIRF3v diff --git a/modules/styles/__pycache__/style_constants.cpython-310.pyc b/modules/styles/__pycache__/style_constants.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08c954b6a149379c1338eab7ec7b5097e908960d GIT binary patch literal 4688 zcmcH+TWlLybvz!AZyY!2WBW+jw39xzaW@a!c@?+2G>@iawN187Q6*EbCO#8qvf~-= zoiRyFSK4m-!KxCgE)pLQ?XrR&{1VS5NJZu2Lk@+<7PmD0LTyo z0(B6AdI-ZVXjlkBBkV@r9@q=}@a3Fm7D&<$`{4i_ghS8-&2SiwECiF%3aCOh3w}5aZ3|*D2oX2~&n<}14js@5T@ZyB#1~}fh92mJKImVN z;4J=2v^w}CB(xBm(?U}coQLP{1aAA1_3#3Qe1SDgIP-=!WSO?3nvPuvp6I{W+dmXX zWU%`a!^4A!^mg|Rk6c8guWxX$Zvc^zk%9hrA0ih=db@k0g-fp*x~Zu&Lsif<(`lQF zC8F)hya(svi5TJ@v>hv#h$?7+KkbS~$B^#jE#jHx5=7!L-Vo{U<&Ae1<&Eoj+MMG( zksu3As_9oU)XJN{f_9!xscDT#jyC781`boUmbOe#={%DsEeaZCfobdW8chasRI_aj zb{<1)fVb5c;={c07)lr-gHhfP>51}&NH^xIyEj4@_N!;PKXq$dQ`2e89*+PK+h)O8 zm72PlVF8U&3w<{9%(TNK4CIw%3FqN5;ULVxZVnD{pl}dH5D6yzb8|Km`D+jYPZe*r@5?@XA-MNz1V!BISjG)_bAFFeWC& z(0zpHBti@$DaDbKl)6zGk!cgxuaOzbO9}J$M5D~#%RwIp{n2PdN(QNx$r~zVa#jO9 zpJl|>vihWD0FyY3_?bMVW_4qpNw!|lm^`cT5v6?aSiqUqvdE*Flc#1{L|*0Lbu57I z5We>%)%Kv*jT7}dUyX~IuJs+0pNd83}d-rX3$^F26P<-9JUwqTO?>;QPp}6lO@&O7S6z{qZ zmEx`98}6d}k-Mn4-*G=GzNNU2QJ-^`-0!*%-AC?X@hv9gH8dDf);wKj6!)FtEmS~T z?xXeA&U962U%9O6=5^f!YgYL}m4usIEyxLl@={fJ@m!VCYgJSgapk%W8O^C-HEkId zMT0Uoc&yqW?{&&DosQB9L#csyM>=TUtjgI_1OIo z)4e`HFX!#)!Mx*GW{pr*6Vy?Ts_@zBo_RoJ(d@MDXd9)att_FKmbt04gYU_CJE0U> za&sF^k57>*@f0xie73<noN`!wesN|(<*Bte|M(?^EQ^R$5c0)jqL^fUiEIK|^wwumxZuGU{=l?OEJN0sK zqnA9R<$>Q`LYp^FXe7Yoq4Af-uTC&&#?nm|7#SbCHo@ep1H+@Ao?yX=mj{MM$1dU7 z*`GFS8pE~0WN%-zza`LfNIp3`l(>S$N4Ue^Pi6 zEM0axbMveb&l#yn)z(raofMk0Zz2f!L!#^_Pvs!_I84Yt!gb{Dq=EdE>>+<9d&!^p z8{S9$NDh)^a+v&HR>*JUR`P54IQbPhL4HY2l3$Qheakzlq9qV!=Yz6=tqzYPJC)$c>MZAGBhwYdU@d5==j(K?L!HxPaCRj zXEkTq0_L|JN}uO{@f5EC=Q+tQB>c7SARvP17kw*DTEUPfeJqBnY55Og>spSyMnnFm z7~(SdsaVIq(o-=YKj9Xne~W?DzoaK6Ir9G{|4rQA?DISt;} XB;0>S&X QIcon: - """Получение иконки по типу""" - return self._icons.get(icon_type, QIcon()) + """Получить иконку по типу""" + return self.icons.get(icon_type, QIcon()) def get_themed_icon(self, icon_type: IconType, theme: str) -> QIcon: """Получение иконки с учетом темы""" diff --git a/modules/styles/page.py b/modules/styles/page.py index 1ab813a..f164f16 100644 --- a/modules/styles/page.py +++ b/modules/styles/page.py @@ -2,15 +2,17 @@ from PyQt6.QtWidgets import QWidget, QStackedWidget, QVBoxLayout from PyQt6.QtCore import QPropertyAnimation, QParallelAnimationGroup, QEasingCurve, Qt, QPoint from .theme import Theme, Colors from .theme_manager import ThemeManager +from .style_constants import StyleConstants class BasePage(QWidget): + """Базовый класс для страниц""" def __init__(self, parent=None): super().__init__(parent) self.theme_manager = ThemeManager.get_instance() - self.setup_ui() + self.setup_base_ui() - def setup_ui(self): - """Базовая настройка страницы""" + def setup_base_ui(self): + """Настройка базового UI""" colors = self.theme_manager.current_theme.get_colors() self.setStyleSheet(f""" QWidget {{ @@ -18,11 +20,19 @@ class BasePage(QWidget): }} """) - # Основной layout self.layout = QVBoxLayout(self) - self.layout.setContentsMargins(24, 24, 24, 24) - self.layout.setSpacing(16) + self.layout.setContentsMargins(0, 0, 0, 0) + self.layout.setSpacing(0) + # Создаем анимации + self.enter_animation = QPropertyAnimation(self, b"pos") + self.enter_animation.setDuration(250) + self.enter_animation.setEasingCurve(QEasingCurve.Type.OutCubic) + + self.exit_animation = QPropertyAnimation(self, b"pos") + self.exit_animation.setDuration(250) + self.exit_animation.setEasingCurve(QEasingCurve.Type.OutCubic) + def enter_animation(self): """Анимация появления страницы""" # Создаем группу анимаций @@ -78,26 +88,43 @@ class BasePage(QWidget): self.anim_group.start() class PageContainer(QStackedWidget): + """Контейнер для страниц с анимацией переходов""" def __init__(self, parent=None): super().__init__(parent) self.pages = {} + self.current_page = None def add_page(self, name: str, page: BasePage): - """Добавление новой страницы""" + """Добавить страницу""" self.pages[name] = page self.addWidget(page) def show_page(self, name: str): - """Показ страницы по имени""" - if name in self.pages: - # Запускаем анимацию исчезновения текущей страницы - current_page = self.currentWidget() - if isinstance(current_page, BasePage): - current_page.leave_animation() + """Показать страницу с анимацией""" + if name not in self.pages: + return - # Показываем новую страницу - new_page = self.pages[name] - self.setCurrentWidget(new_page) + next_page = self.pages[name] + + if self.current_page == next_page: + return - # Запускаем анимацию появления новой страницы - new_page.enter_animation() \ No newline at end of file + # Получаем размеры виджета + width = self.width() + + # Настраиваем анимации + if self.current_page: + # Анимация выхода текущей страницы + self.current_page.exit_animation.setStartValue(QPoint(0, 0)) + self.current_page.exit_animation.setEndValue(QPoint(-width, 0)) + self.current_page.exit_animation.start() + + # Анимация входа следующей страницы + next_page.move(width, 0) + next_page.enter_animation.setStartValue(QPoint(width, 0)) + next_page.enter_animation.setEndValue(QPoint(0, 0)) + next_page.enter_animation.start() + + # Показываем страницу + self.setCurrentWidget(next_page) + self.current_page = next_page \ No newline at end of file diff --git a/modules/styles/style_constants.py b/modules/styles/style_constants.py new file mode 100644 index 0000000..1db505c --- /dev/null +++ b/modules/styles/style_constants.py @@ -0,0 +1,181 @@ +from typing import Dict + +class StyleConstants: + # Цветовая схема + COLORS = { + 'primary': '#7E57C2', # Основной цвет + 'secondary': '#B39DDB', # Вторичный цвет + 'accent': '#536DFE', # Акцентный цвет + 'success': '#66BB6A', # Цвет успеха + 'warning': '#FFA726', # Цвет предупреждения + 'error': '#EF5350', # Цвет ошибки + + # Светлая тема + 'light': { + 'background': 'qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #F5F5F5)', + 'surface': '#FFFFFF', + 'text': '#212121', + 'text_secondary': '#757575', + 'border': '#E0E0E0', + 'hover': '#F5F5F5', + 'pressed': '#EEEEEE' + }, + + # Темная тема + 'dark': { + 'background': 'qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #1A1A1A, stop:1 #2D2D2D)', + 'surface': '#2D2D2D', + 'text': '#FFFFFF', + 'text_secondary': '#B0B0B0', + 'border': '#404040', + 'hover': '#353535', + 'pressed': '#404040' + } + } + + # Размеры и отступы (в пикселях) + SPACING = { + 'xxs': 4, + 'xs': 8, + 'sm': 12, + 'md': 16, + 'lg': 24, + 'xl': 32, + 'xxl': 48 + } + + # Радиусы скругления (в пикселях) + RADIUS = { + 'sm': 4, + 'md': 8, + 'lg': 12, + 'xl': 16, + 'pill': 9999 + } + + # Тени + SHADOWS = { + 'sm': '0 2px 4px rgba(0,0,0,0.1)', + 'md': '0 4px 8px rgba(0,0,0,0.1)', + 'lg': '0 8px 16px rgba(0,0,0,0.1)' + } + + # Анимации + ANIMATIONS = { + 'duration': { + 'fast': 150, + 'normal': 250, + 'slow': 350 + }, + 'easing': 'cubic-bezier(0.4, 0, 0.2, 1)' + } + + # Шрифты + FONTS = { + 'family': { + 'primary': 'Inter', + 'secondary': 'Roboto' + }, + 'size': { + 'xs': '12px', + 'sm': '14px', + 'md': '16px', + 'lg': '18px', + 'xl': '24px', + 'xxl': '32px' + }, + 'weight': { + 'regular': '400', + 'medium': '500', + 'semibold': '600', + 'bold': '700' + } + } + + @classmethod + def get_base_styles(cls, theme: str = 'light') -> str: + """Возвращает базовые стили для приложения""" + colors = cls.COLORS[theme] + + return f""" + /* Основные стили */ + QMainWindow {{ + background: {colors['background']}; + }} + + QWidget {{ + color: {colors['text']}; + font-family: {cls.FONTS['family']['primary']}; + font-size: {cls.FONTS['size']['md']}; + }} + + /* Кнопки */ + QPushButton {{ + background-color: {cls.COLORS['primary']}; + color: white; + border: none; + border-radius: {cls.RADIUS['md']}px; + padding: {cls.SPACING['sm']}px {cls.SPACING['md']}px; + font-weight: {cls.FONTS['weight']['medium']}; + }} + + QPushButton:hover {{ + background-color: {cls.COLORS['secondary']}; + }} + + QPushButton:pressed {{ + background-color: {cls.COLORS['accent']}; + }} + + /* Поля ввода */ + QLineEdit, QTextEdit {{ + background-color: {colors['surface']}; + color: {colors['text']}; + border: 1px solid {colors['border']}; + border-radius: {cls.RADIUS['md']}px; + padding: {cls.SPACING['sm']}px; + selection-background-color: {cls.COLORS['secondary']}; + }} + + QLineEdit:focus, QTextEdit:focus {{ + border-color: {cls.COLORS['primary']}; + }} + + /* Выпадающие списки */ + QComboBox {{ + background-color: {colors['surface']}; + color: {colors['text']}; + border: 1px solid {colors['border']}; + border-radius: {cls.RADIUS['md']}px; + padding: {cls.SPACING['sm']}px; + }} + + QComboBox:hover {{ + border-color: {cls.COLORS['primary']}; + }} + + /* Полосы прокрутки */ + QScrollBar:vertical {{ + background-color: {colors['surface']}; + width: 12px; + margin: 0; + }} + + QScrollBar::handle:vertical {{ + background-color: {cls.COLORS['secondary']}; + min-height: 20px; + border-radius: {cls.RADIUS['sm']}px; + }} + + QScrollBar:horizontal {{ + background-color: {colors['surface']}; + height: 12px; + margin: 0; + }} + + QScrollBar::handle:horizontal {{ + background-color: {cls.COLORS['secondary']}; + min-width: 20px; + border-radius: {cls.RADIUS['sm']}px; + }} + """ \ No newline at end of file diff --git a/modules/windows/console_window.py b/modules/windows/console_window.py new file mode 100644 index 0000000..e9aaabd --- /dev/null +++ b/modules/windows/console_window.py @@ -0,0 +1,91 @@ +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QLabel, QPushButton, QTextEdit, QComboBox) +from PyQt6.QtCore import Qt, pyqtSignal +from PyQt6.QtGui import QTextCursor +from ..styles.style_constants import StyleConstants +from ..styles.icons import IconManager, IconType + +class ConsoleWindow(QWidget): + """Окно для консольного вывода""" + def __init__(self, parent=None): + super().__init__(parent) + self.icon_manager = IconManager.get_instance() + self.setup_ui() + + def setup_ui(self): + self.setWindowTitle("Консоль") + self.resize(600, 400) + + # Основной layout + layout = QVBoxLayout(self) + layout.setSpacing(StyleConstants.SPACING['md']) + layout.setContentsMargins( + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'] + ) + + # Верхняя панель + top_panel = QHBoxLayout() + + # Уровень логирования + self.log_level = QComboBox() + self.log_level.addItems(["INFO", "WARNING", "ERROR", "DEBUG"]) + top_panel.addWidget(self.log_level) + + # Кнопки + clear_btn = QPushButton("Очистить") + clear_btn.setIcon(self.icon_manager.get_icon(IconType.DELETE)) + clear_btn.clicked.connect(self.clear_console) + top_panel.addWidget(clear_btn) + + save_btn = QPushButton("Сохранить") + save_btn.setIcon(self.icon_manager.get_icon(IconType.SAVE)) + top_panel.addWidget(save_btn) + + top_panel.addStretch() + layout.addLayout(top_panel) + + # Консоль + self.console = QTextEdit() + self.console.setReadOnly(True) + self.console.setStyleSheet(f""" + QTextEdit {{ + background-color: {StyleConstants.COLORS['dark']['background']}; + color: {StyleConstants.COLORS['dark']['text']}; + font-family: 'Consolas', monospace; + font-size: {StyleConstants.FONTS['size']['md']}; + padding: {StyleConstants.SPACING['md']}px; + border-radius: {StyleConstants.RADIUS['md']}px; + }} + """) + layout.addWidget(self.console) + + # Применяем стили + self.setStyleSheet(StyleConstants.get_base_styles('light')) + + def log(self, message: str, level: str = "INFO"): + """Добавление сообщения в консоль""" + color = { + "INFO": StyleConstants.COLORS['primary'], + "WARNING": StyleConstants.COLORS['warning'], + "ERROR": StyleConstants.COLORS['error'], + "DEBUG": StyleConstants.COLORS['secondary'] + }.get(level, StyleConstants.COLORS['primary']) + + # Форматируем сообщение + formatted_message = f'[{level}] {message}
' + + # Добавляем сообщение в консоль + cursor = self.console.textCursor() + cursor.movePosition(QTextCursor.MoveOperation.End) + cursor.insertHtml(formatted_message) + + # Прокручиваем к последнему сообщению + self.console.setTextCursor(cursor) + self.console.ensureCursorVisible() + + def clear_console(self): + """Очистка консоли""" + self.console.clear() \ No newline at end of file diff --git a/modules/windows/negative_prompt_window.py b/modules/windows/negative_prompt_window.py new file mode 100644 index 0000000..b460b87 --- /dev/null +++ b/modules/windows/negative_prompt_window.py @@ -0,0 +1,153 @@ +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QLabel, QPushButton, QTextEdit, QComboBox, + QScrollArea, QFrame, QCheckBox) +from PyQt6.QtCore import Qt, pyqtSignal +from ..styles.style_constants import StyleConstants +from ..styles.icons import IconManager, IconType + +class NegativePromptCategory(QFrame): + """Виджет категории негативных промптов""" + def __init__(self, title: str, prompts: dict, parent=None): + super().__init__(parent) + self.title = title + self.prompts = prompts + self.setup_ui() + + def setup_ui(self): + layout = QVBoxLayout(self) + + # Заголовок категории + title_label = QLabel(self.title) + title_label.setStyleSheet(f""" + font-size: {StyleConstants.FONTS['size']['lg']}; + font-weight: {StyleConstants.FONTS['weight']['bold']}; + margin-bottom: {StyleConstants.SPACING['sm']}; + """) + layout.addWidget(title_label) + + # Список промптов с чекбоксами + for prompt, description in self.prompts.items(): + prompt_frame = QFrame() + prompt_layout = QVBoxLayout(prompt_frame) + + checkbox = QCheckBox(prompt) + checkbox.setStyleSheet(f""" + font-size: {StyleConstants.FONTS['size']['md']}; + font-weight: {StyleConstants.FONTS['weight']['medium']}; + """) + + description_label = QLabel(description) + description_label.setStyleSheet(f""" + color: {StyleConstants.COLORS['light']['text_secondary']}; + font-size: {StyleConstants.FONTS['size']['sm']}; + """) + description_label.setWordWrap(True) + + prompt_layout.addWidget(checkbox) + prompt_layout.addWidget(description_label) + layout.addWidget(prompt_frame) + + self.setStyleSheet(f""" + QFrame {{ + background-color: {StyleConstants.COLORS['light']['surface']}; + border-radius: {StyleConstants.RADIUS['lg']}; + padding: {StyleConstants.SPACING['md']}; + margin-bottom: {StyleConstants.SPACING['md']}; + }} + """) + +class NegativePromptWindow(QWidget): + """Окно для работы с негативными промптами""" + prompts_selected = pyqtSignal(list) + + def __init__(self, parent=None): + super().__init__(parent) + self.icon_manager = IconManager.get_instance() + self.setup_ui() + + def setup_ui(self): + self.setWindowTitle("Негативные промпты") + self.resize(800, 600) + + # Основной layout + layout = QVBoxLayout(self) + layout.setSpacing(StyleConstants.SPACING['md']) + layout.setContentsMargins( + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'] + ) + + # Верхняя панель + top_panel = QHBoxLayout() + + # Поиск + self.search_box = QComboBox() + self.search_box.setEditable(True) + self.search_box.setPlaceholderText("Поиск негативных промптов...") + self.search_box.setMinimumWidth(300) + top_panel.addWidget(self.search_box) + + # Кнопки + select_all_btn = QPushButton("Выбрать все") + select_all_btn.setIcon(self.icon_manager.get_icon(IconType.SUCCESS)) + top_panel.addWidget(select_all_btn) + + clear_btn = QPushButton("Очистить") + clear_btn.setIcon(self.icon_manager.get_icon(IconType.CLOSE)) + top_panel.addWidget(clear_btn) + + top_panel.addStretch() + layout.addLayout(top_panel) + + # Область прокрутки для категорий + scroll_area = QScrollArea() + scroll_area.setWidgetResizable(True) + scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + + # Контейнер для категорий + categories_widget = QWidget() + self.categories_layout = QVBoxLayout(categories_widget) + + # Добавляем тестовые категории + test_categories = { + "Качество": { + "Низкое качество": "Удаляет артефакты низкого качества и размытость", + "Шум и зернистость": "Убирает нежелательный шум и зернистость", + "Искажения": "Предотвращает искажения пропорций и перспективы" + }, + "Артефакты": { + "Двойные элементы": "Убирает дублирование частей изображения", + "Размытые лица": "Улучшает четкость и детализацию лиц", + "Неправильная анатомия": "Корректирует анатомические ошибки" + } + } + + for title, prompts in test_categories.items(): + category = NegativePromptCategory(title, prompts) + self.categories_layout.addWidget(category) + + self.categories_layout.addStretch() + scroll_area.setWidget(categories_widget) + layout.addWidget(scroll_area) + + # Нижняя панель + bottom_panel = QHBoxLayout() + + apply_btn = QPushButton("Применить") + apply_btn.setIcon(self.icon_manager.get_icon(IconType.SUCCESS)) + apply_btn.setStyleSheet(f""" + background-color: {StyleConstants.COLORS['success']}; + """) + bottom_panel.addWidget(apply_btn) + + cancel_btn = QPushButton("Отмена") + cancel_btn.setIcon(self.icon_manager.get_icon(IconType.CLOSE)) + bottom_panel.addWidget(cancel_btn) + + bottom_panel.addStretch() + layout.addLayout(bottom_panel) + + # Применяем стили + self.setStyleSheet(StyleConstants.get_base_styles('light')) \ No newline at end of file diff --git a/modules/windows/prompt_window.py b/modules/windows/prompt_window.py new file mode 100644 index 0000000..e7d146e --- /dev/null +++ b/modules/windows/prompt_window.py @@ -0,0 +1,117 @@ +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QLabel, QPushButton, QTextEdit, QComboBox, + QScrollArea, QFrame) +from PyQt6.QtCore import Qt, pyqtSignal +from ..styles.style_constants import StyleConstants +from ..styles.icons import IconManager, IconType + +class PromptCategory(QFrame): + """Виджет категории промптов""" + def __init__(self, title: str, prompts: list, parent=None): + super().__init__(parent) + self.title = title + self.prompts = prompts + self.setup_ui() + + def setup_ui(self): + layout = QVBoxLayout(self) + + # Заголовок категории + title_label = QLabel(self.title) + title_label.setStyleSheet(f""" + font-size: {StyleConstants.FONTS['size']['lg']}; + font-weight: {StyleConstants.FONTS['weight']['bold']}; + margin-bottom: {StyleConstants.SPACING['sm']}; + """) + layout.addWidget(title_label) + + # Список промптов + for prompt in self.prompts: + btn = QPushButton(prompt) + btn.setStyleSheet(f""" + text-align: left; + padding: {StyleConstants.SPACING['sm']}; + margin-bottom: {StyleConstants.SPACING['xs']}; + """) + layout.addWidget(btn) + + self.setStyleSheet(f""" + QFrame {{ + background-color: {StyleConstants.COLORS['light']['surface']}; + border-radius: {StyleConstants.RADIUS['lg']}; + padding: {StyleConstants.SPACING['md']}; + margin-bottom: {StyleConstants.SPACING['md']}; + }} + """) + +class PromptWindow(QWidget): + """Окно для работы с промптами""" + prompt_selected = pyqtSignal(str) + + def __init__(self, parent=None): + super().__init__(parent) + self.icon_manager = IconManager.get_instance() + self.setup_ui() + + def setup_ui(self): + self.setWindowTitle("Библиотека промптов") + self.resize(800, 600) + + # Основной layout + layout = QVBoxLayout(self) + layout.setSpacing(StyleConstants.SPACING['md']) + layout.setContentsMargins( + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'], + StyleConstants.SPACING['lg'] + ) + + # Верхняя панель + top_panel = QHBoxLayout() + + # Поиск + self.search_box = QComboBox() + self.search_box.setEditable(True) + self.search_box.setPlaceholderText("Поиск промптов...") + self.search_box.setMinimumWidth(300) + top_panel.addWidget(self.search_box) + + # Кнопки + add_btn = QPushButton("Добавить промпт") + add_btn.setIcon(self.icon_manager.get_icon(IconType.ADD)) + top_panel.addWidget(add_btn) + + refresh_btn = QPushButton("Обновить") + refresh_btn.setIcon(self.icon_manager.get_icon(IconType.REFRESH)) + top_panel.addWidget(refresh_btn) + + top_panel.addStretch() + layout.addLayout(top_panel) + + # Область прокрутки для категорий + scroll_area = QScrollArea() + scroll_area.setWidgetResizable(True) + scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + + # Контейнер для категорий + categories_widget = QWidget() + self.categories_layout = QVBoxLayout(categories_widget) + + # Добавляем тестовые категории + test_categories = { + "Стили": ["Фотореалистичный", "Аниме", "Масляная живопись", "Акварель"], + "Освещение": ["Дневной свет", "Закат", "Ночное освещение", "Студийный свет"], + "Композиция": ["Крупный план", "Панорама", "Портрет", "Пейзаж"] + } + + for title, prompts in test_categories.items(): + category = PromptCategory(title, prompts) + self.categories_layout.addWidget(category) + + self.categories_layout.addStretch() + scroll_area.setWidget(categories_widget) + layout.addWidget(scroll_area) + + # Применяем стили + self.setStyleSheet(StyleConstants.get_base_styles('light')) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 12a1b6b..2dd2a27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,14 @@ -PyQt6>=6.4.0 -requests>=2.31.0 \ No newline at end of file +# requirements.txt + +certifi==2025.1.31 +charset-normalizer==3.4.1 +dotenv==0.9.9 +idna==3.10 +pillow==11.1.0 +PyQt6==6.8.1 +PyQt6-Qt6==6.8.2 +PyQt6_sip==13.10.0 +python-dotenv==1.0.1 +requests==2.32.3 +urllib3==2.3.0 +websockets==15.0.1 diff --git a/resources/icons/add.svg b/resources/icons/add.svg new file mode 100644 index 0000000..5e9305f --- /dev/null +++ b/resources/icons/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/close.svg b/resources/icons/close.svg new file mode 100644 index 0000000..0e17498 --- /dev/null +++ b/resources/icons/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/delete.svg b/resources/icons/delete.svg new file mode 100644 index 0000000..6f8dc27 --- /dev/null +++ b/resources/icons/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/generate.svg b/resources/icons/generate.svg new file mode 100644 index 0000000..798e8c1 --- /dev/null +++ b/resources/icons/generate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/home.svg b/resources/icons/home.svg new file mode 100644 index 0000000..f56b9ca --- /dev/null +++ b/resources/icons/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/image.svg b/resources/icons/image.svg new file mode 100644 index 0000000..1200c74 --- /dev/null +++ b/resources/icons/image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/models.svg b/resources/icons/models.svg new file mode 100644 index 0000000..0142fba --- /dev/null +++ b/resources/icons/models.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/refresh.svg b/resources/icons/refresh.svg new file mode 100644 index 0000000..939a159 --- /dev/null +++ b/resources/icons/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/save.svg b/resources/icons/save.svg new file mode 100644 index 0000000..6a1f4d1 --- /dev/null +++ b/resources/icons/save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/settings.svg b/resources/icons/settings.svg new file mode 100644 index 0000000..5202f4a --- /dev/null +++ b/resources/icons/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/success.svg b/resources/icons/success.svg new file mode 100644 index 0000000..bb0c2dd --- /dev/null +++ b/resources/icons/success.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/scripts/__pycache__/download_resources.cpython-310.pyc b/scripts/__pycache__/download_resources.cpython-310.pyc index dd964a3ebe5da7e55f2ebecfccac58352e28ab3c..d229bb0fccf5d89aceab3c58e659977b34278ba2 100644 GIT binary patch literal 2044 zcma)6&5zqe6rUM8iIePSRa8NX6!B3oDDeexSXBtAZ~&ndq6I{>$ap=I#Jm1TXU5%b z3oZ@=_EuOalS`k8%9_<0?g=t4&k#UbjdF9~r(x&)Utqiaxunbc&YXVMC-9+=$< ztx@X$b*r>a8}O|$i#E3jf0_-Nh6h54>02ZfRHurP-(^og1| zepEOr;ET{i4BhBSi4Jjwj_{adTlw9o<60|yUd?|yxt`z7ztbT3{mEW_y9JQ5 z;I~>MvesI+YlX$xm6Qo73Zu_tvBJGTFt?X*S4dB$qG;~$Kr(l8S29u5{3MnvmPKXA z1NhY6yyml^43gM3xdD4~l}iOGhDj_~f!Phjm%#SND;L)`hCJC~z7!jPy%{ps8wMM~ z=fMz6G}(#6#G@{(O;YYN(HZU*i&Jwi2w4Sy#3|?qX{=kCn{1EX9!NP9YmU%fO9@uCuK(|{LM zy|2(&vW;$CN9Mvz*HS}Q2}2uQr4G$l*)1!O85Y1 zgr*tz1P1@bfD*S7wh}dM(gnImm%eTQFIZ{s4fOHq1{ssFk)ezLPiAHw8b?U9rI{I- zsd&0_jxGaBE9uj)%?Xx34R`W;`CVvtX88%AoW*6n3Ts9$JmLe2vZE$~-fo975%gmx zqJc9=BGwUC`*R)rbhC6kKL^oI`Wmo3$1jMyK5GxdRQ#{~r;hdo?iGApo;U*DUlI_;D5f=2P=ypLEOM( z&-|0C`Y$Zkjl3XsUAxYe2-W=~2Vt;T-U%du+g?bnqt&vVE>jV@?u`DG&bht>tP7Cf cG-R(~FbQ>X3oXFLr-;?Cn%0>rgkb*lH`=j(4*&oF literal 3169 zcmdT`&2Jk;6yGm9>wGm-EtQ~xkq<~dc(yc2HH8CX?l+SN8CS#lG+cH}FfWb_xXCSA_RvG%bYR?58By^?6?C>K%KBUB;g zY|0x_3*O$8HsqGPBEuW}-Bn;Sv7xkNCy5cYrEV$P68j`noqb=jLS2_m*W(5Sk z%Po6hrLky~gKCblD$9Ab(4{$QH*-~+@um}$S&o~^E_uGoavyMoYc}=lMc*~TaB2Ou zBcjGTATRnVdK~@OzSZ80eugnL)~f zD^65b9goII!3v8Lb&A!;I(4r%Tn4(-WjBn6SZIe0Rw@UM8*4$`t;LBZ^+GouD1#O7 znn})&^k^@^;(SU_FPb`UmKxNLg|Jjd&~X>69@Ll{%S#U>dKzF}j$b^#P^ZC)TMpR* ze1hGQUH2APnR<1IoS<3r1KTO}Tp9J7@kme1{Ul(By@g6wba_0u zEfpu>Qm8q4OSvyOsRyb!5s8-O3_3&3@Ll!Zh&TbsmU?XbUpNr|nlmEojCSl?KP_VY z#O3u9JtlGXiS^LT>%NfOa zA=s%xn%ori9{uLj{+9AKg^q<6lmr8O-t0`-qh;SEWeiRk6KPV$uxQX?+Jpf7bX1NZ z*D?jGlf=xE31XSY@%p>^s>Wg;GbVWB#PBzGDI8#>8?xrKF%CX#)0jl4@rp-mo*0D! zx>J^KSVk3+R^O|+&r1YE4T5GU5 z{qA9SI2-_etSfjDSPr1h3e14sMNRTT#Fuv*Xuf^{yu-;pF%V9eS#z$i&q&td=euVZ zy~=Tr$BjuceFSmW&pv(omO2poO?Q|E=3{sk+XZuTN1WgTB#7?AOb%ft)*3J$Mn^h3 zbeIF-iSKBSy?x9_c^2W)+mS;Xxfd5x*0p1tgK1*U^@oSxqUVg$Ug6)ZJF_b###J~qV4DzGMAr_yX-{2667gQA=r(c zwl~STiu5Ozo9l^2xRjkjMyk6tWEn8fKt3!*Uw4&}E;UX-LXZ)4&Fw~yGXo-xq5Q`k zCyA9+3kJ^rhVb)L-C?5aCI1guDIL?+Ww6gdh##pm

diff --git a/scripts/download_resources.py b/scripts/download_resources.py index b08c0f6..495c87e 100644 --- a/scripts/download_resources.py +++ b/scripts/download_resources.py @@ -1,50 +1,50 @@ -import os import requests from pathlib import Path +import os + +def download_file(url: str, path: Path): + """Загрузка файла по URL""" + try: + response = requests.get(url) + response.raise_for_status() + path.write_bytes(response.content) + print(f"Загружен файл: {path}") + except Exception as e: + print(f"Ошибка при загрузке {path}: {e}") def download_font(): - # Создаем директории если они не существуют - resources_dir = Path("resources") - fonts_dir = resources_dir / "fonts" + """Загрузка шрифта Inter""" + fonts_dir = Path("resources/fonts") fonts_dir.mkdir(parents=True, exist_ok=True) - # URL для загрузки шрифта font_url = "https://github.com/rsms/inter/raw/master/docs/font-files/InterVariable.ttf" font_path = fonts_dir / "InterVariable.ttf" - # Загружаем шрифт если его еще нет if not font_path.exists(): - print("Загрузка шрифта Inter...") - response = requests.get(font_url) - if response.status_code == 200: - with open(font_path, "wb") as f: - f.write(response.content) - print(f"Шрифт успешно загружен в {font_path}") - else: - print(f"Ошибка при загрузке шрифта: {response.status_code}") + download_file(font_url, font_path) def download_icons(): - # Создаем директорию для иконок + """Загрузка иконок""" icons_dir = Path("resources/icons") icons_dir.mkdir(parents=True, exist_ok=True) - # Словарь с иконками и их SVG содержимым icons = { - "home.svg": """""", - - "image.svg": """""", - - "settings.svg": """""" + "home.svg": "https://api.iconify.design/mdi/home.svg", + "models.svg": "https://api.iconify.design/mdi/cube.svg", + "settings.svg": "https://api.iconify.design/mdi/cog.svg", + "generate.svg": "https://api.iconify.design/mdi/image-plus.svg", + "add.svg": "https://api.iconify.design/mdi/plus.svg", + "delete.svg": "https://api.iconify.design/mdi/delete.svg", + "refresh.svg": "https://api.iconify.design/mdi/refresh.svg", + "save.svg": "https://api.iconify.design/mdi/content-save.svg", + "close.svg": "https://api.iconify.design/mdi/close.svg", + "success.svg": "https://api.iconify.design/mdi/check-circle.svg", } - # Сохраняем иконки - for filename, svg_content in icons.items(): + for filename, url in icons.items(): icon_path = icons_dir / filename if not icon_path.exists(): - print(f"Создаем иконку {filename}...") - with open(icon_path, "w", encoding="utf-8") as f: - f.write(svg_content) - print(f"Иконка {filename} создана") + download_file(url, icon_path) if __name__ == "__main__": download_font() diff --git a/server.js b/server.js index f580630..6578781 100644 --- a/server.js +++ b/server.js @@ -6,95 +6,88 @@ const app = express(); const port = 3000; // Конфигурация API Stable Diffusion -const SD_API_URL = 'http://localhost:7860'; +const SD_API_URL = process.env.SD_API_URL || 'http://localhost:7860'; app.use(cors()); app.use(express.json()); -// Прокси для txt2img с отслеживанием прогресса +// Middleware для логирования запросов +app.use((req, res, next) => { + console.log(`${req.method} ${req.path}`); + next(); +}); + +// Прокси для txt2img app.post('/api/txt2img', async (req, res) => { try { - // Отправляем запрос на генерацию - const generationPromise = axios.post(`${SD_API_URL}/sdapi/v1/txt2img`, req.body); - - // Начинаем отслеживать прогресс сразу - let isGenerating = true; - let lastProgress = 0; - - while (isGenerating) { - try { - const progressResponse = await axios.get(`${SD_API_URL}/sdapi/v1/progress`); - const progress = progressResponse.data; - - if (progress.progress >= 1.0) { - isGenerating = false; - } - - // Если прогресс изменился, обновляем lastProgress - if (progress.progress !== lastProgress) { - lastProgress = progress.progress; - console.log(`Прогресс генерации: ${Math.round(progress.progress * 100)}%`); - } - - await new Promise(resolve => setTimeout(resolve, 100)); - } catch (error) { - console.error('Ошибка при получении прогресса:', error); - break; - } - } - - // Ждем завершения генерации - const response = await generationPromise; + const response = await axios.post(`${SD_API_URL}/sdapi/v1/txt2img`, req.body); res.json(response.data); } catch (error) { console.error('Ошибка при запросе к Stable Diffusion API:', error); - res.status(500).json({ error: 'Ошибка при генерации изображения' }); + res.status(500).json({ + error: 'Ошибка при генерации изображения', + details: error.message + }); } }); -// Прокси для проверки прогресса +// Прокси для получения прогресса app.get('/api/progress', async (req, res) => { try { const response = await axios.get(`${SD_API_URL}/sdapi/v1/progress`); - const progress = response.data; - - // Добавляем дополнительную информацию о прогрессе - const result = { - ...progress, - percentage: Math.round(progress.progress * 100), - current_step: progress.state?.sampling_step || 0, - total_steps: progress.state?.sampling_steps || 1 - }; - - res.json(result); + res.json({ + ...response.data, + percentage: Math.round(response.data.progress * 100) + }); } catch (error) { console.error('Ошибка при получении прогресса:', error); - res.status(500).json({ error: 'Ошибка при получении прогресса' }); + res.status(500).json({ + error: 'Ошибка при получении прогресса', + details: error.message + }); } }); -// Прокси для получения моделей -app.get('/api/sd-models', async (req, res) => { +// Прокси для получения списка моделей +app.get('/api/models', async (req, res) => { try { const response = await axios.get(`${SD_API_URL}/sdapi/v1/sd-models`); res.json(response.data); } catch (error) { console.error('Ошибка при получении списка моделей:', error); - res.status(500).json({ error: 'Ошибка при получении списка моделей' }); + res.status(500).json({ + error: 'Ошибка при получении списка моделей', + details: error.message + }); } }); -// Прокси для получения сэмплеров -app.get('/api/samplers', async (req, res) => { +// Прокси для изменения модели +app.post('/api/models/switch', async (req, res) => { try { - const response = await axios.get(`${SD_API_URL}/sdapi/v1/samplers`); - res.json(response.data); + const response = await axios.post(`${SD_API_URL}/sdapi/v1/options`, { + sd_model_checkpoint: req.body.model_name + }); + res.json({ success: true }); } catch (error) { - console.error('Ошибка при получении списка сэмплеров:', error); - res.status(500).json({ error: 'Ошибка при получении списка сэмплеров' }); + console.error('Ошибка при переключении модели:', error); + res.status(500).json({ + error: 'Ошибка при переключении модели', + details: error.message + }); } }); +// Обработка ошибок +app.use((err, req, res, next) => { + console.error(err.stack); + res.status(500).json({ + error: 'Внутренняя ошибка сервера', + details: err.message + }); +}); + app.listen(port, () => { console.log(`Сервер запущен на порту ${port}`); + console.log(`Stable Diffusion API URL: ${SD_API_URL}`); }); \ No newline at end of file diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/INSTALLER b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/INSTALLER similarity index 100% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/INSTALLER rename to venv/Lib/site-packages/dotenv-0.9.9.dist-info/INSTALLER diff --git a/venv/Lib/site-packages/dotenv-0.9.9.dist-info/LICENSE b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/LICENSE new file mode 100644 index 0000000..0452e84 --- /dev/null +++ b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Pedro Burón + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/venv/Lib/site-packages/dotenv-0.9.9.dist-info/METADATA b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/METADATA new file mode 100644 index 0000000..273e7f9 --- /dev/null +++ b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/METADATA @@ -0,0 +1,14 @@ +Metadata-Version: 2.1 +Name: dotenv +Version: 0.9.9 +Summary: Deprecated package +Home-page: https://github.com/pedroburon/dotenv +Author: Pedro Burón +Author-email: pedroburonv@gmail.com +License: UNKNOWN +Platform: UNKNOWN +License-File: LICENSE +Requires-Dist: python-dotenv + +UNKNOWN + diff --git a/venv/Lib/site-packages/dotenv-0.9.9.dist-info/RECORD b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/RECORD new file mode 100644 index 0000000..a2d7c7b --- /dev/null +++ b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/RECORD @@ -0,0 +1,7 @@ +dotenv-0.9.9.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +dotenv-0.9.9.dist-info/LICENSE,sha256=UDN9gmLB0tw_cK1WQ5POBgI5Iu13Bt4kf9VSMrrjJ7c,1069 +dotenv-0.9.9.dist-info/METADATA,sha256=C-L93MBAM6T9nTEUOLcRWO_CuLfoo4Zd9WIpxnMu4e0,279 +dotenv-0.9.9.dist-info/RECORD,, +dotenv-0.9.9.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +dotenv-0.9.9.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110 +dotenv-0.9.9.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/REQUESTED b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/REQUESTED similarity index 100% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/REQUESTED rename to venv/Lib/site-packages/dotenv-0.9.9.dist-info/REQUESTED diff --git a/venv/Lib/site-packages/dotenv-0.9.9.dist-info/WHEEL b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/WHEEL new file mode 100644 index 0000000..0c3c990 --- /dev/null +++ b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.45.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/dotenv-0.9.9.dist-info/top_level.txt b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/top_level.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/dotenv-0.9.9.dist-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/dotenv/__init__.py b/venv/Lib/site-packages/dotenv/__init__.py new file mode 100644 index 0000000..7f4c631 --- /dev/null +++ b/venv/Lib/site-packages/dotenv/__init__.py @@ -0,0 +1,49 @@ +from typing import Any, Optional + +from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key, + unset_key) + + +def load_ipython_extension(ipython: Any) -> None: + from .ipython import load_ipython_extension + load_ipython_extension(ipython) + + +def get_cli_string( + path: Optional[str] = None, + action: Optional[str] = None, + key: Optional[str] = None, + value: Optional[str] = None, + quote: Optional[str] = None, +): + """Returns a string suitable for running as a shell script. + + Useful for converting a arguments passed to a fabric task + to be passed to a `local` or `run` command. + """ + command = ['dotenv'] + if quote: + command.append(f'-q {quote}') + if path: + command.append(f'-f {path}') + if action: + command.append(action) + if key: + command.append(key) + if value: + if ' ' in value: + command.append(f'"{value}"') + else: + command.append(value) + + return ' '.join(command).strip() + + +__all__ = ['get_cli_string', + 'load_dotenv', + 'dotenv_values', + 'get_key', + 'set_key', + 'unset_key', + 'find_dotenv', + 'load_ipython_extension'] diff --git a/venv/Lib/site-packages/dotenv/__main__.py b/venv/Lib/site-packages/dotenv/__main__.py new file mode 100644 index 0000000..3977f55 --- /dev/null +++ b/venv/Lib/site-packages/dotenv/__main__.py @@ -0,0 +1,6 @@ +"""Entry point for cli, enables execution with `python -m dotenv`""" + +from .cli import cli + +if __name__ == "__main__": + cli() diff --git a/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66d5faf73b8fec8f7776dc13157385de3d134182 GIT binary patch literal 1239 zcmY*ZJCEEp5GE;#yQ_Wpe0E+y5D2NVg)dc_LlD?-8(e?{X@muIJdwL6pG3(dwa6NB zleo-3Fbv$KGvJ@&imfXH`2}`fLu$`NDYmyO+1QAgc)ik4ZoW(WESUt){^*9^XlWYRtsl*}{Y)!>TjGxdf znXv0e+!PZ@BidV0(*D^O3jg@MfZ+X>8^=@#?%n3{7YNco z;LnMkf`OiUSO7dn`UbE!ckdssTHQR5g*7W<`B^1%-j=H^B)9s$JX@L4$~!GDF8D^8 z)sW%Wd0wj0=J`>(3ob|C%J>Loc!q<<(U#kD$9UoE<|1E?I26mp4?Cz`0qyXP7)X8| zGW`_d`wL*2iAg<6uGdv%x;n$Ab3J7U^%o zy10*?A`w4}yse7Ex*!XBiTn5pUy>_dQ}*b^kKs^E%2Q)?sWz$U%21+o-RM+zN_iy@ z2IsP>Qd8)%wMR*k0{v{{x~qa|(WtG|Hdv=zZ@OA4Ytoh*BSmT(*kR4jbXla9n~Sg- zlxOmP7N=EH@ai;$txsX^)3j*nnk#V>>@zl;&7a6iWQ zHcrTbXm79_2d2j$Yk$t#H;kTm@c#$x&p))yGCuLNTsUTTE!0c<3!ozaM{8cHVR^6* zK7z~lj(mT+2;vJHx>26<^ZGVxunLptMc>qc~y{LbGw^A*4WO35K5jNsv+Zy6^4 UGD7}g5&4@@@)wJfx3e$)0|Y8AEC2ui literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea78adc84a39f69cfc28d4d13972694ea93e17b4 GIT binary patch literal 306 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3393c9fb4bd8837383e85d729708400629485c26 GIT binary patch literal 1464 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..797dff82693076b9928bd98c97f55c57bedc98b4 GIT binary patch literal 6133 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8906b026cda3904484ae5f2be1201cdc701dd5c9 GIT binary patch literal 3522 zcma)9TaO&Y6|PI)=DOp>F}6d90}i-}?Odct!Lq@|kO&DD6f1t13~BXF)$GoAre|E; zy9!H>lxWEten*OsypR4rJk={tNO_OMOY)tX`Q78D#fPj-zhcNoqAfp z+0%;hG#gY;M7yRVUBAS1L;1JaAD9YM_&HOd7Akro+fDRTR24l{-8`160UcuM7+WE{iNVxX)$G5X|q~H4U zUpmuUpS%&TX>Q%Rv6L2LmF}en!@><;A059vTYKt$>{c=v=l#DXhpFkOyF=Y2AJ)GB z!d;Y{D$Uwlv9?fLOC_`i1f=qSfUg7P>k!yhbOdC?C7g|ppeKC2W8SW+2pCnYcdr=`G#gCx<9 zlf*W6#>M-i$xx4UR%jJV>*adbGZbC4R}Mg)F>?;$clYk!>P*adpu0uh$qVv5Nhkfz zq0SCFAM|%SdB4y%CTaIkx~KDw8W&Lfasg9*bMh%|o9QHZfeejMRe8ic9`K_Y`FL}t zwG#6-93*EsigVCIL%|VKN5fh6OqeZdpI>yiUb79+hVWrLJk*yU2R(I#=GRX^>)YOp&<_pVQz?NRw8B%ox8a}6~VPu zks$^wWz=wfM{Jvm;3{{$F}D>&d)ghQdEUj4jc>{10lGJ%Nl8SDr+h?{huD!lF^iqH zuOdX3&>{51O|Kn6sz6W7^blDMUDHz6wOmFXt<_Xp&^DAr+_h}@0nXEaWd30~JkX{F z19qM}7sAw?3x!O{OO~uo=NUIYMQ=PmA8Mb1g`n?e{US+ThSD8Sl^?a{J0l=w$}XM$ z;-fY}?{;mXp|IgEf`PEd1I`ZfB`=ic~l56jtykV2l5fxE?kk$s{Op5fjwDQ+e(tSL&yH) zhXZR7%mn8tuuKDeS5a~bwK|wn=Sx?C6*2m3q*|B*1KEJk5Ey+uU(_t;>dxbXo5mlSJIUZd{zuO22Vrvl+ zbK1sD^CC^VNEMOW&;b}aK|>Ik%T)cCDniZ5epVQ=+!6MFaFt^5Cn!0k7~*PEZp)_s ziZrC@qHKKR)LoR^pxUIU_K0GX@_R`4DgeEFB^^~m6+sGAMTh92#9vi4^i&{KLDjly zK&s*D1Wjk_xJ!a&FRsys^5`11(Zl&=WIak(Hk{vObIwwbE^OZ^1p2R0a!Sns2Z7Hm>^Ymkl-KUlB+8g822*^3$?_{7j(K46 zVx?>3*qx*5^(%AV?wD6F)7+%$RjN)!5JkanQCtLF*tF^YV)Qjk{$572f!7nnYZSCr z?Doyi$q>gQN9Yw~uan}Gg%p^-Ls`=KBI11E?^%2%j2&)t+pYKv++0d07qTS<9 z>{tpdiZCnpbm0On_SUX)QW*--)4);4+(mJ~o##zXnP>^z4`&D>>zQf7yg}MknmF?| z{{_bViY%z3ir8h|^yV3YG_xd1_vJ=9rWX%|eHSJF0@dGv#FQ6|a5~}dvQJ*87u!>D z!a6`~>Xky_Svd9ai!3q?N<`cv&%9R1l4vXcL61i734e&!QQ?(-i5&ApkW_k8{x~Z9 zk{$DDh_T@#X5O983)kln<*CHMj-fQY;=Q{v9lzqhknJ|=^)p3}0=yC@Y38z_A&0FT z>MV|&-!|wTm>kb_f0P#8ee2`0GX*{B)M{-TV8ULpf9hoI)+9B#UcRmK-(zw2q!oYj zcvIBzUc{fknTr6w5x>a2|Cl#1D&DrjXe-m*uA%(qUS~EaKBfN{3+|LzSfU>{y*X_7wyCe4OEpdDHete6t Zbh)j{T4bdV+>2WO-fpyNtrsp|_%HZio1y>! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-310.pyc b/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39d9dc3c3162a1cd3bf1d56570782d1ac61d7c4a GIT binary patch literal 177 zcmd1j<>g`kf;W$^q>BOR#~=<)p?Z7G%bhrRJ5z_+%!< v6la#C>J}s>XD6no7RRLImjEU7p=Rk7RNmsS$<0qG%}KQbIieV3Fb4wwwNWl$ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/dotenv/cli.py b/venv/Lib/site-packages/dotenv/cli.py new file mode 100644 index 0000000..65ead46 --- /dev/null +++ b/venv/Lib/site-packages/dotenv/cli.py @@ -0,0 +1,199 @@ +import json +import os +import shlex +import sys +from contextlib import contextmanager +from subprocess import Popen +from typing import Any, Dict, IO, Iterator, List + +try: + import click +except ImportError: + sys.stderr.write('It seems python-dotenv is not installed with cli option. \n' + 'Run pip install "python-dotenv[cli]" to fix this.') + sys.exit(1) + +from .main import dotenv_values, set_key, unset_key +from .version import __version__ + + +def enumerate_env(): + """ + Return a path for the ${pwd}/.env file. + + If pwd does not exist, return None. + """ + try: + cwd = os.getcwd() + except FileNotFoundError: + return None + path = os.path.join(cwd, '.env') + return path + + +@click.group() +@click.option('-f', '--file', default=enumerate_env(), + type=click.Path(file_okay=True), + help="Location of the .env file, defaults to .env file in current working directory.") +@click.option('-q', '--quote', default='always', + type=click.Choice(['always', 'never', 'auto']), + help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.") +@click.option('-e', '--export', default=False, + type=click.BOOL, + help="Whether to write the dot file as an executable bash script.") +@click.version_option(version=__version__) +@click.pass_context +def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: + """This script is used to set, get or unset values from a .env file.""" + ctx.obj = {'QUOTE': quote, 'EXPORT': export, 'FILE': file} + + +@contextmanager +def stream_file(path: os.PathLike) -> Iterator[IO[str]]: + """ + Open a file and yield the corresponding (decoded) stream. + + Exits with error code 2 if the file cannot be opened. + """ + + try: + with open(path) as stream: + yield stream + except OSError as exc: + print(f"Error opening env file: {exc}", file=sys.stderr) + exit(2) + + +@cli.command() +@click.pass_context +@click.option('--format', default='simple', + type=click.Choice(['simple', 'json', 'shell', 'export']), + help="The format in which to display the list. Default format is simple, " + "which displays name=value without quotes.") +def list(ctx: click.Context, format: bool) -> None: + """Display all the stored key/value.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + if format == 'json': + click.echo(json.dumps(values, indent=2, sort_keys=True)) + else: + prefix = 'export ' if format == 'export' else '' + for k in sorted(values): + v = values[k] + if v is not None: + if format in ('export', 'shell'): + v = shlex.quote(v) + click.echo(f'{prefix}{k}={v}') + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +@click.argument('value', required=True) +def set(ctx: click.Context, key: Any, value: Any) -> None: + """Store the given key/value.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + export = ctx.obj['EXPORT'] + success, key, value = set_key(file, key, value, quote, export) + if success: + click.echo(f'{key}={value}') + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def get(ctx: click.Context, key: Any) -> None: + """Retrieve the value for the given key.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + stored_value = values.get(key) + if stored_value: + click.echo(stored_value) + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def unset(ctx: click.Context, key: Any) -> None: + """Removes the given key.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + success, key = unset_key(file, key, quote) + if success: + click.echo(f"Successfully removed {key}") + else: + exit(1) + + +@cli.command(context_settings={'ignore_unknown_options': True}) +@click.pass_context +@click.option( + "--override/--no-override", + default=True, + help="Override variables from the environment file with those from the .env file.", +) +@click.argument('commandline', nargs=-1, type=click.UNPROCESSED) +def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: + """Run command with environment variables present.""" + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + f'Invalid value for \'-f\' "{file}" does not exist.', + ctx=ctx + ) + dotenv_as_dict = { + k: v + for (k, v) in dotenv_values(file).items() + if v is not None and (override or k not in os.environ) + } + + if not commandline: + click.echo('No command given.') + exit(1) + ret = run_command(commandline, dotenv_as_dict) + exit(ret) + + +def run_command(command: List[str], env: Dict[str, str]) -> int: + """Run command in sub process. + + Runs the command in a sub process with the variables from `env` + added in the current environment variables. + + Parameters + ---------- + command: List[str] + The command and it's parameters + env: Dict + The additional environment variables + + Returns + ------- + int + The return code of the command + + """ + # copy the current environment variables and add the vales from + # `env` + cmd_env = os.environ.copy() + cmd_env.update(env) + + p = Popen(command, + universal_newlines=True, + bufsize=0, + shell=False, + env=cmd_env) + _, _ = p.communicate() + + return p.returncode diff --git a/venv/Lib/site-packages/dotenv/ipython.py b/venv/Lib/site-packages/dotenv/ipython.py new file mode 100644 index 0000000..7df727c --- /dev/null +++ b/venv/Lib/site-packages/dotenv/ipython.py @@ -0,0 +1,39 @@ +from IPython.core.magic import Magics, line_magic, magics_class # type: ignore +from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore + parse_argstring) # type: ignore + +from .main import find_dotenv, load_dotenv + + +@magics_class +class IPythonDotEnv(Magics): + + @magic_arguments() + @argument( + '-o', '--override', action='store_true', + help="Indicate to override existing variables" + ) + @argument( + '-v', '--verbose', action='store_true', + help="Indicate function calls to be verbose" + ) + @argument('dotenv_path', nargs='?', type=str, default='.env', + help='Search in increasingly higher folders for the `dotenv_path`') + @line_magic + def dotenv(self, line): + args = parse_argstring(self.dotenv, line) + # Locate the .env file + dotenv_path = args.dotenv_path + try: + dotenv_path = find_dotenv(dotenv_path, True, True) + except IOError: + print("cannot find .env file") + return + + # Load the .env file + load_dotenv(dotenv_path, verbose=args.verbose, override=args.override) + + +def load_ipython_extension(ipython): + """Register the %dotenv magic.""" + ipython.register_magics(IPythonDotEnv) diff --git a/venv/Lib/site-packages/dotenv/main.py b/venv/Lib/site-packages/dotenv/main.py new file mode 100644 index 0000000..7bc5428 --- /dev/null +++ b/venv/Lib/site-packages/dotenv/main.py @@ -0,0 +1,392 @@ +import io +import logging +import os +import pathlib +import shutil +import sys +import tempfile +from collections import OrderedDict +from contextlib import contextmanager +from typing import (IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, + Union) + +from .parser import Binding, parse_stream +from .variables import parse_variables + +# A type alias for a string path to be used for the paths in this file. +# These paths may flow to `open()` and `shutil.move()`; `shutil.move()` +# only accepts string paths, not byte paths or file descriptors. See +# https://github.com/python/typeshed/pull/6832. +StrPath = Union[str, 'os.PathLike[str]'] + +logger = logging.getLogger(__name__) + + +def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]: + for mapping in mappings: + if mapping.error: + logger.warning( + "Python-dotenv could not parse statement starting at line %s", + mapping.original.line, + ) + yield mapping + + +class DotEnv: + def __init__( + self, + dotenv_path: Optional[StrPath], + stream: Optional[IO[str]] = None, + verbose: bool = False, + encoding: Optional[str] = None, + interpolate: bool = True, + override: bool = True, + ) -> None: + self.dotenv_path: Optional[StrPath] = dotenv_path + self.stream: Optional[IO[str]] = stream + self._dict: Optional[Dict[str, Optional[str]]] = None + self.verbose: bool = verbose + self.encoding: Optional[str] = encoding + self.interpolate: bool = interpolate + self.override: bool = override + + @contextmanager + def _get_stream(self) -> Iterator[IO[str]]: + if self.dotenv_path and os.path.isfile(self.dotenv_path): + with open(self.dotenv_path, encoding=self.encoding) as stream: + yield stream + elif self.stream is not None: + yield self.stream + else: + if self.verbose: + logger.info( + "Python-dotenv could not find configuration file %s.", + self.dotenv_path or '.env', + ) + yield io.StringIO('') + + def dict(self) -> Dict[str, Optional[str]]: + """Return dotenv as dict""" + if self._dict: + return self._dict + + raw_values = self.parse() + + if self.interpolate: + self._dict = OrderedDict(resolve_variables(raw_values, override=self.override)) + else: + self._dict = OrderedDict(raw_values) + + return self._dict + + def parse(self) -> Iterator[Tuple[str, Optional[str]]]: + with self._get_stream() as stream: + for mapping in with_warn_for_invalid_lines(parse_stream(stream)): + if mapping.key is not None: + yield mapping.key, mapping.value + + def set_as_environment_variables(self) -> bool: + """ + Load the current dotenv as system environment variable. + """ + if not self.dict(): + return False + + for k, v in self.dict().items(): + if k in os.environ and not self.override: + continue + if v is not None: + os.environ[k] = v + + return True + + def get(self, key: str) -> Optional[str]: + """ + """ + data = self.dict() + + if key in data: + return data[key] + + if self.verbose: + logger.warning("Key %s not found in %s.", key, self.dotenv_path) + + return None + + +def get_key( + dotenv_path: StrPath, + key_to_get: str, + encoding: Optional[str] = "utf-8", +) -> Optional[str]: + """ + Get the value of a given key from the given .env. + + Returns `None` if the key isn't found or doesn't have a value. + """ + return DotEnv(dotenv_path, verbose=True, encoding=encoding).get(key_to_get) + + +@contextmanager +def rewrite( + path: StrPath, + encoding: Optional[str], +) -> Iterator[Tuple[IO[str], IO[str]]]: + pathlib.Path(path).touch() + + with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest: + error = None + try: + with open(path, encoding=encoding) as source: + yield (source, dest) + except BaseException as err: + error = err + + if error is None: + shutil.move(dest.name, path) + else: + os.unlink(dest.name) + raise error from None + + +def set_key( + dotenv_path: StrPath, + key_to_set: str, + value_to_set: str, + quote_mode: str = "always", + export: bool = False, + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str, str]: + """ + Adds or Updates a key/value to the given .env + + If the .env path given doesn't exist, fails instead of risking creating + an orphan .env somewhere in the filesystem + """ + if quote_mode not in ("always", "auto", "never"): + raise ValueError(f"Unknown quote_mode: {quote_mode}") + + quote = ( + quote_mode == "always" + or (quote_mode == "auto" and not value_to_set.isalnum()) + ) + + if quote: + value_out = "'{}'".format(value_to_set.replace("'", "\\'")) + else: + value_out = value_to_set + if export: + line_out = f'export {key_to_set}={value_out}\n' + else: + line_out = f"{key_to_set}={value_out}\n" + + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + replaced = False + missing_newline = False + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_set: + dest.write(line_out) + replaced = True + else: + dest.write(mapping.original.string) + missing_newline = not mapping.original.string.endswith("\n") + if not replaced: + if missing_newline: + dest.write("\n") + dest.write(line_out) + + return True, key_to_set, value_to_set + + +def unset_key( + dotenv_path: StrPath, + key_to_unset: str, + quote_mode: str = "always", + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str]: + """ + Removes a given key from the given `.env` file. + + If the .env path given doesn't exist, fails. + If the given key doesn't exist in the .env, fails. + """ + if not os.path.exists(dotenv_path): + logger.warning("Can't delete from %s - it doesn't exist.", dotenv_path) + return None, key_to_unset + + removed = False + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_unset: + removed = True + else: + dest.write(mapping.original.string) + + if not removed: + logger.warning("Key %s not removed from %s - key doesn't exist.", key_to_unset, dotenv_path) + return None, key_to_unset + + return removed, key_to_unset + + +def resolve_variables( + values: Iterable[Tuple[str, Optional[str]]], + override: bool, +) -> Mapping[str, Optional[str]]: + new_values: Dict[str, Optional[str]] = {} + + for (name, value) in values: + if value is None: + result = None + else: + atoms = parse_variables(value) + env: Dict[str, Optional[str]] = {} + if override: + env.update(os.environ) # type: ignore + env.update(new_values) + else: + env.update(new_values) + env.update(os.environ) # type: ignore + result = "".join(atom.resolve(env) for atom in atoms) + + new_values[name] = result + + return new_values + + +def _walk_to_root(path: str) -> Iterator[str]: + """ + Yield directories starting from the given directory up to the root + """ + if not os.path.exists(path): + raise IOError('Starting path not found') + + if os.path.isfile(path): + path = os.path.dirname(path) + + last_dir = None + current_dir = os.path.abspath(path) + while last_dir != current_dir: + yield current_dir + parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir)) + last_dir, current_dir = current_dir, parent_dir + + +def find_dotenv( + filename: str = '.env', + raise_error_if_not_found: bool = False, + usecwd: bool = False, +) -> str: + """ + Search in increasingly higher folders for the given file + + Returns path to the file if found, or an empty string otherwise + """ + + def _is_interactive(): + """ Decide whether this is running in a REPL or IPython notebook """ + try: + main = __import__('__main__', None, None, fromlist=['__file__']) + except ModuleNotFoundError: + return False + return not hasattr(main, '__file__') + + if usecwd or _is_interactive() or getattr(sys, 'frozen', False): + # Should work without __file__, e.g. in REPL or IPython notebook. + path = os.getcwd() + else: + # will work for .py files + frame = sys._getframe() + current_file = __file__ + + while frame.f_code.co_filename == current_file or not os.path.exists( + frame.f_code.co_filename + ): + assert frame.f_back is not None + frame = frame.f_back + frame_filename = frame.f_code.co_filename + path = os.path.dirname(os.path.abspath(frame_filename)) + + for dirname in _walk_to_root(path): + check_path = os.path.join(dirname, filename) + if os.path.isfile(check_path): + return check_path + + if raise_error_if_not_found: + raise IOError('File not found') + + return '' + + +def load_dotenv( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + override: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> bool: + """Parse a .env file and then load all the variables found as environment variables. + + Parameters: + dotenv_path: Absolute or relative path to .env file. + stream: Text stream (such as `io.StringIO`) with .env content, used if + `dotenv_path` is `None`. + verbose: Whether to output a warning the .env file is missing. + override: Whether to override the system environment variables with the variables + from the `.env` file. + encoding: Encoding to be used to read the file. + Returns: + Bool: True if at least one environment variable is set else False + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + dotenv = DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=override, + encoding=encoding, + ) + return dotenv.set_as_environment_variables() + + +def dotenv_values( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> Dict[str, Optional[str]]: + """ + Parse a .env file and return its content as a dict. + + The returned dict will have `None` values for keys without values in the .env file. + For example, `foo=bar` results in `{"foo": "bar"}` whereas `foo` alone results in + `{"foo": None}` + + Parameters: + dotenv_path: Absolute or relative path to the .env file. + stream: `StringIO` object with .env content, used if `dotenv_path` is `None`. + verbose: Whether to output a warning if the .env file is missing. + encoding: Encoding to be used to read the file. + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + return DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict() diff --git a/venv/Lib/site-packages/dotenv/parser.py b/venv/Lib/site-packages/dotenv/parser.py new file mode 100644 index 0000000..735f14a --- /dev/null +++ b/venv/Lib/site-packages/dotenv/parser.py @@ -0,0 +1,175 @@ +import codecs +import re +from typing import (IO, Iterator, Match, NamedTuple, Optional, # noqa:F401 + Pattern, Sequence, Tuple) + + +def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: + return re.compile(string, re.UNICODE | extra_flags) + + +_newline = make_regex(r"(\r\n|\n|\r)") +_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE) +_whitespace = make_regex(r"[^\S\r\n]*") +_export = make_regex(r"(?:export[^\S\r\n]+)?") +_single_quoted_key = make_regex(r"'([^']+)'") +_unquoted_key = make_regex(r"([^=\#\s]+)") +_equal_sign = make_regex(r"(=[^\S\r\n]*)") +_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'") +_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"') +_unquoted_value = make_regex(r"([^\r\n]*)") +_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?") +_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)") +_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?") +_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") +_single_quote_escapes = make_regex(r"\\[\\']") + + +class Original(NamedTuple): + string: str + line: int + + +class Binding(NamedTuple): + key: Optional[str] + value: Optional[str] + original: Original + error: bool + + +class Position: + def __init__(self, chars: int, line: int) -> None: + self.chars = chars + self.line = line + + @classmethod + def start(cls) -> "Position": + return cls(chars=0, line=1) + + def set(self, other: "Position") -> None: + self.chars = other.chars + self.line = other.line + + def advance(self, string: str) -> None: + self.chars += len(string) + self.line += len(re.findall(_newline, string)) + + +class Error(Exception): + pass + + +class Reader: + def __init__(self, stream: IO[str]) -> None: + self.string = stream.read() + self.position = Position.start() + self.mark = Position.start() + + def has_next(self) -> bool: + return self.position.chars < len(self.string) + + def set_mark(self) -> None: + self.mark.set(self.position) + + def get_marked(self) -> Original: + return Original( + string=self.string[self.mark.chars:self.position.chars], + line=self.mark.line, + ) + + def peek(self, count: int) -> str: + return self.string[self.position.chars:self.position.chars + count] + + def read(self, count: int) -> str: + result = self.string[self.position.chars:self.position.chars + count] + if len(result) < count: + raise Error("read: End of string") + self.position.advance(result) + return result + + def read_regex(self, regex: Pattern[str]) -> Sequence[str]: + match = regex.match(self.string, self.position.chars) + if match is None: + raise Error("read_regex: Pattern not found") + self.position.advance(self.string[match.start():match.end()]) + return match.groups() + + +def decode_escapes(regex: Pattern[str], string: str) -> str: + def decode_match(match: Match[str]) -> str: + return codecs.decode(match.group(0), 'unicode-escape') # type: ignore + + return regex.sub(decode_match, string) + + +def parse_key(reader: Reader) -> Optional[str]: + char = reader.peek(1) + if char == "#": + return None + elif char == "'": + (key,) = reader.read_regex(_single_quoted_key) + else: + (key,) = reader.read_regex(_unquoted_key) + return key + + +def parse_unquoted_value(reader: Reader) -> str: + (part,) = reader.read_regex(_unquoted_value) + return re.sub(r"\s+#.*", "", part).rstrip() + + +def parse_value(reader: Reader) -> str: + char = reader.peek(1) + if char == u"'": + (value,) = reader.read_regex(_single_quoted_value) + return decode_escapes(_single_quote_escapes, value) + elif char == u'"': + (value,) = reader.read_regex(_double_quoted_value) + return decode_escapes(_double_quote_escapes, value) + elif char in (u"", u"\n", u"\r"): + return u"" + else: + return parse_unquoted_value(reader) + + +def parse_binding(reader: Reader) -> Binding: + reader.set_mark() + try: + reader.read_regex(_multiline_whitespace) + if not reader.has_next(): + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=False, + ) + reader.read_regex(_export) + key = parse_key(reader) + reader.read_regex(_whitespace) + if reader.peek(1) == "=": + reader.read_regex(_equal_sign) + value: Optional[str] = parse_value(reader) + else: + value = None + reader.read_regex(_comment) + reader.read_regex(_end_of_line) + return Binding( + key=key, + value=value, + original=reader.get_marked(), + error=False, + ) + except Error: + reader.read_regex(_rest_of_line) + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=True, + ) + + +def parse_stream(stream: IO[str]) -> Iterator[Binding]: + reader = Reader(stream) + while reader.has_next(): + yield parse_binding(reader) diff --git a/venv/Lib/site-packages/dotenv/py.typed b/venv/Lib/site-packages/dotenv/py.typed new file mode 100644 index 0000000..7632ecf --- /dev/null +++ b/venv/Lib/site-packages/dotenv/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 diff --git a/venv/Lib/site-packages/dotenv/variables.py b/venv/Lib/site-packages/dotenv/variables.py new file mode 100644 index 0000000..667f2f2 --- /dev/null +++ b/venv/Lib/site-packages/dotenv/variables.py @@ -0,0 +1,86 @@ +import re +from abc import ABCMeta, abstractmethod +from typing import Iterator, Mapping, Optional, Pattern + +_posix_variable: Pattern[str] = re.compile( + r""" + \$\{ + (?P[^\}:]*) + (?::- + (?P[^\}]*) + )? + \} + """, + re.VERBOSE, +) + + +class Atom(metaclass=ABCMeta): + def __ne__(self, other: object) -> bool: + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result + + @abstractmethod + def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... + + +class Literal(Atom): + def __init__(self, value: str) -> None: + self.value = value + + def __repr__(self) -> str: + return f"Literal(value={self.value})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return self.value == other.value + + def __hash__(self) -> int: + return hash((self.__class__, self.value)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + return self.value + + +class Variable(Atom): + def __init__(self, name: str, default: Optional[str]) -> None: + self.name = name + self.default = default + + def __repr__(self) -> str: + return f"Variable(name={self.name}, default={self.default})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return (self.name, self.default) == (other.name, other.default) + + def __hash__(self) -> int: + return hash((self.__class__, self.name, self.default)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + default = self.default if self.default is not None else "" + result = env.get(self.name, default) + return result if result is not None else "" + + +def parse_variables(value: str) -> Iterator[Atom]: + cursor = 0 + + for match in _posix_variable.finditer(value): + (start, end) = match.span() + name = match["name"] + default = match["default"] + + if start > cursor: + yield Literal(value=value[cursor:start]) + + yield Variable(name=name, default=default) + cursor = end + + length = len(value) + if cursor < length: + yield Literal(value=value[cursor:length]) diff --git a/venv/Lib/site-packages/dotenv/version.py b/venv/Lib/site-packages/dotenv/version.py new file mode 100644 index 0000000..5c4105c --- /dev/null +++ b/venv/Lib/site-packages/dotenv/version.py @@ -0,0 +1 @@ +__version__ = "1.0.1" diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/RECORD b/venv/Lib/site-packages/pip-22.2.1.dist-info/RECORD deleted file mode 100644 index 50bbd33..0000000 --- a/venv/Lib/site-packages/pip-22.2.1.dist-info/RECORD +++ /dev/null @@ -1,992 +0,0 @@ -../../Scripts/pip.exe,sha256=wVTlSM1CoHzfPpDxEAOsp6Jjwv-I_iqzOCFudVcKfJI,107893 -../../Scripts/pip3.10.exe,sha256=AZt5rsH4BlFFFrekn19LvZKeuvhlzaPjf3hwlvXq6RQ,107893 -../../Scripts/pip3.exe,sha256=AZt5rsH4BlFFFrekn19LvZKeuvhlzaPjf3hwlvXq6RQ,107893 -pip-22.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip-22.2.1.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093 -pip-22.2.1.dist-info/METADATA,sha256=shj9XW4KG9MEp43PNu0VqMaNr0dbIBnk0SALqyhNu6Q,4197 -pip-22.2.1.dist-info/RECORD,, -pip-22.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip-22.2.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 -pip-22.2.1.dist-info/entry_points.txt,sha256=_ZUyZpzz1RdotcszCitH_lQ6yiWAKmaOcIkCEmkrePU,124 -pip-22.2.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip/__init__.py,sha256=TnK0qWewypiwM5sIDNYfy404XnpGnbemXiEH9cyPTWg,357 -pip/__main__.py,sha256=mXwWDftNLMKfwVqKFWGE_uuBZvGSIiUELhLkeysIuZc,1198 -pip/__pip-runner__.py,sha256=9cY5wjw19ypL7f1StHYjB9Ud2WqQvEcynma3hOoeIRU,1085 -pip/__pycache__/__init__.cpython-310.pyc,, -pip/__pycache__/__main__.cpython-310.pyc,, -pip/__pycache__/__pip-runner__.cpython-310.pyc,, -pip/_internal/__init__.py,sha256=nnFCuxrPMgALrIDxSoy-H6Zj4W4UY60D-uL1aJyq0pc,573 -pip/_internal/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/__pycache__/build_env.cpython-310.pyc,, -pip/_internal/__pycache__/cache.cpython-310.pyc,, -pip/_internal/__pycache__/configuration.cpython-310.pyc,, -pip/_internal/__pycache__/exceptions.cpython-310.pyc,, -pip/_internal/__pycache__/main.cpython-310.pyc,, -pip/_internal/__pycache__/pyproject.cpython-310.pyc,, -pip/_internal/__pycache__/self_outdated_check.cpython-310.pyc,, -pip/_internal/__pycache__/wheel_builder.cpython-310.pyc,, -pip/_internal/build_env.py,sha256=Io06wf8aNlP1FkDYCbbuVFPGWAMJNys7l_p7r9CmEKE,9535 -pip/_internal/cache.py,sha256=-FXxS81WOM-amtx3w7N8s20PfFIlHPX8X27FfOBql-I,10623 -pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 -pip/_internal/cli/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc,, -pip/_internal/cli/__pycache__/base_command.cpython-310.pyc,, -pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc,, -pip/_internal/cli/__pycache__/command_context.cpython-310.pyc,, -pip/_internal/cli/__pycache__/main.cpython-310.pyc,, -pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc,, -pip/_internal/cli/__pycache__/parser.cpython-310.pyc,, -pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc,, -pip/_internal/cli/__pycache__/req_command.cpython-310.pyc,, -pip/_internal/cli/__pycache__/spinners.cpython-310.pyc,, -pip/_internal/cli/__pycache__/status_codes.cpython-310.pyc,, -pip/_internal/cli/autocompletion.py,sha256=wY2JPZY2Eji1vhR7bVo-yCBPJ9LCy6P80iOAhZD1Vi8,6676 -pip/_internal/cli/base_command.py,sha256=EiHzq1RBubmgYkhsVgJLNc4Y18koPUS1TzMVJwpnYxc,8146 -pip/_internal/cli/cmdoptions.py,sha256=LKKpinHThNt7wtHqxwkWJpgCUcyQeTX0GUCqyXImAbc,29985 -pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774 -pip/_internal/cli/main.py,sha256=ioJ8IVlb2K1qLOxR-tXkee9lURhYV89CDM71MKag7YY,2472 -pip/_internal/cli/main_parser.py,sha256=Q9TnytfuC5Z2JSjBFWVGtEdYLFy7rukNIb04movHdAo,2614 -pip/_internal/cli/parser.py,sha256=tWP-K1uSxnJyXu3WE0kkH3niAYRBeuUaxeydhzOdhL4,10817 -pip/_internal/cli/progress_bars.py,sha256=So4mPoSjXkXiSHiTzzquH3VVyVD_njXlHJSExYPXAow,1968 -pip/_internal/cli/req_command.py,sha256=ypTutLv4j_efxC2f6C6aCQufxre-zaJdi5m_tWlLeBk,18172 -pip/_internal/cli/spinners.py,sha256=rs_NveD0wCoJ9GiJJmOjGC1UPVK8isOQpQsFVE899zQ,5098 -pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116 -pip/_internal/commands/__init__.py,sha256=5oRO9O3dM2vGuh0bFw4HOVletryrz5HHMmmPWwJrH9U,3882 -pip/_internal/commands/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/commands/__pycache__/cache.cpython-310.pyc,, -pip/_internal/commands/__pycache__/check.cpython-310.pyc,, -pip/_internal/commands/__pycache__/completion.cpython-310.pyc,, -pip/_internal/commands/__pycache__/configuration.cpython-310.pyc,, -pip/_internal/commands/__pycache__/debug.cpython-310.pyc,, -pip/_internal/commands/__pycache__/download.cpython-310.pyc,, -pip/_internal/commands/__pycache__/freeze.cpython-310.pyc,, -pip/_internal/commands/__pycache__/hash.cpython-310.pyc,, -pip/_internal/commands/__pycache__/help.cpython-310.pyc,, -pip/_internal/commands/__pycache__/index.cpython-310.pyc,, -pip/_internal/commands/__pycache__/inspect.cpython-310.pyc,, -pip/_internal/commands/__pycache__/install.cpython-310.pyc,, -pip/_internal/commands/__pycache__/list.cpython-310.pyc,, -pip/_internal/commands/__pycache__/search.cpython-310.pyc,, -pip/_internal/commands/__pycache__/show.cpython-310.pyc,, -pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc,, -pip/_internal/commands/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/commands/cache.py,sha256=muaT0mbL-ZUpn6AaushVAipzTiMwE4nV2BLbJBwt_KQ,7582 -pip/_internal/commands/check.py,sha256=0gjXR7j36xJT5cs2heYU_dfOfpnFfzX8OoPNNoKhqdM,1685 -pip/_internal/commands/completion.py,sha256=H0TJvGrdsoleuIyQKzJbicLFppYx2OZA0BLNpQDeFjI,4129 -pip/_internal/commands/configuration.py,sha256=ZJRO2YMzI5vPA2ADTWZrSsvGd4q880CylCUzEUJziZY,9500 -pip/_internal/commands/debug.py,sha256=kVjn-O1ixLk0webD0w9vfFFq_GCTUTd2hmLOnYtDCig,6573 -pip/_internal/commands/download.py,sha256=vLtEY3QqIAddjAOGvJJsbaHJg7Har5TPa4UuOOL6Gn8,5058 -pip/_internal/commands/freeze.py,sha256=gCjoD6foBZPBAAYx5t8zZLkJhsF_ZRtnb3dPuD7beO8,2951 -pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703 -pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132 -pip/_internal/commands/index.py,sha256=1VVXXj5MsI2qH-N7uniQQyVkg-KCn_RdjiyiUmkUS5U,4762 -pip/_internal/commands/inspect.py,sha256=mRJ9aIkBQN0IJ7Um8pzaxAzVPIgL8KfWHx1fWKJgUAQ,3374 -pip/_internal/commands/install.py,sha256=nyZCUv7Oi8rScPe4WENgQ8Vd5n3OHzBuj2tw6khg4Ss,30315 -pip/_internal/commands/list.py,sha256=wF2g5i4j_JyoRckO9FAeB7KhcFAnLboy0dL-G9fn7Eo,12148 -pip/_internal/commands/search.py,sha256=sbBZiARRc050QquOKcCvOr2K3XLsoYebLKZGRi__iUI,5697 -pip/_internal/commands/show.py,sha256=CJI8q4SSY0X346K1hi4Th8Nbyhl4nxPTBJUuzOlTaYE,6129 -pip/_internal/commands/uninstall.py,sha256=0JQhifYxecNrJAwoILFwjm9V1V3liXzNT-y4bgRXXPw,3680 -pip/_internal/commands/wheel.py,sha256=dar33wNjUyTN6Cy8PVxV5TerJS1u7pZmKoqgoYiQh7g,6307 -pip/_internal/configuration.py,sha256=uBKTus43pDIO6IzT2mLWQeROmHhtnoabhniKNjPYvD0,13529 -pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858 -pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/base.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/installed.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/distributions/base.py,sha256=jrF1Vi7eGyqFqMHrieh1PIOrGU7KeCxhYPZnbvtmvGY,1221 -pip/_internal/distributions/installed.py,sha256=NI2OgsgH9iBq9l5vB-56vOg5YsybOy-AU4VE5CSCO2I,729 -pip/_internal/distributions/sdist.py,sha256=SQBdkatXSigKGG_SaD0U0p1Jwdfrg26UCNcHgkXZfdA,6494 -pip/_internal/distributions/wheel.py,sha256=m-J4XO-gvFerlYsFzzSXYDvrx8tLZlJFTCgDxctn8ig,1164 -pip/_internal/exceptions.py,sha256=U-dV1ixkSz6NAU6Aw9dosKi2EzZ5D3BA7ilYZuTLKeU,20912 -pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 -pip/_internal/index/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/index/__pycache__/collector.cpython-310.pyc,, -pip/_internal/index/__pycache__/package_finder.cpython-310.pyc,, -pip/_internal/index/__pycache__/sources.cpython-310.pyc,, -pip/_internal/index/collector.py,sha256=UCB2bYQIbIV4IIcTWK7cfy8iYpdOIcDiNLGFDcL6c-A,20301 -pip/_internal/index/package_finder.py,sha256=kmcMu5_i-BP6v3NQGY0_am1ezxM2Gk4t00arZMmm4sc,37596 -pip/_internal/index/sources.py,sha256=SVyPitv08-Qalh2_Bk5diAJ9GAA_d-a93koouQodAG0,6557 -pip/_internal/locations/__init__.py,sha256=pxbyuIew0-ZMHs-aGfUgrNlYXdHTqvEJj_mM3UWiH1U,17461 -pip/_internal/locations/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc,, -pip/_internal/locations/__pycache__/_sysconfig.cpython-310.pyc,, -pip/_internal/locations/__pycache__/base.cpython-310.pyc,, -pip/_internal/locations/_distutils.py,sha256=6aYLJT475os90AQJ0w6YtgJcYN86aa60Ld27q8rkRK8,6254 -pip/_internal/locations/_sysconfig.py,sha256=nM-DiVHXWTxippdmN0MGVl5r7OIfIMy3vgDMlo8c_oo,7867 -pip/_internal/locations/base.py,sha256=ufyDqPwZ4jLbScD44u8AwTVI-3ft8O78UGrroQI5f68,2573 -pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340 -pip/_internal/metadata/__init__.py,sha256=IeqRXbTeSreqClORmjA_4CMjkWA-trWdss7Oyimwosw,3535 -pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/_json.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/base.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc,, -pip/_internal/metadata/_json.py,sha256=BTkWfFDrWFwuSodImjtbAh8wCL3isecbnjTb5E6UUDI,2595 -pip/_internal/metadata/base.py,sha256=gOjhT0Mk4f6hCa8hzZIQKynIwpHzydnm6krwGTHTVhI,24596 -pip/_internal/metadata/importlib/__init__.py,sha256=9ZVO8BoE7NEZPmoHp5Ap_NJo0HgNIezXXg-TFTtt3Z4,107 -pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_compat.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_dists.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_envs.cpython-310.pyc,, -pip/_internal/metadata/importlib/_compat.py,sha256=B_qZlMBcbf2VrjHw4Pz9gfk-c-W1Mzp2u_GAzoWWuLE,1493 -pip/_internal/metadata/importlib/_dists.py,sha256=iEu6KvMdFIfq3ujQvsS0fvI9jDbp1qFC9SmOySfn_fY,7456 -pip/_internal/metadata/importlib/_envs.py,sha256=-4O0PiYmxydf0e6upJ7X-_BR4DB46I_szlgx53hnJLs,7195 -pip/_internal/metadata/pkg_resources.py,sha256=RfU--nYrkHAYJXfpoviyBHJA5b9Mw3Dc5HpeYwki1gE,9289 -pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 -pip/_internal/models/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/models/__pycache__/candidate.cpython-310.pyc,, -pip/_internal/models/__pycache__/direct_url.cpython-310.pyc,, -pip/_internal/models/__pycache__/format_control.cpython-310.pyc,, -pip/_internal/models/__pycache__/index.cpython-310.pyc,, -pip/_internal/models/__pycache__/installation_report.cpython-310.pyc,, -pip/_internal/models/__pycache__/link.cpython-310.pyc,, -pip/_internal/models/__pycache__/scheme.cpython-310.pyc,, -pip/_internal/models/__pycache__/search_scope.cpython-310.pyc,, -pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc,, -pip/_internal/models/__pycache__/target_python.cpython-310.pyc,, -pip/_internal/models/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/models/candidate.py,sha256=6pcABsaR7CfIHlbJbr2_kMkVJFL_yrYjTx6SVWUnCPQ,990 -pip/_internal/models/direct_url.py,sha256=HLO0sL2aYB6n45bwmd72TDN05sLHJlOQI8M01l2SH3I,5877 -pip/_internal/models/format_control.py,sha256=DJpMYjxeYKKQdwNcML2_F0vtAh-qnKTYe-CpTxQe-4g,2520 -pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030 -pip/_internal/models/installation_report.py,sha256=ad1arqtxrSFBvWnm6mRqmG12HLV3pZZcZcHrlTFIiqU,2617 -pip/_internal/models/link.py,sha256=_5okBLOR7vshRltnD11SC3cyD0aSxOa0lMpKWIwQ5UY,10490 -pip/_internal/models/scheme.py,sha256=3EFQp_ICu_shH1-TBqhl0QAusKCPDFOlgHFeN4XowWs,738 -pip/_internal/models/search_scope.py,sha256=LwloG0PJAmtI1hFXIypsD95kWE9xfR5hf_a2v1Vw7sk,4520 -pip/_internal/models/selection_prefs.py,sha256=KZdi66gsR-_RUXUr9uejssk3rmTHrQVJWeNA2sV-VSY,1907 -pip/_internal/models/target_python.py,sha256=qKpZox7J8NAaPmDs5C_aniwfPDxzvpkrCKqfwndG87k,3858 -pip/_internal/models/wheel.py,sha256=X_fakLR3OGF7HhrhwVXCUN-1wBwVCT2Lz0o3NguT_GQ,3575 -pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 -pip/_internal/network/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/network/__pycache__/auth.cpython-310.pyc,, -pip/_internal/network/__pycache__/cache.cpython-310.pyc,, -pip/_internal/network/__pycache__/download.cpython-310.pyc,, -pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc,, -pip/_internal/network/__pycache__/session.cpython-310.pyc,, -pip/_internal/network/__pycache__/utils.cpython-310.pyc,, -pip/_internal/network/__pycache__/xmlrpc.cpython-310.pyc,, -pip/_internal/network/auth.py,sha256=a3C7Xaa8kTJjXkdi_wrUjqaySc8Z9Yz7U6QIbXfzMyc,12190 -pip/_internal/network/cache.py,sha256=hgXftU-eau4MWxHSLquTMzepYq5BPC2zhCkhN3glBy8,2145 -pip/_internal/network/download.py,sha256=HvDDq9bVqaN3jcS3DyVJHP7uTqFzbShdkf7NFSoHfkw,6096 -pip/_internal/network/lazy_wheel.py,sha256=7YsbcpwOLyXbwCbR484ikhG9-C1FbUVABekVSBS0zHc,7637 -pip/_internal/network/session.py,sha256=BpDOJ7_Xw5VkgPYWsePzcaqOfcyRZcB2AW7W0HGBST0,18443 -pip/_internal/network/utils.py,sha256=6A5SrUJEEUHxbGtbscwU2NpCyz-3ztiDlGWHpRRhsJ8,4073 -pip/_internal/network/xmlrpc.py,sha256=AzQgG4GgS152_cqmGr_Oz2MIXsCal-xfsis7fA7nmU0,1791 -pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/operations/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/__pycache__/check.cpython-310.pyc,, -pip/_internal/operations/__pycache__/freeze.cpython-310.pyc,, -pip/_internal/operations/__pycache__/prepare.cpython-310.pyc,, -pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/operations/build/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata_editable.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel_editable.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-310.pyc,, -pip/_internal/operations/build/build_tracker.py,sha256=vf81EwomN3xe9G8qRJED0VGqNikmRQRQoobNsxi5Xrs,4133 -pip/_internal/operations/build/metadata.py,sha256=ES_uRmAvhrNm_nDTpZxshBfUsvnXtkj-g_4rZrH9Rww,1404 -pip/_internal/operations/build/metadata_editable.py,sha256=_Rai0VZjxoeJUkjkuICrq45LtjwFoDOveosMYH43rKc,1456 -pip/_internal/operations/build/metadata_legacy.py,sha256=o-eU21As175hDC7dluM1fJJ_FqokTIShyWpjKaIpHZw,2198 -pip/_internal/operations/build/wheel.py,sha256=AO9XnTGhTgHtZmU8Dkbfo1OGr41rBuSDjIgAa4zUKgE,1063 -pip/_internal/operations/build/wheel_editable.py,sha256=TVETY-L_M_dSEKBhTIcQOP75zKVXw8tuq1U354Mm30A,1405 -pip/_internal/operations/build/wheel_legacy.py,sha256=C9j6rukgQI1n_JeQLoZGuDdfUwzCXShyIdPTp6edbMQ,3064 -pip/_internal/operations/check.py,sha256=ca4O9CkPt9Em9sLCf3H0iVt1GIcW7M8C0U5XooaBuT4,5109 -pip/_internal/operations/freeze.py,sha256=mwTZ2uML8aQgo3k8MR79a7SZmmmvdAJqdyaknKbavmg,9784 -pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 -pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/operations/install/editable_legacy.py,sha256=ee4kfJHNuzTdKItbfAsNOSEwq_vD7DRPGkBdK48yBhU,1354 -pip/_internal/operations/install/legacy.py,sha256=cHdcHebyzf8w7OaOLwcsTNSMSSV8WBoAPFLay_9CjE8,4105 -pip/_internal/operations/install/wheel.py,sha256=ZbmrarCh74tariXY8rgI56jbZ1BJ2Z6u5fZt4nt3Gmw,27379 -pip/_internal/operations/prepare.py,sha256=kvL-s1ZUs53g1JIzmJ62j8FwCO_fKWXN45pAtVuz0xE,22962 -pip/_internal/pyproject.py,sha256=ob0Gb0l12YLZNxjdpZGRfWHgjqhZTnSVv96RuJyNOfs,7074 -pip/_internal/req/__init__.py,sha256=rUQ9d_Sh3E5kNYqX9pkN0D06YL-LrtcbJQ-LiIonq08,2807 -pip/_internal/req/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/req/__pycache__/constructors.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_file.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_install.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_set.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc,, -pip/_internal/req/constructors.py,sha256=ypjtq1mOQ3d2mFkFPMf_6Mr8SLKeHQk3tUKHA1ddG0U,16611 -pip/_internal/req/req_file.py,sha256=Qgqx7qLfDO3ai72oO2U1u928_6Idajun5VFRWPZg3XM,17502 -pip/_internal/req/req_install.py,sha256=bOtpOZnDgmEst_QuWZRXViaPW1JJ1iAvO6vVFgFf0PI,33506 -pip/_internal/req/req_set.py,sha256=j3esG0s6SzoVReX9rWn4rpYNtyET_fwxbwJPRimvRxo,2858 -pip/_internal/req/req_uninstall.py,sha256=ZFQfgSNz6H1BMsgl87nQNr2iaQCcbFcmXpW8rKVQcic,24045 -pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/__pycache__/base.cpython-310.pyc,, -pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583 -pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc,, -pip/_internal/resolution/legacy/resolver.py,sha256=9em8D5TcSsEN4xZM1WreaRShOnyM4LlvhMSHpUPsocE,24129 -pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/base.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/base.py,sha256=u1O4fkvCO4mhmu5i32xrDv9AX5NgUci_eYVyBDQhTIM,5220 -pip/_internal/resolution/resolvelib/candidates.py,sha256=6kQZeMzwibnL4lO6bW0hUQQjNEvXfADdFphRRkRvOtc,18963 -pip/_internal/resolution/resolvelib/factory.py,sha256=OnjkLIgyk5Tol7uOOqapA1D4qiRHWmPU18DF1yN5N8o,27878 -pip/_internal/resolution/resolvelib/found_candidates.py,sha256=hvL3Hoa9VaYo-qEOZkBi2Iqw251UDxPz-uMHVaWmLpE,5705 -pip/_internal/resolution/resolvelib/provider.py,sha256=Vd4jW_NnyifB-HMkPYtZIO70M3_RM0MbL5YV6XyBM-w,9914 -pip/_internal/resolution/resolvelib/reporter.py,sha256=3ZVVYrs5PqvLFJkGLcuXoMK5mTInFzl31xjUpDBpZZk,2526 -pip/_internal/resolution/resolvelib/requirements.py,sha256=B1ndvKPSuyyyTEXt9sKhbwminViSWnBrJa7qO2ln4Z0,5455 -pip/_internal/resolution/resolvelib/resolver.py,sha256=nYZ9bTFXj5c1ILKnkSgU7tUCTYyo5V5J-J0sKoA7Wzg,11533 -pip/_internal/self_outdated_check.py,sha256=R3MmjCyUt_lkUNMc6p3xVSx7vX28XiDh3VDs5OrYn6Q,8020 -pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/utils/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/utils/__pycache__/_log.cpython-310.pyc,, -pip/_internal/utils/__pycache__/appdirs.cpython-310.pyc,, -pip/_internal/utils/__pycache__/compat.cpython-310.pyc,, -pip/_internal/utils/__pycache__/compatibility_tags.cpython-310.pyc,, -pip/_internal/utils/__pycache__/datetime.cpython-310.pyc,, -pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc,, -pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc,, -pip/_internal/utils/__pycache__/distutils_args.cpython-310.pyc,, -pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc,, -pip/_internal/utils/__pycache__/encoding.cpython-310.pyc,, -pip/_internal/utils/__pycache__/entrypoints.cpython-310.pyc,, -pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc,, -pip/_internal/utils/__pycache__/filetypes.cpython-310.pyc,, -pip/_internal/utils/__pycache__/glibc.cpython-310.pyc,, -pip/_internal/utils/__pycache__/hashes.cpython-310.pyc,, -pip/_internal/utils/__pycache__/inject_securetransport.cpython-310.pyc,, -pip/_internal/utils/__pycache__/logging.cpython-310.pyc,, -pip/_internal/utils/__pycache__/misc.cpython-310.pyc,, -pip/_internal/utils/__pycache__/models.cpython-310.pyc,, -pip/_internal/utils/__pycache__/packaging.cpython-310.pyc,, -pip/_internal/utils/__pycache__/setuptools_build.cpython-310.pyc,, -pip/_internal/utils/__pycache__/subprocess.cpython-310.pyc,, -pip/_internal/utils/__pycache__/temp_dir.cpython-310.pyc,, -pip/_internal/utils/__pycache__/unpacking.cpython-310.pyc,, -pip/_internal/utils/__pycache__/urls.cpython-310.pyc,, -pip/_internal/utils/__pycache__/virtualenv.cpython-310.pyc,, -pip/_internal/utils/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015 -pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665 -pip/_internal/utils/compat.py,sha256=ACyBfLgj3_XG-iA5omEDrXqDM0cQKzi8h8HRBInzG6Q,1884 -pip/_internal/utils/compatibility_tags.py,sha256=ydin8QG8BHqYRsPY4OL6cmb44CbqXl1T0xxS97VhHkk,5377 -pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242 -pip/_internal/utils/deprecation.py,sha256=Ozzqnnl9kI0oQW6e2Pm3c-v0IZPy6gGERviDG45TmbY,3638 -pip/_internal/utils/direct_url_helpers.py,sha256=6F1tc2rcKaCZmgfVwsE6ObIe_Pux23mUVYA-2D9wCFc,3206 -pip/_internal/utils/distutils_args.py,sha256=bYUt4wfFJRaeGO4VHia6FNaA8HlYXMcKuEq1zYijY5g,1115 -pip/_internal/utils/egg_link.py,sha256=5MVlpz5LirT4iLQq86OYzjXaYF0D4Qk1dprEI7ThST4,2203 -pip/_internal/utils/encoding.py,sha256=qqsXDtiwMIjXMEiIVSaOjwH5YmirCaK-dIzb6-XJsL0,1169 -pip/_internal/utils/entrypoints.py,sha256=GgeG2FUbbYhQ0sYgG2AtM-a4d1P8MJYdmEl5IhQ-WeM,2900 -pip/_internal/utils/filesystem.py,sha256=RhMIXUaNVMGjc3rhsDahWQ4MavvEQDdqXqgq-F6fpw8,5122 -pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716 -pip/_internal/utils/glibc.py,sha256=tDfwVYnJCOC0BNVpItpy8CGLP9BjkxFHdl0mTS0J7fc,3110 -pip/_internal/utils/hashes.py,sha256=EPVx_I0UI8Gvu_skgLwpJA90pHZ5Ev1qNaZagYOub7I,4811 -pip/_internal/utils/inject_securetransport.py,sha256=o-QRVMGiENrTJxw3fAhA7uxpdEdw6M41TjHYtSVRrcg,795 -pip/_internal/utils/logging.py,sha256=U2q0i1n8hPS2gQh8qcocAg5dovGAa_bR24akmXMzrk4,11632 -pip/_internal/utils/misc.py,sha256=49Rs2NgrD4JGTKFt0farCm7FIAi-rjyoxgioArhCW_0,21617 -pip/_internal/utils/models.py,sha256=5GoYU586SrxURMvDn_jBMJInitviJg4O5-iOU-6I0WY,1193 -pip/_internal/utils/packaging.py,sha256=5Wm6_x7lKrlqVjPI5MBN_RurcRHwVYoQ7Ksrs84de7s,2108 -pip/_internal/utils/setuptools_build.py,sha256=vNH9hQB9wT6d-h1hVQhBKw91jNeT42meHpVeii-urOI,5652 -pip/_internal/utils/subprocess.py,sha256=MYySbvY7qBevRxq_RFfOsDqG4vMqrB4vDoL_eyPE6Bo,9197 -pip/_internal/utils/temp_dir.py,sha256=aCX489gRa4Nu0dMKRFyGhV6maJr60uEynu5uCbKR4Qg,7702 -pip/_internal/utils/unpacking.py,sha256=SBb2iV1crb89MDRTEKY86R4A_UOWApTQn9VQVcMDOlE,8821 -pip/_internal/utils/urls.py,sha256=AhaesUGl-9it6uvG6fsFPOr9ynFpGaTMk4t5XTX7Z_Q,1759 -pip/_internal/utils/virtualenv.py,sha256=4_48qMzCwB_F5jIK5BC_ua7uiAMVifmQWU9NdaGUoVA,3459 -pip/_internal/utils/wheel.py,sha256=lXOgZyTlOm5HmK8tw5iw0A3_5A6wRzsXHOaQkIvvloU,4549 -pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596 -pip/_internal/vcs/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/bazaar.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/git.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/mercurial.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/subversion.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/versioncontrol.cpython-310.pyc,, -pip/_internal/vcs/bazaar.py,sha256=IGb5ca1xSZfgegRD2_JeyoZPrQQHs7lEYEIgpVsKpoU,3047 -pip/_internal/vcs/git.py,sha256=mjhwudCx9WlLNkxZ6_kOKmueF0rLoU2i1xeASKF6yiQ,18116 -pip/_internal/vcs/mercurial.py,sha256=Bzbd518Jsx-EJI0IhIobiQqiRsUv5TWYnrmRIFWE0Gw,5238 -pip/_internal/vcs/subversion.py,sha256=TEMRdwECvMcXakZX0pTNUep79kmBYkWDkWFkrYmcmac,11718 -pip/_internal/vcs/versioncontrol.py,sha256=KUOc-hN51em9jrqxKwUR3JnkgSE-xSOqMiiJcSaL6B8,22811 -pip/_internal/wheel_builder.py,sha256=S-_i83q75xGqKjBenUl4uaTkLyXcZf7jFgChcCNi0xc,12712 -pip/_vendor/__init__.py,sha256=fNxOSVD0auElsD8fN9tuq5psfgMQ-RFBtD4X5gjlRkg,4966 -pip/_vendor/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/__pycache__/six.cpython-310.pyc,, -pip/_vendor/__pycache__/typing_extensions.cpython-310.pyc,, -pip/_vendor/cachecontrol/__init__.py,sha256=hrxlv3q7upsfyMw8k3gQ9vagBax1pYHSGGqYlZ0Zk0M,465 -pip/_vendor/cachecontrol/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/adapter.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/controller.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/serialize.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-310.pyc,, -pip/_vendor/cachecontrol/_cmd.py,sha256=lxUXqfNTVx84zf6tcWbkLZHA6WVBRtJRpfeA9ZqhaAY,1379 -pip/_vendor/cachecontrol/adapter.py,sha256=ew9OYEQHEOjvGl06ZsuX8W3DAvHWsQKHwWAxISyGug8,5033 -pip/_vendor/cachecontrol/cache.py,sha256=Tty45fOjH40fColTGkqKQvQQmbYsMpk-nCyfLcv2vG4,1535 -pip/_vendor/cachecontrol/caches/__init__.py,sha256=h-1cUmOz6mhLsjTjOrJ8iPejpGdLCyG4lzTftfGZvLg,242 -pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/file_cache.py,sha256=GpexcE29LoY4MaZwPUTcUBZaDdcsjqyLxZFznk8Hbr4,5271 -pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=mp-QWonP40I3xJGK3XVO-Gs9a3UjzlqqEmp9iLJH9F4,1033 -pip/_vendor/cachecontrol/compat.py,sha256=LNx7vqBndYdHU8YuJt53ab_8rzMGTXVrvMb7CZJkxG0,778 -pip/_vendor/cachecontrol/controller.py,sha256=bAYrt7x_VH4toNpI066LQxbHpYGpY1MxxmZAhspplvw,16416 -pip/_vendor/cachecontrol/filewrapper.py,sha256=X4BAQOO26GNOR7nH_fhTzAfeuct2rBQcx_15MyFBpcs,3946 -pip/_vendor/cachecontrol/heuristics.py,sha256=8kAyuZLSCyEIgQr6vbUwfhpqg9ows4mM0IV6DWazevI,4154 -pip/_vendor/cachecontrol/serialize.py,sha256=_U1NU_C-SDgFzkbAxAsPDgMTHeTWZZaHCQnZN_jh0U8,7105 -pip/_vendor/cachecontrol/wrapper.py,sha256=X3-KMZ20Ho3VtqyVaXclpeQpFzokR5NE8tZSfvKVaB8,774 -pip/_vendor/certifi/__init__.py,sha256=SuZ3iYmzdRyUv-PiaZkquUgXtWZ16ICUKgymlEBspx0,94 -pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255 -pip/_vendor/certifi/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/certifi/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/certifi/__pycache__/core.cpython-310.pyc,, -pip/_vendor/certifi/cacert.pem,sha256=pZ_eiDoO-ddKudrQCWieABc9KFlbV0FsmLLugygMbkw,285222 -pip/_vendor/certifi/core.py,sha256=g6EYcIFUAhYv5CB9B94iKRgMfGj8f82MF0CRdTDovxM,3052 -pip/_vendor/chardet/__init__.py,sha256=9-r0i294avRciob2HKVcKf6GJmXPHpgMqIijVrqHBDU,3705 -pip/_vendor/chardet/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/big5freq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/big5prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/chardistribution.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/charsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/cp949prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/enums.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/escprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/escsm.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/eucjpprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euckrfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euckrprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euctwfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euctwprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/gb2312freq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/gb2312prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/hebrewprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/jisfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/johabfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/johabprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/jpcntx.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langthaimodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/latin1prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcssm.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sjisprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/universaldetector.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/utf1632prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/utf8prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/version.cpython-310.pyc,, -pip/_vendor/chardet/big5freq.py,sha256=ltcfP-3PjlNHCoo5e4a7C4z-2DhBTXRfY6jbMbB7P30,31274 -pip/_vendor/chardet/big5prober.py,sha256=neUXIlq35507yibstiznZWFzyNcMn6EXrqJaUJVPWKg,1741 -pip/_vendor/chardet/chardistribution.py,sha256=M9NTKdM72KieFKy4TT5eml4PP0WaVcXuY5PpWSFD0FA,9608 -pip/_vendor/chardet/charsetgroupprober.py,sha256=CaIBAmNitEsYuSgMvgAsMREN4cLxMj5OYwMhVo6MAxk,3817 -pip/_vendor/chardet/charsetprober.py,sha256=Eo3w8sCmbvnVKOGNW1iy50KATVs8xV-gF7cQ0VG85dQ,4801 -pip/_vendor/chardet/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/chardet/cli/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-310.pyc,, -pip/_vendor/chardet/cli/chardetect.py,sha256=1qMxT3wrp5vP6ugSf1-Zz3BWwlbCWJ0jzeCuhgX85vw,2406 -pip/_vendor/chardet/codingstatemachine.py,sha256=BiGR9kgTYbS4gJI5qBmE52HMOBOR_roDvXf7aIehdEk,3559 -pip/_vendor/chardet/cp949prober.py,sha256=kCQEaOCzMntqv7pAyXEobWTRgIUxYfoiUr0btXO1nI8,1838 -pip/_vendor/chardet/enums.py,sha256=Rodw4p61Vg9U-oCo6eUuT7uDzKwIbCaA15HwbvCoCNk,1619 -pip/_vendor/chardet/escprober.py,sha256=girD61r3NsQLnMQXsWWBU4hHuRJzTH3V7-VfTUr-nQY,3864 -pip/_vendor/chardet/escsm.py,sha256=0Vs4iPPovberMoSxxnK5pI161Xf-mtKgOl14g5Xc7zg,12021 -pip/_vendor/chardet/eucjpprober.py,sha256=pGgs4lINwCEDV2bxqIZ6hXpaj2j4l2oLsMx6kuOK_zQ,3676 -pip/_vendor/chardet/euckrfreq.py,sha256=3mHuRvXfsq_QcQysDQFb8qSudvTiol71C6Ic2w57tKM,13566 -pip/_vendor/chardet/euckrprober.py,sha256=qBuSS2zXWaoUmGdzz3owAnD1GNhuKR_8bYzDC3yxe6I,1731 -pip/_vendor/chardet/euctwfreq.py,sha256=2alILE1Lh5eqiFJZjzRkMQXolNJRHY5oBQd-vmZYFFM,36913 -pip/_vendor/chardet/euctwprober.py,sha256=SLnCoJC94jZL8PJio60Q8PZACJA1rVPtUdWMa1W8Pwk,1731 -pip/_vendor/chardet/gb2312freq.py,sha256=49OrdXzD-HXqwavkqjo8Z7gvs58hONNzDhAyMENNkvY,20735 -pip/_vendor/chardet/gb2312prober.py,sha256=NS_i52jZE0TnWGkKqFduvu9fzW0nMcS2XbYJ8qSX8hY,1737 -pip/_vendor/chardet/hebrewprober.py,sha256=1l1hXF8-2IWDrPkf85UvAO1GVtMfY1r11kDgOqa-gU4,13919 -pip/_vendor/chardet/jisfreq.py,sha256=mm8tfrwqhpOd3wzZKS4NJqkYBQVcDfTM2JiQ5aW932E,25796 -pip/_vendor/chardet/johabfreq.py,sha256=dBpOYG34GRX6SL8k_LbS9rxZPMjLjoMlgZ03Pz5Hmqc,42498 -pip/_vendor/chardet/johabprober.py,sha256=C18osd4vMPfy9facw-Y1Lor_9UrW0PeV-zxM2fu441c,1730 -pip/_vendor/chardet/jpcntx.py,sha256=m1gDpPkRca4EDwym8XSL5YdoILFnFsDbNBYMQV7_-NE,26797 -pip/_vendor/chardet/langbulgarianmodel.py,sha256=vmbvYFP8SZkSxoBvLkFqKiH1sjma5ihk3PTpdy71Rr4,104562 -pip/_vendor/chardet/langgreekmodel.py,sha256=JfB7bupjjJH2w3X_mYnQr9cJA_7EuITC2cRW13fUjeI,98484 -pip/_vendor/chardet/langhebrewmodel.py,sha256=3HXHaLQPNAGcXnJjkIJfozNZLTvTJmf4W5Awi6zRRKc,98196 -pip/_vendor/chardet/langhungarianmodel.py,sha256=WxbeQIxkv8YtApiNqxQcvj-tMycsoI4Xy-fwkDHpP_Y,101363 -pip/_vendor/chardet/langrussianmodel.py,sha256=s395bTZ87ESTrZCOdgXbEjZ9P1iGPwCl_8xSsac_DLY,128035 -pip/_vendor/chardet/langthaimodel.py,sha256=7bJlQitRpTnVGABmbSznHnJwOHDy3InkTvtFUx13WQI,102774 -pip/_vendor/chardet/langturkishmodel.py,sha256=XY0eGdTIy4eQ9Xg1LVPZacb-UBhHBR-cq0IpPVHowKc,95372 -pip/_vendor/chardet/latin1prober.py,sha256=u_iGcQMUcZLXvj4B_WXx4caA0C5oaE2Qj1KTpz_RQ1I,5260 -pip/_vendor/chardet/mbcharsetprober.py,sha256=iKKuB6o_FF80NynRLBDT0UtwOnpLqmL_OspRPMib7CM,3367 -pip/_vendor/chardet/mbcsgroupprober.py,sha256=1D_kp9nv2_NQRddq9I2WDvB35OJh7Tfpo-OYTnL3B5o,2056 -pip/_vendor/chardet/mbcssm.py,sha256=EfORNu1WXgnFvpFarU8uJHS8KFif63xmgrHOB4DdDdY,30068 -pip/_vendor/chardet/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/metadata/__pycache__/languages.cpython-310.pyc,, -pip/_vendor/chardet/metadata/languages.py,sha256=HcaBygWtZq3gR8prIkJp_etvkhm2V4pUIToqjPZhgrc,13280 -pip/_vendor/chardet/sbcharsetprober.py,sha256=VvtWiNRLbHDZ5xgnofsmP1u8VQIkkaAuw3Ir9m1zDzQ,6199 -pip/_vendor/chardet/sbcsgroupprober.py,sha256=mekr4E3hgT4onmwi8oi1iEGW1CN-Z-BArG6kOtCunJw,4129 -pip/_vendor/chardet/sjisprober.py,sha256=sLfWS25PVFr5cDGhEf6h_s-RJsyeSteA-4ynsTl_UvA,3749 -pip/_vendor/chardet/universaldetector.py,sha256=BHeNWt1kn0yQgnR6xNtLAjiNmEQpSHYlKEvuZ9QyR1k,13288 -pip/_vendor/chardet/utf1632prober.py,sha256=N42YJEOkVDB67c38t5aJhXMG1QvnyWWDMNY5ERzniU0,8289 -pip/_vendor/chardet/utf8prober.py,sha256=mnLaSBV4gg-amt2WmxKFKWy4vVBedMNgjdbvgzBo0Dc,2709 -pip/_vendor/chardet/version.py,sha256=u_QYi-DXU1s7fyC_Rwa0I0-UcxMVmH7Co6c7QGKbe3g,242 -pip/_vendor/colorama/__init__.py,sha256=ihDoWQOkapwF7sqQ99AoDoEF3vGYm40OtmgW211cLZw,239 -pip/_vendor/colorama/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/ansi.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/ansitowin32.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/initialise.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/win32.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/winterm.cpython-310.pyc,, -pip/_vendor/colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 -pip/_vendor/colorama/ansitowin32.py,sha256=gGrO7MVtwc-j1Sq3jKfZpERT1JWmYSOsTVDiTnFbZU4,10830 -pip/_vendor/colorama/initialise.py,sha256=PprovDNxMTrvoNHFcL2NZjpH2XzDc8BLxLxiErfUl4k,1915 -pip/_vendor/colorama/win32.py,sha256=bJ8Il9jwaBN5BJ8bmN6FoYZ1QYuMKv2j8fGrXh7TJjw,5404 -pip/_vendor/colorama/winterm.py,sha256=2y_2b7Zsv34feAsP67mLOVc-Bgq51mdYGo571VprlrM,6438 -pip/_vendor/distlib/__init__.py,sha256=kshNHF2XFPxmBv57X7Jsj7c6VzF5r9naVwGePP-s5Wc,581 -pip/_vendor/distlib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/database.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/index.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/locators.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/manifest.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/markers.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/metadata.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/resources.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/scripts.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/util.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/version.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/wheel.cpython-310.pyc,, -pip/_vendor/distlib/compat.py,sha256=tfoMrj6tujk7G4UC2owL6ArgDuCKabgBxuJRGZSmpko,41259 -pip/_vendor/distlib/database.py,sha256=o_mw0fAr93NDAHHHfqG54Y1Hi9Rkfrp2BX15XWZYK50,51697 -pip/_vendor/distlib/index.py,sha256=HFiDG7LMoaBs829WuotrfIwcErOOExUOR_AeBtw_TCU,20834 -pip/_vendor/distlib/locators.py,sha256=wNzG-zERzS_XGls-nBPVVyLRHa2skUlkn0-5n0trMWA,51991 -pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 -pip/_vendor/distlib/markers.py,sha256=TpHHHLgkzyT7YHbwj-2i6weRaq-Ivy2-MUnrDkjau-U,5058 -pip/_vendor/distlib/metadata.py,sha256=g_DIiu8nBXRzA-mWPRpatHGbmFZqaFoss7z9TG7QSUU,39801 -pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820 -pip/_vendor/distlib/scripts.py,sha256=BmkTKmiTk4m2cj-iueliatwz3ut_9SsABBW51vnQnZU,18102 -pip/_vendor/distlib/t32.exe,sha256=lD3IWCwZiYZ9onypJifi2R1sGS-S24t3mYupsEAOKyA,97792 -pip/_vendor/distlib/t64-arm.exe,sha256=3hjLTLg7XBVHwDxgzZpkiHXXp4IJQMLvg_ZlGGpKZDI,182784 -pip/_vendor/distlib/t64.exe,sha256=vvS31h4-SnumthypJJKAWBeBh7cxSJ8AwGmbqumM05k,107520 -pip/_vendor/distlib/util.py,sha256=31dPXn3Rfat0xZLeVoFpuniyhe6vsbl9_QN-qd9Lhlk,66262 -pip/_vendor/distlib/version.py,sha256=WG__LyAa2GwmA6qSoEJtvJE8REA1LZpbSizy8WvhJLk,23513 -pip/_vendor/distlib/w32.exe,sha256=-a9nfgVZClK_mGnbQtXVLbn7xtPYw3xDKTddKnu2AJ8,91648 -pip/_vendor/distlib/w64-arm.exe,sha256=LW-JyIIGblDOp8Psy8igJXDvcg_YpJIINvN0tRjfv18,168448 -pip/_vendor/distlib/w64.exe,sha256=XvKqAoQzca86ERd2-KV5Vo1RSOBM28I2a35sPQONrYI,101888 -pip/_vendor/distlib/wheel.py,sha256=Rgqs658VsJ3R2845qwnZD8XQryV2CzWw2mghwLvxxsI,43898 -pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981 -pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64 -pip/_vendor/distro/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/distro/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/distro/__pycache__/distro.cpython-310.pyc,, -pip/_vendor/distro/distro.py,sha256=UYQG_9H_iSOt422uasA92HlY7aXeTnWKdV-IhsSAdwQ,48841 -pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849 -pip/_vendor/idna/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/codec.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/core.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/idnadata.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/intranges.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/package_data.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/uts46data.cpython-310.pyc,, -pip/_vendor/idna/codec.py,sha256=6ly5odKfqrytKT9_7UrlGklHnf1DSK2r9C6cSM4sa28,3374 -pip/_vendor/idna/compat.py,sha256=0_sOEUMT4CVw9doD3vyRhX80X19PwqFoUBs7gWsFME4,321 -pip/_vendor/idna/core.py,sha256=RFIkY-HhFZaDoBEFjGwyGd_vWI04uOAQjnzueMWqwOU,12795 -pip/_vendor/idna/idnadata.py,sha256=fzMzkCea2xieVxcrjngJ-2pLsKQNejPCZFlBajIuQdw,44025 -pip/_vendor/idna/intranges.py,sha256=YBr4fRYuWH7kTKS2tXlFjM24ZF1Pdvcir-aywniInqg,1881 -pip/_vendor/idna/package_data.py,sha256=szxQhV0ZD0nKJ84Kuobw3l8q4_KeCyXjFRdpwIpKZmw,21 -pip/_vendor/idna/uts46data.py,sha256=o-D7V-a0fOLZNd7tvxof6MYfUd0TBZzE2bLR5XO67xU,204400 -pip/_vendor/msgpack/__init__.py,sha256=NryGaKLDk_Egd58ZxXpnuI7OWO27AXz7S6CBFRM3sAY,1132 -pip/_vendor/msgpack/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/ext.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/fallback.cpython-310.pyc,, -pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081 -pip/_vendor/msgpack/ext.py,sha256=TuldJPkYu8Wo_Xh0tFGL2l06-gY88NSR8tOje9fo2Wg,6080 -pip/_vendor/msgpack/fallback.py,sha256=OORDn86-fHBPlu-rPlMdM10KzkH6S_Rx9CHN1b7o4cg,34557 -pip/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 -pip/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 -pip/_vendor/packaging/__pycache__/__about__.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_structures.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/markers.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/requirements.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/tags.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/utils.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/version.cpython-310.pyc,, -pip/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 -pip/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 -pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 -pip/_vendor/packaging/markers.py,sha256=AJBOcY8Oq0kYc570KuuPTkvuqjAlhufaE2c9sCUbm64,8487 -pip/_vendor/packaging/requirements.py,sha256=NtDlPBtojpn1IUC85iMjPNsUmufjpSlwnNA-Xb4m5NA,4676 -pip/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 -pip/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 -pip/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 -pip/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 -pip/_vendor/pep517/__init__.py,sha256=Y1bATL2qbFNN6M_DQa4yyrwqjpIiL-j9T6kBmR0DS14,130 -pip/_vendor/pep517/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/build.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/check.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/colorlog.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/dirtools.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/envbuild.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/meta.cpython-310.pyc,, -pip/_vendor/pep517/__pycache__/wrappers.cpython-310.pyc,, -pip/_vendor/pep517/build.py,sha256=2bar6EdjwIz2Dlfy94qdxn3oA9mVnnny40mfoT5f-qI,3457 -pip/_vendor/pep517/check.py,sha256=bCORq1WrHjhpTONa-zpAqG0EB9rHNuhO1ORu6DsDuL8,6084 -pip/_vendor/pep517/colorlog.py,sha256=Tk9AuYm_cLF3BKTBoSTJt9bRryn0aFojIQOwbfVUTxQ,4098 -pip/_vendor/pep517/compat.py,sha256=NmLImE5oiDT3gbEhJ4w7xeoMFcpAPrGu_NltBytSJUY,1253 -pip/_vendor/pep517/dirtools.py,sha256=2mkAkAL0mRz_elYFjRKuekTJVipH1zTn4tbf1EDev84,1129 -pip/_vendor/pep517/envbuild.py,sha256=zFde--rmzjXMLXcm7SA_3hDtgk5VCTA8hjpk88RbF6E,6100 -pip/_vendor/pep517/in_process/__init__.py,sha256=MyWoAi8JHdcBv7yXuWpUSVADbx6LSB9rZh7kTIgdA8Y,563 -pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-310.pyc,, -pip/_vendor/pep517/in_process/_in_process.py,sha256=D3waguyNSGcwosociD5USfcycYr2RCzCjYtxX5UHQmQ,11201 -pip/_vendor/pep517/meta.py,sha256=8mnM5lDnT4zXQpBTliJbRGfesH7iioHwozbDxALPS9Y,2463 -pip/_vendor/pep517/wrappers.py,sha256=impq7Cz_LL1iDF1iiOzYWB4MaEu6O6Gps7TJ5qsJz1Q,13429 -pip/_vendor/pkg_resources/__init__.py,sha256=NnpQ3g6BCHzpMgOR_OLBmYtniY4oOzdKpwqghfq_6ug,108287 -pip/_vendor/pkg_resources/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-310.pyc,, -pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 -pip/_vendor/platformdirs/__init__.py,sha256=x0aUmmovXXuRFVrVQBtwIiovX12B7rUkdV4F9UlLz0Y,12831 -pip/_vendor/platformdirs/__main__.py,sha256=ZmsnTxEOxtTvwa-Y_Vfab_JN3X4XCVeN8X0yyy9-qnc,1176 -pip/_vendor/platformdirs/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/android.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/api.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/macos.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/unix.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/version.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/windows.cpython-310.pyc,, -pip/_vendor/platformdirs/android.py,sha256=GKizhyS7ESRiU67u8UnBJLm46goau9937EchXWbPBlk,4068 -pip/_vendor/platformdirs/api.py,sha256=MXKHXOL3eh_-trSok-JUTjAR_zjmmKF3rjREVABjP8s,4910 -pip/_vendor/platformdirs/macos.py,sha256=-3UXQewbT0yMhMdkzRXfXGAntmLIH7Qt4a9Hlf8I5_Y,2655 -pip/_vendor/platformdirs/unix.py,sha256=b4aVYTz0qZ50HntwOXo8r6tp82jAa3qTjxw-WlnC2yc,6910 -pip/_vendor/platformdirs/version.py,sha256=tsBKKPDX3LLh39yHXeTYauGRbRd-AmOJr9SwKldlFIU,78 -pip/_vendor/platformdirs/windows.py,sha256=ISruopR5UGBePC0BxCxXevkZYfjJsIZc49YWU5iYfQ4,6439 -pip/_vendor/pygments/__init__.py,sha256=M4yPkVb6x8OkEb4tHfVU8p6B3DBEsshB_8a2gZvr4FE,3002 -pip/_vendor/pygments/__main__.py,sha256=p0_rz3JZmNZMNZBOqDojaEx1cr9wmA9FQZX_TYl74lQ,353 -pip/_vendor/pygments/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/cmdline.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/console.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/filter.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/formatter.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/lexer.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/modeline.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/plugin.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/regexopt.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/scanner.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/sphinxext.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/style.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/token.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/unistring.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/util.cpython-310.pyc,, -pip/_vendor/pygments/cmdline.py,sha256=HYs14dbtMgL7t_BJ7B84NXlFjOzMYgW7Z0ZSxkTJun4,23408 -pip/_vendor/pygments/console.py,sha256=hQfqCFuOlGk7DW2lPQYepsw-wkOH1iNt9ylNA1eRymM,1697 -pip/_vendor/pygments/filter.py,sha256=NglMmMPTRRv-zuRSE_QbWid7JXd2J4AvwjCW2yWALXU,1938 -pip/_vendor/pygments/filters/__init__.py,sha256=F8WwJguaJLs3bomEH8LyVATQfpULTpSpTd4PRPONR5A,40292 -pip/_vendor/pygments/filters/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/formatter.py,sha256=6-TS2Y8pUMeWIUolWwr1O8ruC-U6HydWDwOdbAiJgJQ,2917 -pip/_vendor/pygments/formatters/__init__.py,sha256=5LfCZThsbVVtZU5OyavkRPwC0MV7tB6pqcJ793PWi6E,5119 -pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/groff.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/html.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/img.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/irc.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/latex.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/other.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/svg.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-310.pyc,, -pip/_vendor/pygments/formatters/_mapping.py,sha256=QLyYZ7Cv9W7YcM8seq0XqR3MXW3MzoFZSyHd7BDNU84,6517 -pip/_vendor/pygments/formatters/bbcode.py,sha256=JrL4ITjN-KzPcuQpPMBf1pm33eW2sDUNr8WzSoAJsJA,3314 -pip/_vendor/pygments/formatters/groff.py,sha256=xrOFoLbafSA9uHsSLRogy79_Zc4GWJ8tMK2hCdTJRsw,5086 -pip/_vendor/pygments/formatters/html.py,sha256=QNt9prPgxmbKx2M-nfDwoR1bIg06-sNouQuWnE434Wc,35441 -pip/_vendor/pygments/formatters/img.py,sha256=j3hHU1fhbBEIKEtWTV-vc-z-5c2nqoobOty3QqeQbpk,21819 -pip/_vendor/pygments/formatters/irc.py,sha256=iwk5tDJOxbCV64SCmOFyvk__x6RD60ay0nUn7ko9n7U,5871 -pip/_vendor/pygments/formatters/latex.py,sha256=thPbytJCIs2AUXsO3NZwqKtXJ-upOlcXP4CXsx94G4w,19351 -pip/_vendor/pygments/formatters/other.py,sha256=PczqK1Rms43lz6iucOLPeBMxIncPKOGBt-195w1ynII,5073 -pip/_vendor/pygments/formatters/pangomarkup.py,sha256=ZZzMsKJKXrsDniFeMTkIpe7aQ4VZYRHu0idWmSiUJ2U,2212 -pip/_vendor/pygments/formatters/rtf.py,sha256=abrKlWjipBkQvhIICxtjYTUNv6WME0iJJObFvqVuudE,5014 -pip/_vendor/pygments/formatters/svg.py,sha256=6MM9YyO8NhU42RTQfTWBiagWMnsf9iG5gwhqSriHORE,7335 -pip/_vendor/pygments/formatters/terminal.py,sha256=NpEGvwkC6LgMLQTjVzGrJXji3XcET1sb5JCunSCzoRo,4674 -pip/_vendor/pygments/formatters/terminal256.py,sha256=4v4OVizvsxtwWBpIy_Po30zeOzE5oJg_mOc1-rCjMDk,11753 -pip/_vendor/pygments/lexer.py,sha256=ZPB_TGn_qzrXodRFwEdPzzJk6LZBo9BlfSy3lacc6zg,32005 -pip/_vendor/pygments/lexers/__init__.py,sha256=Gku6kqn9IvgIdvV50gISPo0mmyyMNYRoUliEwhw6eNY,11491 -pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-310.pyc,, -pip/_vendor/pygments/lexers/__pycache__/python.cpython-310.pyc,, -pip/_vendor/pygments/lexers/_mapping.py,sha256=sExOsmEbtg7hKwXgSz6M3L77cKPaOgskzxOCdw_GxVc,72083 -pip/_vendor/pygments/lexers/python.py,sha256=QWj4ud4brZCj0-LXjR7IcO0kL6lqM2HzM_DzZZxMRjg,52792 -pip/_vendor/pygments/modeline.py,sha256=gIbMSYrjSWPk0oATz7W9vMBYkUyTK2OcdVyKjioDRvA,986 -pip/_vendor/pygments/plugin.py,sha256=tIRWetjR4dokpgbbFnsx7jjfN57T4-Z4errH1eVgGYw,1727 -pip/_vendor/pygments/regexopt.py,sha256=c6xcXGpGgvCET_3VWawJJqAnOp0QttFpQEdOPNY2Py0,3072 -pip/_vendor/pygments/scanner.py,sha256=F2T2G6cpkj-yZtzGQr-sOBw5w5-96UrJWveZN6va2aM,3092 -pip/_vendor/pygments/sphinxext.py,sha256=F8L0211sPnXaiWutN0lkSUajWBwlgDMIEFFAbMWOvZY,4630 -pip/_vendor/pygments/style.py,sha256=RRnussX1YiK9Z7HipIvKorImxu3-HnkdpPCO4u925T0,6257 -pip/_vendor/pygments/styles/__init__.py,sha256=eVJlJqbmc-TYSQEEl-2yhbtnW6INfuvlayJOiXrt9ro,3252 -pip/_vendor/pygments/styles/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/token.py,sha256=naybicpgOtSlh3vMGvbbx2T_6qEdGWYEH_RJ4gacIcc,6143 -pip/_vendor/pygments/unistring.py,sha256=gP3gK-6C4oAFjjo9HvoahsqzuV4Qz0jl0E0OxfDerHI,63187 -pip/_vendor/pygments/util.py,sha256=KgwpWWC3By5AiNwxGTI7oI9aXupH2TyZWukafBJe0Mg,9110 -pip/_vendor/pyparsing/__init__.py,sha256=ZPdI7pPo4IYXcABw-51AcqOzsxVvDtqnQbyn_qYWZvo,9171 -pip/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/common.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/core.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/results.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/util.cpython-310.pyc,, -pip/_vendor/pyparsing/actions.py,sha256=wU9i32e0y1ymxKE3OUwSHO-SFIrt1h_wv6Ws0GQjpNU,6426 -pip/_vendor/pyparsing/common.py,sha256=lFL97ooIeR75CmW5hjURZqwDCTgruqltcTCZ-ulLO2Q,12936 -pip/_vendor/pyparsing/core.py,sha256=AzTm1KFT1FIhiw2zvXZJmrpQoAwB0wOmeDCiR6SYytw,213344 -pip/_vendor/pyparsing/diagram/__init__.py,sha256=KW0PV_TvWKnL7jysz0pQbZ24nzWWu2ZfNaeyUIIywIg,23685 -pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyparsing/exceptions.py,sha256=3LbSafD32NYb1Tzt85GHNkhEAU1eZkTtNSk24cPMemo,9023 -pip/_vendor/pyparsing/helpers.py,sha256=QpUOjW0-psvueMwWb9bQpU2noqKCv98_wnw1VSzSdVo,39129 -pip/_vendor/pyparsing/results.py,sha256=HgNvWVXBdQP-Q6PtJfoCEeOJk2nwEvG-2KVKC5sGA30,25341 -pip/_vendor/pyparsing/testing.py,sha256=7tu4Abp4uSeJV0N_yEPRmmNUhpd18ZQP3CrX41DM814,13402 -pip/_vendor/pyparsing/unicode.py,sha256=fwuhMj30SQ165Cv7HJpu-rSxGbRm93kN9L4Ei7VGc1Y,10787 -pip/_vendor/pyparsing/util.py,sha256=kq772O5YSeXOSdP-M31EWpbH_ayj7BMHImBYo9xPD5M,6805 -pip/_vendor/requests/__init__.py,sha256=3XN75ZS4slWy3TQsEGF7-Q6l2R146teU-s2_rXNhxhU,5178 -pip/_vendor/requests/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/__version__.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/_internal_utils.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/adapters.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/api.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/auth.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/certs.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/cookies.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/help.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/hooks.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/models.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/packages.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/sessions.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/status_codes.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/structures.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/utils.cpython-310.pyc,, -pip/_vendor/requests/__version__.py,sha256=nJVa3ef2yRyeYMhy7yHnRyjjpnNTDykZsE4Sp9irBC4,440 -pip/_vendor/requests/_internal_utils.py,sha256=aSPlF4uDhtfKxEayZJJ7KkAxtormeTfpwKSBSwtmAUw,1397 -pip/_vendor/requests/adapters.py,sha256=GFEz5koZaMZD86v0SHXKVB5SE9MgslEjkCQzldkNwVM,21443 -pip/_vendor/requests/api.py,sha256=dyvkDd5itC9z2g0wHl_YfD1yf6YwpGWLO7__8e21nks,6377 -pip/_vendor/requests/auth.py,sha256=h-HLlVx9j8rKV5hfSAycP2ApOSglTz77R0tz7qCbbEE,10187 -pip/_vendor/requests/certs.py,sha256=kHDlkK_beuHXeMPc5jta2wgl8gdKeUWt5f2nTDVrvt8,441 -pip/_vendor/requests/compat.py,sha256=IhK9quyX0RRuWTNcg6d2JGSAOUbM6mym2p_2XjLTwf4,1286 -pip/_vendor/requests/cookies.py,sha256=kD3kNEcCj-mxbtf5fJsSaT86eGoEYpD3X0CSgpzl7BM,18560 -pip/_vendor/requests/exceptions.py,sha256=FA-_kVwBZ2jhXauRctN_ewHVK25b-fj0Azyz1THQ0Kk,3823 -pip/_vendor/requests/help.py,sha256=FnAAklv8MGm_qb2UilDQgS6l0cUttiCFKUjx0zn2XNA,3879 -pip/_vendor/requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733 -pip/_vendor/requests/models.py,sha256=GZRMMrGwDOLVvVfFHLUq0qTfIWDla3NcFHa1f5xs9Q8,35287 -pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 -pip/_vendor/requests/sessions.py,sha256=KUqJcRRLovNefUs7ScOXSUVCcfSayTFWtbiJ7gOSlTI,30180 -pip/_vendor/requests/status_codes.py,sha256=FvHmT5uH-_uimtRz5hH9VCbt7VV-Nei2J9upbej6j8g,4235 -pip/_vendor/requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912 -pip/_vendor/requests/utils.py,sha256=0gzSOcx9Ya4liAbHnHuwt4jM78lzCZZoDFgkmsInNUg,33240 -pip/_vendor/resolvelib/__init__.py,sha256=UL-B2BDI0_TRIqkfGwLHKLxY-LjBlomz7941wDqzB1I,537 -pip/_vendor/resolvelib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/providers.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/reporters.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/resolvers.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/structs.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156 -pip/_vendor/resolvelib/providers.py,sha256=roVmFBItQJ0TkhNua65h8LdNny7rmeqVEXZu90QiP4o,5872 -pip/_vendor/resolvelib/reporters.py,sha256=fW91NKf-lK8XN7i6Yd_rczL5QeOT3sc6AKhpaTEnP3E,1583 -pip/_vendor/resolvelib/resolvers.py,sha256=2wYzVGBGerbmcIpH8cFmgSKgLSETz8jmwBMGjCBMHG4,17592 -pip/_vendor/resolvelib/structs.py,sha256=IVIYof6sA_N4ZEiE1C1UhzTX495brCNnyCdgq6CYq28,4794 -pip/_vendor/rich/__init__.py,sha256=zREyQ22R3zKg8gMdhiikczdVQYtZNeayHNrbBg5scm0,5944 -pip/_vendor/rich/__main__.py,sha256=BmTmBWI93ytq75IEPi1uAAdeRYzFfDbgaAXjsX1ogig,8808 -pip/_vendor/rich/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_cell_widths.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_emoji_codes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_emoji_replace.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_export_format.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_extension.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_inspect.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_log_render.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_loop.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_palettes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_pick.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_ratio.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_spinners.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_stack.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_timer.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_win32_console.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_windows.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_windows_renderer.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_wrap.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/abc.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/align.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/ansi.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/bar.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/box.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/cells.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/color.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/color_triplet.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/columns.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/console.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/constrain.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/containers.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/control.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/default_styles.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/diagnose.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/emoji.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/errors.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/file_proxy.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/filesize.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/highlighter.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/json.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/jupyter.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/layout.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/live.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/live_render.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/logging.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/markup.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/measure.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/padding.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/pager.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/palette.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/panel.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/pretty.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/progress.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/progress_bar.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/prompt.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/protocol.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/region.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/repr.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/rule.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/scope.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/screen.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/segment.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/spinner.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/status.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/style.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/styled.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/syntax.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/table.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/terminal_theme.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/text.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/theme.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/themes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/traceback.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/tree.cpython-310.pyc,, -pip/_vendor/rich/_cell_widths.py,sha256=2n4EiJi3X9sqIq0O16kUZ_zy6UYMd3xFfChlKfnW1Hc,10096 -pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235 -pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064 -pip/_vendor/rich/_export_format.py,sha256=nHArqOljIlYn6NruhWsAsh-fHo7oJC3y9BDJyAa-QYQ,2114 -pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265 -pip/_vendor/rich/_inspect.py,sha256=oZJGw31e64dwXSCmrDnvZbwVb1ZKhWfU8wI3VWohjJk,9695 -pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225 -pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236 -pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063 -pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423 -pip/_vendor/rich/_ratio.py,sha256=2lLSliL025Y-YMfdfGbutkQDevhcyDqc-DtUYW9mU70,5472 -pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919 -pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351 -pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417 -pip/_vendor/rich/_win32_console.py,sha256=P0vxI2fcndym1UU1S37XAzQzQnkyY7YqAKmxm24_gug,22820 -pip/_vendor/rich/_windows.py,sha256=dvNl9TmfPzNVxiKk5WDFihErZ5796g2UC9-KGGyfXmk,1926 -pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783 -pip/_vendor/rich/_wrap.py,sha256=xfV_9t0Sg6rzimmrDru8fCVmUlalYAcHLDfrJZnbbwQ,1840 -pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890 -pip/_vendor/rich/align.py,sha256=FV6_GS-8uhIyViMng3hkIWSFaTgMohK1Oqyjl8I8mGE,10368 -pip/_vendor/rich/ansi.py,sha256=HtaPG7dvgL6_yo0sQmx5CM05DJ4_1goY5SWXXOYNaKs,6820 -pip/_vendor/rich/bar.py,sha256=a7UD303BccRCrEhGjfMElpv5RFYIinaAhAuqYqhUvmw,3264 -pip/_vendor/rich/box.py,sha256=1Iv1sUWqjtp5XwLwGH-AJ8HgyXZ7dRFUkO0z3M_bRl8,9864 -pip/_vendor/rich/cells.py,sha256=zMjFI15wCpgjLR14lHdfFMVC6qMDi5OsKIB0PYZBBMk,4503 -pip/_vendor/rich/color.py,sha256=kp87L8V4-3qayE6CUxtW_nP8Ujfew_-DAhNwYMXBMOY,17957 -pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054 -pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131 -pip/_vendor/rich/console.py,sha256=bTT9DNX03V4cQXefg22d-gLSs_e_ZY2zdCvLIlEyU2Q,95885 -pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288 -pip/_vendor/rich/containers.py,sha256=aKgm5UDHn5Nmui6IJaKdsZhbHClh_X7D-_Wg8Ehrr7s,5497 -pip/_vendor/rich/control.py,sha256=DSkHTUQLorfSERAKE_oTAEUFefZnZp4bQb4q8rHbKws,6630 -pip/_vendor/rich/default_styles.py,sha256=WqVh-RPNEsx0Wxf3fhS_fCn-wVqgJ6Qfo-Zg7CoCsLE,7954 -pip/_vendor/rich/diagnose.py,sha256=an6uouwhKPAlvQhYpNNpGq9EJysfMIOvvCbO3oSoR24,972 -pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501 -pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642 -pip/_vendor/rich/file_proxy.py,sha256=4gCbGRXg0rW35Plaf0UVvj3dfENHuzc_n8I_dBqxI7o,1616 -pip/_vendor/rich/filesize.py,sha256=yShoVpARafJBreyZFaAhC4OhnJ6ydC1WXR-Ez4wU_YQ,2507 -pip/_vendor/rich/highlighter.py,sha256=3WW6PACGlq0e3YDjfqiMBQ0dYZwu7pcoFYUgJy01nb0,9585 -pip/_vendor/rich/json.py,sha256=RCm4lXBXrjvXHpqrWPH8wdGP0jEo4IohLmkddlhRY18,5051 -pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252 -pip/_vendor/rich/layout.py,sha256=E3xJ4fomizUADwime3VA0lBXoMSPl9blEokIzVBjO0Q,14074 -pip/_vendor/rich/live.py,sha256=emVaLUua-FKSYqZXmtJJjBIstO99CqMOuA6vMAKVkO0,14172 -pip/_vendor/rich/live_render.py,sha256=zElm3PrfSIvjOce28zETHMIUf9pFYSUA5o0AflgUP64,3667 -pip/_vendor/rich/logging.py,sha256=10j13lPr-QuYqEEBz_2aRJp8gNYvSN2wmCUlUqJcPLM,11471 -pip/_vendor/rich/markup.py,sha256=xzF4uAafiEeEYDJYt_vUnJOGoTU8RrH-PH7WcWYXjCg,8198 -pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305 -pip/_vendor/rich/padding.py,sha256=kTFGsdGe0os7tXLnHKpwTI90CXEvrceeZGCshmJy5zw,4970 -pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828 -pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396 -pip/_vendor/rich/panel.py,sha256=CzdojkDAjxAKgvDxis47nWzUh1V2NniOqkJJQajosG8,8744 -pip/_vendor/rich/pretty.py,sha256=CalVLVW3mvTn1hvI9Pgi2v-y4S-5zUWBK-PH7SlVs-U,36576 -pip/_vendor/rich/progress.py,sha256=zjQRwd3TmDnAvSjTPsNPHFjmqE9GOEX3bf0Lj56hIL8,59746 -pip/_vendor/rich/progress_bar.py,sha256=zHHaFPEfIhW2fq6Fnl5vBY7AUpP1N0HVGElISUHsnqw,8161 -pip/_vendor/rich/prompt.py,sha256=x0mW-pIPodJM4ry6grgmmLrl8VZp99kqcmdnBe70YYA,11303 -pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391 -pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166 -pip/_vendor/rich/repr.py,sha256=Je91CIrZN_av9L3FRCKCs5yoX2LvczrCNKqUbVsjUvQ,4449 -pip/_vendor/rich/rule.py,sha256=V6AWI0wCb6DB0rvN967FRMlQrdlG7HoZdfEAHyeG8CM,4773 -pip/_vendor/rich/scope.py,sha256=HX13XsJfqzQHpPfw4Jn9JmJjCsRj9uhHxXQEqjkwyLA,2842 -pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591 -pip/_vendor/rich/segment.py,sha256=6XdX0MfL18tUCaUWDWncIqx0wpq3GiaqzhYP779JvRA,24224 -pip/_vendor/rich/spinner.py,sha256=7b8MCleS4fa46HX0AzF98zfu6ZM6fAL0UgYzPOoakF4,4374 -pip/_vendor/rich/status.py,sha256=gJsIXIZeSo3urOyxRUjs6VrhX5CZrA0NxIQ-dxhCnwo,4425 -pip/_vendor/rich/style.py,sha256=4WnUEkHNMp9Tfmd8cmbxWGby7QeTk2LUTQzFSs46EQc,26240 -pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258 -pip/_vendor/rich/syntax.py,sha256=_M08KbE11nNWNBPooFLKAA7lWkThPzlGUsuesxQYsuA,34697 -pip/_vendor/rich/table.py,sha256=r_lahmj45cINCWLYaIjq9yEv3gve8E6bkYTP8NDqApE,39515 -pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370 -pip/_vendor/rich/text.py,sha256=oajdGIeHcLcSdOwbC48_20ylDsHAS5fsPZD_Ih0clyA,44666 -pip/_vendor/rich/theme.py,sha256=GKNtQhDBZKAzDaY0vQVQQFzbc0uWfFe6CJXA-syT7zQ,3627 -pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102 -pip/_vendor/rich/traceback.py,sha256=MORQpXH7AvhAAThW8oIbtwffXb8M6XRkSkcJ52JuA3g,26060 -pip/_vendor/rich/tree.py,sha256=BMbUYNjS9uodNPfvtY_odmU09GA5QzcMbQ5cJZhllQI,9169 -pip/_vendor/six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549 -pip/_vendor/tenacity/__init__.py,sha256=GLLsTFD4Bd5VDgTR6mU_FxyOsrxc48qONorVaRebeD4,18257 -pip/_vendor/tenacity/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/_asyncio.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/_utils.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/after.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/before.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/before_sleep.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/nap.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/retry.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/stop.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/wait.cpython-310.pyc,, -pip/_vendor/tenacity/_asyncio.py,sha256=HEb0BVJEeBJE9P-m9XBxh1KcaF96BwoeqkJCL5sbVcQ,3314 -pip/_vendor/tenacity/_utils.py,sha256=-y68scDcyoqvTJuJJ0GTfjdSCljEYlbCYvgk7nM4NdM,1944 -pip/_vendor/tenacity/after.py,sha256=dlmyxxFy2uqpLXDr838DiEd7jgv2AGthsWHGYcGYsaI,1496 -pip/_vendor/tenacity/before.py,sha256=7XtvRmO0dRWUp8SVn24OvIiGFj8-4OP5muQRUiWgLh0,1376 -pip/_vendor/tenacity/before_sleep.py,sha256=ThyDvqKU5yle_IvYQz_b6Tp6UjUS0PhVp6zgqYl9U6Y,1908 -pip/_vendor/tenacity/nap.py,sha256=fRWvnz1aIzbIq9Ap3gAkAZgDH6oo5zxMrU6ZOVByq0I,1383 -pip/_vendor/tenacity/retry.py,sha256=62R71W59bQjuNyFKsDM7hE2aEkEPtwNBRA0tnsEvgSk,6645 -pip/_vendor/tenacity/stop.py,sha256=sKHmHaoSaW6sKu3dTxUVKr1-stVkY7lw4Y9yjZU30zQ,2790 -pip/_vendor/tenacity/tornadoweb.py,sha256=E8lWO2nwe6dJgoB-N2HhQprYLDLB_UdSgFnv-EN6wKE,2145 -pip/_vendor/tenacity/wait.py,sha256=e_Saa6I2tsNLpCL1t9897wN2fGb0XQMQlE4bU2t9V2w,6691 -pip/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396 -pip/_vendor/tomli/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_parser.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_re.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_types.cpython-310.pyc,, -pip/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633 -pip/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943 -pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254 -pip/_vendor/typing_extensions.py,sha256=U_PyumPFBkMiR_Iq78QWZXdPprTywptECB2WRIQjDv0,75420 -pip/_vendor/urllib3/__init__.py,sha256=j3yzHIbmW7CS-IKQJ9-PPQf_YKO8EOAey_rMW0UR7us,2763 -pip/_vendor/urllib3/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/_collections.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/_version.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/connection.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/connectionpool.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/fields.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/filepost.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/poolmanager.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/request.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/response.cpython-310.pyc,, -pip/_vendor/urllib3/_collections.py,sha256=Rp1mVyBgc_UlAcp6M3at1skJBXR5J43NawRTvW2g_XY,10811 -pip/_vendor/urllib3/_version.py,sha256=kDAZ-bEcWgqZsVJELrYbVo4buZP5eBBOGl_X7VA0Ic4,64 -pip/_vendor/urllib3/connection.py,sha256=8976wL6sGeVMW0JnXvx5mD00yXu87uQjxtB9_VL8dx8,20070 -pip/_vendor/urllib3/connectionpool.py,sha256=vEzk1iJEw1qR2vHBo7m3Y98iDfna6rKkUz3AyK5lJKQ,39093 -pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957 -pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632 -pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922 -pip/_vendor/urllib3/contrib/appengine.py,sha256=lfzpHFmJiO82shClLEm3QB62SYgHWnjpZOH_2JhU5Tc,11034 -pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=ej9gGvfAb2Gt00lafFp45SIoRz-QwrQ4WChm6gQmAlM,4538 -pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=oR_4W0U0gaDYBN8Q5qz_VZ8xrYZsoXve52RwIKdYGbc,16899 -pip/_vendor/urllib3/contrib/securetransport.py,sha256=yhZdmVjY6PI6EeFbp7qYOp6-vp1Rkv2NMuOGaEj7pmc,34448 -pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097 -pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217 -pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579 -pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440 -pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/packages/__pycache__/six.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417 -pip/_vendor/urllib3/packages/six.py,sha256=b9LM0wBXv7E7SrbCjAm4wwN-hrH-iNxv18LgWNMMKPo,34665 -pip/_vendor/urllib3/poolmanager.py,sha256=0KOOJECoeLYVjUHvv-0h4Oq3FFQQ2yb-Fnjkbj8gJO0,19786 -pip/_vendor/urllib3/request.py,sha256=ZFSIqX0C6WizixecChZ3_okyu7BEv0lZu1VT0s6h4SM,5985 -pip/_vendor/urllib3/response.py,sha256=36JUM28H4dHsuCQgIPeN91LNcK8r1wBUJGFLk3ALfJc,28156 -pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155 -pip/_vendor/urllib3/util/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/connection.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/proxy.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/queue.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/request.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/response.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/retry.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/timeout.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/url.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/wait.cpython-310.pyc,, -pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901 -pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605 -pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498 -pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997 -pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510 -pip/_vendor/urllib3/util/retry.py,sha256=iESg2PvViNdXBRY4MpL4h0kqwOOkHkxmLn1kkhFHPU8,22001 -pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177 -pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758 -pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895 -pip/_vendor/urllib3/util/timeout.py,sha256=QSbBUNOB9yh6AnDn61SrLQ0hg5oz0I9-uXEG91AJuIg,10003 -pip/_vendor/urllib3/util/url.py,sha256=49HwObaTUUjqVe4qvSUvIjZyf3ghgNA6-OLm3kmkFKM,14287 -pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403 -pip/_vendor/vendor.txt,sha256=8XILGklF_LcEc20OonK8_bpFH7tG7wLotFxI0k3FMU0,469 -pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 -pip/_vendor/webencodings/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/labels.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/mklabels.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/tests.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-310.pyc,, -pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 -pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 -pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 -pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 -pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286 diff --git a/venv/Lib/site-packages/pip-25.0.1.dist-info/AUTHORS.txt b/venv/Lib/site-packages/pip-25.0.1.dist-info/AUTHORS.txt new file mode 100644 index 0000000..f42daec --- /dev/null +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/AUTHORS.txt @@ -0,0 +1,806 @@ +@Switch01 +A_Rog +Aakanksha Agrawal +Abhinav Sagar +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Wentz +admin +Adolfo Ochagavía +Adrien Morison +Agus +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Alberto Sottile +Aleks Bunin +Ales Erjavec +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Hedges +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Aleš Erjavec +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andre Aguiar +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrew Shymanel +Andrey Bienkowski +Andrey Bulgakov +Andrés Delfino +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Anton Zelenov +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anudit Nagar +Anuj Godase +AQNOUCH Mohammed +AraHaan +arena +arenasys +Arindam Choudhury +Armin Ronacher +Arnon Yaari +Artem +Arun Babu Neelicattu +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avinash Karhana +Avner Cohen +Awit (Ah-Wit) Ghirmai +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Bodenmiller +Ben Darnell +Ben Hoyt +Ben Mares +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernard +Bernard Tyers +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bhavam Vidyarthi +Blazej Michalik +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Branch Vincent +Brandon L. Reiss +Brandt Bucher +Brannon Dorsey +Brett Randall +Brett Rosen +Brian Cristante +Brian Rosner +briantracy +BrownTruck +Bruno Oliveira +Bruno Renié +Bruno S +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +bwoodsend +c22 +Caleb Brown +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Charlie Marsh +charwick +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris Kuehl +Chris Markiewicz +Chris McDonough +Chris Pawley +Chris Pryer +Chris Wolfe +Christian Clauss +Christian Heimes +Christian Oudard +Christoph Reiter +Christopher Hunt +Christopher Snyder +chrysle +cjc7373 +Clark Boylan +Claudio Jolowicz +Clay McClure +Cody +Cody Soyland +Colin Watson +Collin Anderson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Cristina +Cristina Muñoz +ctg123 +Curtis Doty +cytolentino +Daan De Meyer +Dale +Damian +Damian Quiroga +Damian Shaw +Dan Black +Dan Savilonis +Dan Sully +Dane Hillard +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Katz +Daniel Shaulov +Daniele Esposti +Daniele Nicolodi +Daniele Procida +Daniil Konovalenko +Danny Hermes +Danny McClanahan +Darren Kavanagh +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Caro +David D Lowe +David Evans +David Hewitt +David Linke +David Poggi +David Poznik +David Pursehouse +David Runge +David Tucker +David Wales +Davidovich +ddelange +Deepak Sharma +Deepyaman Datta +Denise Yu +dependabot[bot] +derwolfe +Desetude +Devesh Kumar Singh +devsagul +Diego Caraballo +Diego Ramirez +DiegoCaraballo +Dimitri Merejkowsky +Dimitri Papadopoulos +Dimitri Papadopoulos Orfanos +Dirk Stolle +Dmitry Gladkov +Dmitry Volodin +Domen Kožar +Dominic Davis-Foster +Donald Stufft +Dongweiming +doron zarhi +Dos Moonen +Douglas Thor +DrFeathers +Dustin Ingram +Dustin Rodrigues +Dwayne Bailey +Ed Morley +Edgar Ramírez +Edgar Ramírez Mondragón +Ee Durbin +Efflam Lemaillet +efflamlemaillet +Eitan Adler +ekristina +elainechan +Eli Schwartz +Elisha Hollander +Ellen Marie Dash +Emil Burzo +Emil Styrke +Emmanuel Arias +Endoh Takanao +enoch +Erdinc Mutlu +Eric Cousineau +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Erwin Janssen +Eugene Vereshchagin +everdimension +Federico +Felipe Peter +Felix Yan +fiber-space +Filip Kokosiński +Filipe Laíns +Finn Womack +finnagin +Flavio Amurrio +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Fredrik Orderud +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gavin +gdanielson +Geoffrey Sneddon +George Song +Georgi Valkov +Georgy Pchelkin +ghost +Giftlin Rajaiah +gizmoguy1 +gkdoc +Godefroid Chapelle +Gopinath M +GOTO Hayato +gousaiyang +gpiks +Greg Roodt +Greg Ward +Guilherme Espada +Guillaume Seguin +gutsytechster +Guy Rozendorn +Guy Tuval +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +harupy +Harutaka Kawamura +hauntsaninja +Henrich Hartzer +Henry Schreiner +Herbert Pfennig +Holly Stotelmyer +Honnix +Hsiaoming Yang +Hugo Lopes Tavares +Hugo van Kemenade +Hugues Bruant +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ikko Ashimine +Ilan Schnell +Illia Volochii +Ilya Baryshev +Inada Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Itamar Turner-Trauring +Ivan Pozdeev +J. Nick Koston +Jacob Kim +Jacob Walls +Jaime Sanz +jakirkham +Jakub Kuczys +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Curtin +James Firth +James Gerity +James Polley +Jan Pokorný +Jannis Leidel +Jarek Potiuk +jarondl +Jason Curtis +Jason R. Coombs +JasonMo +JasonMo1 +Jay Graves +Jean Abou Samra +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jeff Widman +Jelmer Vernooij +jenix21 +Jeremy Fleischman +Jeremy Stanley +Jeremy Zafran +Jesse Rittner +Jiashuo Li +Jim Fisher +Jim Garrison +Jinzhe Zeng +Jiun Bae +Jivan Amara +Joe Bylund +Joe Michelini +John Paton +John Sirois +John T. Wodder II +John-Scott Atlakson +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joonatan Partanen +Joost Molenaar +Jorge Niedbalski +Joseph Bylund +Joseph Long +Josh Bronson +Josh Cannon +Josh Hansen +Josh Schneier +Joshua +JoshuaPerdue +Juan Luis Cano Rodríguez +Juanjo Bazán +Judah Rand +Julian Berman +Julian Gethmann +Julien Demoor +July Tikhonov +Jussi Kukkonen +Justin van Heek +jwg4 +Jyrki Pulliainen +Kai Chen +Kai Mueller +Kamal Bin Mustafa +Karolina Surma +kasium +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +Klaas van Schelven +KOLANICH +konstin +kpinc +Krishna Oza +Kumar McMillan +Kuntal Majumder +Kurt McKee +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurent LAPORTE +Laurie O +Laurie Opperman +layday +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +lorddavidiii +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luis Medel +Lukas Geiger +Lukas Juhrich +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +M00nL1ght +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark McLoughlin +Mark Williams +Markus Hametner +Martey Dodoo +Martin Fischer +Martin Häcker +Martin Pavlasek +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Mathieu Kniewallner +Matt Bacchi +Matt Good +Matt Maker +Matt Robenolt +Matt Wozniski +matthew +Matthew Einhorn +Matthew Feickert +Matthew Gilliard +Matthew Hughes +Matthew Iversen +Matthew Treinish +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maurits van Rees +Max W Chase +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna +mdebi +memoselyk +meowmeowcat +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Mintz +Michael Williamson +michaelpacer +Michał Górny +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +morotti +mrKazzila +Muha Ajjan +Nadav Wexler +Nahuel Ambrosini +Nate Coraor +Nate Prewitt +Nathan Houghton +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nguyễn Gia Phong +Nicholas Serra +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nicole Harris +Nikhil Benesch +Nikhil Ladha +Nikita Chepanov +Nikolay Korolev +Nipunn Koorapati +Nitesh Sharma +Niyas Sait +Noah +Noah Gorny +Nowell Strite +NtaleGrey +nvdv +OBITORASU +Ofek Lev +ofrinevo +Oliver Freund +Oliver Jeeves +Oliver Mannion +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +onlinejudge95 +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Ganssle +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavel Safronov +Pavithra Eswaramoorthy +Pawel Jasinski +Paweł Szramowski +Pekka Klärck +Peter Gessler +Peter Lisák +Peter Shen +Peter Waller +Petr Viktorin +petr-tik +Phaneendra Chiruvella +Phil Elson +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +Pieter Degroote +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Prashant Sharma +Pratik Mallya +pre-commit-ci[bot] +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal +q0w +Qiangning Hong +Qiming Xu +Quentin Lee +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Ran Benita +Randy Döring +Razzi Abuissa +rdb +Reece Dunham +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Riccardo Schirone +Richard Jones +Richard Si +Ricky Ng-Adam +Rishi +rmorotti +RobberPhex +Robert Collins +Robert McGibbon +Robert Pollak +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Roman Bogorodskiy +Roman Donchenko +Romuald Brunet +ronaudinho +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Ruairidh MacLeod +Russell Keith-Magee +Ryan Shepherd +Ryan Wooden +ryneeverett +S. Guliaev +Sachi King +Salvatore Rinchiera +sandeepkiran-js +Sander Van Balen +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Michael Larson +Seth Woodworth +Shahar Epstein +Shantanu +shenxianpeng +shireenrao +Shivansh-007 +Shixian Sheng +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +sinscary +snook92 +socketubs +Sorin Sbarnea +Srinivas Nyayapati +Srishti Hegde +Stavros Korokithakis +Stefan Scherfke +Stefano Rivera +Stephan Erb +Stephen Rosen +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +Steven Silvester +stonebig +studioj +Stéphane Bidoul +Stéphane Bidoul (ACSONE) +Stéphane Klein +Sumana Harihareswara +Surbhi Sharma +Sviatoslav Sydorenko +Sviatoslav Sydorenko (Святослав Сидоренко) +Swat009 +Sylvain +Takayuki SHIMIZUKAWA +Taneli Hukkinen +tbeswick +Thiago +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Thomas VINCENT +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tobias Hermann +Tom Forbes +Tom Freudenheim +Tom V +Tomas Hrnciar +Tomas Orsava +Tomer Chachamu +Tommi Enenkel | AnB +Tomáš Hrnčiar +Tony Beswick +Tony Narlock +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +toxinu +Travis Swicegood +Tushar Sadhwani +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Vikram - Google +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo +Vipul Kumar +Vitaly Babiy +Vladimir Fokow +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William Edwards +William ML Leslie +William T Olson +William Woodruff +Wilson Mo +wim glenn +Winson Luk +Wolfgang Maier +Wu Zhenyu +XAMES3 +Xavier Fernandez +Xianpeng Shen +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Yusuke Hayashi +Zearin +Zhiping Deng +ziebam +Zvezdan Petkovic +Łukasz Langa +Роман Донченко +Семён Марьясин diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/top_level.txt b/venv/Lib/site-packages/pip-25.0.1.dist-info/INSTALLER similarity index 100% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/top_level.txt rename to venv/Lib/site-packages/pip-25.0.1.dist-info/INSTALLER diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/LICENSE.txt b/venv/Lib/site-packages/pip-25.0.1.dist-info/LICENSE.txt similarity index 100% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/LICENSE.txt rename to venv/Lib/site-packages/pip-25.0.1.dist-info/LICENSE.txt diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/METADATA b/venv/Lib/site-packages/pip-25.0.1.dist-info/METADATA similarity index 70% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/METADATA rename to venv/Lib/site-packages/pip-25.0.1.dist-info/METADATA index daaddfa..3315c06 100644 --- a/venv/Lib/site-packages/pip-22.2.1.dist-info/METADATA +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/METADATA @@ -1,11 +1,10 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.2 Name: pip -Version: 22.2.1 +Version: 25.0.1 Summary: The PyPA recommended tool for installing Python packages. -Home-page: https://pip.pypa.io/ -Author: The pip developers -Author-email: distutils-sig@python.org +Author-email: The pip developers License: MIT +Project-URL: Homepage, https://pip.pypa.io/ Project-URL: Documentation, https://pip.pypa.io Project-URL: Source, https://github.com/pypa/pip Project-URL: Changelog, https://pip.pypa.io/en/stable/news/ @@ -16,24 +15,35 @@ Classifier: Topic :: Software Development :: Build Tools Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.7 +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst License-File: LICENSE.txt +License-File: AUTHORS.txt pip - The Python Package Installer ================================== -.. image:: https://img.shields.io/pypi/v/pip.svg +.. |pypi-version| image:: https://img.shields.io/pypi/v/pip.svg :target: https://pypi.org/project/pip/ + :alt: PyPI -.. image:: https://readthedocs.org/projects/pip/badge/?version=latest +.. |python-versions| image:: https://img.shields.io/pypi/pyversions/pip + :target: https://pypi.org/project/pip + :alt: PyPI - Python Version + +.. |docs-badge| image:: https://readthedocs.org/projects/pip/badge/?version=latest :target: https://pip.pypa.io/en/latest + :alt: Documentation + +|pypi-version| |python-versions| |docs-badge| pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. @@ -47,10 +57,6 @@ We release updates regularly, with a new version every 3 months. Find more detai * `Release notes`_ * `Release process`_ -In pip 20.3, we've `made a big improvement to the heart of pip`_; `learn more`_. We want your input, so `sign up for our user experience research studies`_ to help us do it right. - -**Note**: pip 21.0, in January 2021, removed Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3. - If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: * `Issue tracking`_ @@ -61,7 +67,6 @@ If you want to get involved head over to GitHub to get the source code, look at * `GitHub page`_ * `Development documentation`_ -* `Development mailing list`_ * `Development IRC`_ Code of Conduct @@ -78,13 +83,8 @@ rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. .. _Release process: https://pip.pypa.io/en/latest/development/release-process/ .. _GitHub page: https://github.com/pypa/pip .. _Development documentation: https://pip.pypa.io/en/latest/development -.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html -.. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020 -.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html -.. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support .. _Issue tracking: https://github.com/pypa/pip/issues .. _Discourse channel: https://discuss.python.org/c/packaging -.. _Development mailing list: https://mail.python.org/mailman3/lists/distutils-sig.python.org/ .. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa .. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev .. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md diff --git a/venv/Lib/site-packages/pip-25.0.1.dist-info/RECORD b/venv/Lib/site-packages/pip-25.0.1.dist-info/RECORD new file mode 100644 index 0000000..59e445b --- /dev/null +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/RECORD @@ -0,0 +1,854 @@ +../../Scripts/pip.exe,sha256=TWiJ5FcJI2RNY2D9Eq2Vpk8aawbkJwUoQGIH4xe81k4,108405 +../../Scripts/pip3.10.exe,sha256=TWiJ5FcJI2RNY2D9Eq2Vpk8aawbkJwUoQGIH4xe81k4,108405 +../../Scripts/pip3.exe,sha256=TWiJ5FcJI2RNY2D9Eq2Vpk8aawbkJwUoQGIH4xe81k4,108405 +pip-25.0.1.dist-info/AUTHORS.txt,sha256=HqzpBVLfT1lBthqQfiDlVeFkg65hJ7ZQvvWhoq-BAsA,11018 +pip-25.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-25.0.1.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093 +pip-25.0.1.dist-info/METADATA,sha256=T6cxjPMPl523zsRcEsu8K0-IoV8S7vv1mmKR0KA6-SY,3677 +pip-25.0.1.dist-info/RECORD,, +pip-25.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip-25.0.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91 +pip-25.0.1.dist-info/entry_points.txt,sha256=eeIjuzfnfR2PrhbjnbzFU6MnSS70kZLxwaHHq6M-bD0,87 +pip-25.0.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/__init__.py,sha256=aKiv_sTe7UbE7qmtCinJutFjqN0MndZQZ1fKLNwFFLE,357 +pip/__main__.py,sha256=WzbhHXTbSE6gBY19mNN9m4s5o_365LOvTYSgqgbdBhE,854 +pip/__pip-runner__.py,sha256=cPPWuJ6NK_k-GzfvlejLFgwzmYUROmpAR6QC3Q-vkXQ,1450 +pip/__pycache__/__init__.cpython-310.pyc,, +pip/__pycache__/__main__.cpython-310.pyc,, +pip/__pycache__/__pip-runner__.cpython-310.pyc,, +pip/_internal/__init__.py,sha256=MfcoOluDZ8QMCFYal04IqOJ9q6m2V7a0aOsnI-WOxUo,513 +pip/_internal/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/__pycache__/build_env.cpython-310.pyc,, +pip/_internal/__pycache__/cache.cpython-310.pyc,, +pip/_internal/__pycache__/configuration.cpython-310.pyc,, +pip/_internal/__pycache__/exceptions.cpython-310.pyc,, +pip/_internal/__pycache__/main.cpython-310.pyc,, +pip/_internal/__pycache__/pyproject.cpython-310.pyc,, +pip/_internal/__pycache__/self_outdated_check.cpython-310.pyc,, +pip/_internal/__pycache__/wheel_builder.cpython-310.pyc,, +pip/_internal/build_env.py,sha256=Dv4UCClSg4uNaal_hL-trg5-zl3Is9CuIDxkChCkXF4,10700 +pip/_internal/cache.py,sha256=Jb698p5PNigRtpW5o26wQNkkUv4MnQ94mc471wL63A0,10369 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-310.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc,, +pip/_internal/cli/__pycache__/command_context.cpython-310.pyc,, +pip/_internal/cli/__pycache__/index_command.cpython-310.pyc,, +pip/_internal/cli/__pycache__/main.cpython-310.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-310.pyc,, +pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc,, +pip/_internal/cli/__pycache__/req_command.cpython-310.pyc,, +pip/_internal/cli/__pycache__/spinners.cpython-310.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-310.pyc,, +pip/_internal/cli/autocompletion.py,sha256=Lli3Mr6aDNu7ZkJJFFvwD2-hFxNI6Avz8OwMyS5TVrs,6865 +pip/_internal/cli/base_command.py,sha256=NZin6KMzW9NSYzKk4Tc8isb_TQYKR4CKd5j9mSm46PI,8625 +pip/_internal/cli/cmdoptions.py,sha256=V3BB22F4_v_RkHaZ5onWnszhbBtjYZvNhbn9M0NO0HI,30116 +pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774 +pip/_internal/cli/index_command.py,sha256=i_sgNlPmXC5iHUaY-dmmrHKKTgc5O4hWzisr5Al1rr0,5677 +pip/_internal/cli/main.py,sha256=BDZef-bWe9g9Jpr4OVs4dDf-845HJsKw835T7AqEnAc,2817 +pip/_internal/cli/main_parser.py,sha256=laDpsuBDl6kyfywp9eMMA9s84jfH2TJJn-vmL0GG90w,4338 +pip/_internal/cli/parser.py,sha256=VCMtduzECUV87KaHNu-xJ-wLNL82yT3x16V4XBxOAqI,10825 +pip/_internal/cli/progress_bars.py,sha256=9GcgusWtwfqou2zhAQp1XNbQHIDslqyyz9UwLzw7Jgc,2717 +pip/_internal/cli/req_command.py,sha256=DqeFhmUMs6o6Ev8qawAcOoYNdAZsfyKS0MZI5jsJYwQ,12250 +pip/_internal/cli/spinners.py,sha256=hIJ83GerdFgFCdobIA23Jggetegl_uC4Sp586nzFbPE,5118 +pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116 +pip/_internal/commands/__init__.py,sha256=5oRO9O3dM2vGuh0bFw4HOVletryrz5HHMmmPWwJrH9U,3882 +pip/_internal/commands/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/commands/__pycache__/cache.cpython-310.pyc,, +pip/_internal/commands/__pycache__/check.cpython-310.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-310.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-310.pyc,, +pip/_internal/commands/__pycache__/debug.cpython-310.pyc,, +pip/_internal/commands/__pycache__/download.cpython-310.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-310.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-310.pyc,, +pip/_internal/commands/__pycache__/help.cpython-310.pyc,, +pip/_internal/commands/__pycache__/index.cpython-310.pyc,, +pip/_internal/commands/__pycache__/inspect.cpython-310.pyc,, +pip/_internal/commands/__pycache__/install.cpython-310.pyc,, +pip/_internal/commands/__pycache__/list.cpython-310.pyc,, +pip/_internal/commands/__pycache__/search.cpython-310.pyc,, +pip/_internal/commands/__pycache__/show.cpython-310.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/commands/cache.py,sha256=IOezTicHjGE5sWdBx2nwPVgbjuJHM3s-BZEkpZLemuY,8107 +pip/_internal/commands/check.py,sha256=Hr_4eiMd9cgVDgEvjtIdw915NmL7ROIWW8enkr8slPQ,2268 +pip/_internal/commands/completion.py,sha256=HT4lD0bgsflHq2IDgYfiEdp7IGGtE7s6MgI3xn0VQEw,4287 +pip/_internal/commands/configuration.py,sha256=n98enwp6y0b5G6fiRQjaZo43FlJKYve_daMhN-4BRNc,9766 +pip/_internal/commands/debug.py,sha256=DNDRgE9YsKrbYzU0s3VKi8rHtKF4X13CJ_br_8PUXO0,6797 +pip/_internal/commands/download.py,sha256=0qB0nys6ZEPsog451lDsjL5Bx7Z97t-B80oFZKhpzKM,5273 +pip/_internal/commands/freeze.py,sha256=2Vt72BYTSm9rzue6d8dNzt8idxWK4Db6Hd-anq7GQ80,3203 +pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703 +pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132 +pip/_internal/commands/index.py,sha256=RAXxmJwFhVb5S1BYzb5ifX3sn9Na8v2CCVYwSMP8pao,4731 +pip/_internal/commands/inspect.py,sha256=PGrY9TRTRCM3y5Ml8Bdk8DEOXquWRfscr4DRo1LOTPc,3189 +pip/_internal/commands/install.py,sha256=r3yHQUxvxt7gD5j9n6zRDslAvtx9CT_whLuQJcktp6M,29390 +pip/_internal/commands/list.py,sha256=oiIzSjLP6__d7dIS3q0Xb5ywsaOThBWRqMyjjKzkPdM,12769 +pip/_internal/commands/search.py,sha256=fWkUQVx_gm8ebbFAlCgqtxKXT9rNahpJ-BI__3HNZpg,5626 +pip/_internal/commands/show.py,sha256=0YBhCga3PAd81vT3l7UWflktSpB5-aYqQcJxBVPazVM,7857 +pip/_internal/commands/uninstall.py,sha256=7pOR7enK76gimyxQbzxcG1OsyLXL3DvX939xmM8Fvtg,3892 +pip/_internal/commands/wheel.py,sha256=eJRhr_qoNNxWAkkdJCNiQM7CXd4E1_YyQhsqJnBPGGg,6414 +pip/_internal/configuration.py,sha256=-KOok6jh3hFzXMPQFPJ1_EFjBpAsge-RSreQuLHLmzo,14005 +pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858 +pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/distributions/__pycache__/base.cpython-310.pyc,, +pip/_internal/distributions/__pycache__/installed.cpython-310.pyc,, +pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc,, +pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/distributions/base.py,sha256=QeB9qvKXDIjLdPBDE5fMgpfGqMMCr-govnuoQnGuiF8,1783 +pip/_internal/distributions/installed.py,sha256=QinHFbWAQ8oE0pbD8MFZWkwlnfU1QYTccA1vnhrlYOU,842 +pip/_internal/distributions/sdist.py,sha256=PlcP4a6-R6c98XnOM-b6Lkb3rsvh9iG4ok8shaanrzs,6751 +pip/_internal/distributions/wheel.py,sha256=THBYfnv7VVt8mYhMYUtH13S1E7FDwtDyDfmUcl8ai0E,1317 +pip/_internal/exceptions.py,sha256=2_byISIv3kSnI_9T-Esfxrt0LnTRgcUHyxu0twsHjQY,26481 +pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 +pip/_internal/index/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/index/__pycache__/collector.cpython-310.pyc,, +pip/_internal/index/__pycache__/package_finder.cpython-310.pyc,, +pip/_internal/index/__pycache__/sources.cpython-310.pyc,, +pip/_internal/index/collector.py,sha256=RdPO0JLAlmyBWPAWYHPyRoGjz3GNAeTngCNkbGey_mE,16265 +pip/_internal/index/package_finder.py,sha256=mJHAljlHeHuclyuxtjvBZO6DtovKjsZjF_tCh_wux5E,38076 +pip/_internal/index/sources.py,sha256=lPBLK5Xiy8Q6IQMio26Wl7ocfZOKkgGklIBNyUJ23fI,8632 +pip/_internal/locations/__init__.py,sha256=UaAxeZ_f93FyouuFf4p7SXYF-4WstXuEvd3LbmPCAno,14925 +pip/_internal/locations/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc,, +pip/_internal/locations/__pycache__/_sysconfig.cpython-310.pyc,, +pip/_internal/locations/__pycache__/base.cpython-310.pyc,, +pip/_internal/locations/_distutils.py,sha256=x6nyVLj7X11Y4khIdf-mFlxMl2FWadtVEgeb8upc_WI,6013 +pip/_internal/locations/_sysconfig.py,sha256=IGzds60qsFneRogC-oeBaY7bEh3lPt_v47kMJChQXsU,7724 +pip/_internal/locations/base.py,sha256=RQiPi1d4FVM2Bxk04dQhXZ2PqkeljEL2fZZ9SYqIQ78,2556 +pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340 +pip/_internal/metadata/__init__.py,sha256=CU8jK1TZso7jOLdr0sX9xDjrcs5iy8d7IRK-hvaIO5Y,4337 +pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/metadata/__pycache__/_json.cpython-310.pyc,, +pip/_internal/metadata/__pycache__/base.cpython-310.pyc,, +pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc,, +pip/_internal/metadata/_json.py,sha256=ezrIYazHCINM2QUk1eA9wEAMj3aeGWeDVgGalgUzKpc,2707 +pip/_internal/metadata/base.py,sha256=ft0K5XNgI4ETqZnRv2-CtvgYiMOMAeGMAzxT-f6VLJA,25298 +pip/_internal/metadata/importlib/__init__.py,sha256=jUUidoxnHcfITHHaAWG1G2i5fdBYklv_uJcjo2x7VYE,135 +pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/metadata/importlib/__pycache__/_compat.cpython-310.pyc,, +pip/_internal/metadata/importlib/__pycache__/_dists.cpython-310.pyc,, +pip/_internal/metadata/importlib/__pycache__/_envs.cpython-310.pyc,, +pip/_internal/metadata/importlib/_compat.py,sha256=c6av8sP8BBjAZuFSJow1iWfygUXNM3xRTCn5nqw6B9M,2796 +pip/_internal/metadata/importlib/_dists.py,sha256=ftmYiyfUGUIjnVwt6W-Ijsimy5c28KgmXly5Q5IQ2P4,8279 +pip/_internal/metadata/importlib/_envs.py,sha256=UUB980XSrDWrMpQ1_G45i0r8Hqlg_tg3IPQ63mEqbNc,7431 +pip/_internal/metadata/pkg_resources.py,sha256=U07ETAINSGeSRBfWUG93E4tZZbaW_f7PGzEqZN0hulc,10542 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-310.pyc,, +pip/_internal/models/__pycache__/direct_url.cpython-310.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-310.pyc,, +pip/_internal/models/__pycache__/index.cpython-310.pyc,, +pip/_internal/models/__pycache__/installation_report.cpython-310.pyc,, +pip/_internal/models/__pycache__/link.cpython-310.pyc,, +pip/_internal/models/__pycache__/scheme.cpython-310.pyc,, +pip/_internal/models/__pycache__/search_scope.cpython-310.pyc,, +pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc,, +pip/_internal/models/__pycache__/target_python.cpython-310.pyc,, +pip/_internal/models/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/models/candidate.py,sha256=zzgFRuw_kWPjKpGw7LC0ZUMD2CQ2EberUIYs8izjdCA,753 +pip/_internal/models/direct_url.py,sha256=uBtY2HHd3TO9cKQJWh0ThvE5FRr-MWRYChRU4IG9HZE,6578 +pip/_internal/models/format_control.py,sha256=wtsQqSK9HaUiNxQEuB-C62eVimw6G4_VQFxV9-_KDBE,2486 +pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030 +pip/_internal/models/installation_report.py,sha256=zRVZoaz-2vsrezj_H3hLOhMZCK9c7TbzWgC-jOalD00,2818 +pip/_internal/models/link.py,sha256=GQ8hq7x-FDFPv25Nbn2veIM-MlBrGZDGLd7aZeF4Xrg,21448 +pip/_internal/models/scheme.py,sha256=PakmHJM3e8OOWSZFtfz1Az7f1meONJnkGuQxFlt3wBE,575 +pip/_internal/models/search_scope.py,sha256=67NEnsYY84784S-MM7ekQuo9KXLH-7MzFntXjapvAo0,4531 +pip/_internal/models/selection_prefs.py,sha256=qaFfDs3ciqoXPg6xx45N1jPLqccLJw4N0s4P0PyHTQ8,2015 +pip/_internal/models/target_python.py,sha256=2XaH2rZ5ZF-K5wcJbEMGEl7SqrTToDDNkrtQ2v_v_-Q,4271 +pip/_internal/models/wheel.py,sha256=G7dND_s4ebPkEL7RJ1qCY0QhUUWIIK6AnjWgRATF5no,4539 +pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 +pip/_internal/network/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/network/__pycache__/auth.cpython-310.pyc,, +pip/_internal/network/__pycache__/cache.cpython-310.pyc,, +pip/_internal/network/__pycache__/download.cpython-310.pyc,, +pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc,, +pip/_internal/network/__pycache__/session.cpython-310.pyc,, +pip/_internal/network/__pycache__/utils.cpython-310.pyc,, +pip/_internal/network/__pycache__/xmlrpc.cpython-310.pyc,, +pip/_internal/network/auth.py,sha256=D4gASjUrqoDFlSt6gQ767KAAjv6PUyJU0puDlhXNVRE,20809 +pip/_internal/network/cache.py,sha256=0yGMA3Eet59xBSLtbPAenvI53dl29oUOeqZ2c0QL2Ss,4614 +pip/_internal/network/download.py,sha256=FLOP29dPYECBiAi7eEjvAbNkyzaKNqbyjOT2m8HPW8U,6048 +pip/_internal/network/lazy_wheel.py,sha256=PBdoMoNQQIA84Fhgne38jWF52W4x_KtsHjxgv4dkRKA,7622 +pip/_internal/network/session.py,sha256=msM4es16LmmNEYNkrYyg8fTc7gAHbKFltawfKP27LOI,18771 +pip/_internal/network/utils.py,sha256=Inaxel-NxBu4PQWkjyErdnfewsFCcgHph7dzR1-FboY,4088 +pip/_internal/network/xmlrpc.py,sha256=sAxzOacJ-N1NXGPvap9jC3zuYWSnnv3GXtgR2-E2APA,1838 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/operations/__pycache__/check.cpython-310.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-310.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-310.pyc,, +pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/build/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/metadata_editable.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/wheel_editable.cpython-310.pyc,, +pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-310.pyc,, +pip/_internal/operations/build/build_tracker.py,sha256=-ARW_TcjHCOX7D2NUOGntB4Fgc6b4aolsXkAK6BWL7w,4774 +pip/_internal/operations/build/metadata.py,sha256=9S0CUD8U3QqZeXp-Zyt8HxwU90lE4QrnYDgrqZDzBnc,1422 +pip/_internal/operations/build/metadata_editable.py,sha256=xlAwcP9q_8_fmv_3I39w9EZ7SQV9hnJZr9VuTsq2Y68,1510 +pip/_internal/operations/build/metadata_legacy.py,sha256=8i6i1QZX9m_lKPStEFsHKM0MT4a-CD408JOw99daLmo,2190 +pip/_internal/operations/build/wheel.py,sha256=sT12FBLAxDC6wyrDorh8kvcZ1jG5qInCRWzzP-UkJiQ,1075 +pip/_internal/operations/build/wheel_editable.py,sha256=yOtoH6zpAkoKYEUtr8FhzrYnkNHQaQBjWQ2HYae1MQg,1417 +pip/_internal/operations/build/wheel_legacy.py,sha256=K-6kNhmj-1xDF45ny1yheMerF0ui4EoQCLzEoHh6-tc,3045 +pip/_internal/operations/check.py,sha256=L24vRL8VWbyywdoeAhM89WCd8zLTnjIbULlKelUgIec,5912 +pip/_internal/operations/freeze.py,sha256=1_M79jAQKnCxWr-KCCmHuVXOVFGaUJHmoWLfFzgh7K4,9843 +pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 +pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc,, +pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/operations/install/editable_legacy.py,sha256=PoEsNEPGbIZ2yQphPsmYTKLOCMs4gv5OcCdzW124NcA,1283 +pip/_internal/operations/install/wheel.py,sha256=X5Iz9yUg5LlK5VNQ9g2ikc6dcRu8EPi_SUi5iuEDRgo,27615 +pip/_internal/operations/prepare.py,sha256=joWJwPkuqGscQgVNImLK71e9hRapwKvRCM8HclysmvU,28118 +pip/_internal/pyproject.py,sha256=GLJ6rWRS5_2noKdajohoLyDty57Z7QXhcUAYghmTnWc,7286 +pip/_internal/req/__init__.py,sha256=HxBFtZy_BbCclLgr26waMtpzYdO5T3vxePvpGAXSt5s,2653 +pip/_internal/req/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-310.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-310.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-310.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-310.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc,, +pip/_internal/req/constructors.py,sha256=v1qzCN1mIldwx-nCrPc8JO4lxkm3Fv8M5RWvt8LISjc,18430 +pip/_internal/req/req_file.py,sha256=eys82McgaICOGic2UZRHjD720piKJPwmeSYdXlWwl6w,20234 +pip/_internal/req/req_install.py,sha256=BMptxHYg2uG_b-7HFEULPb3nuw0FMAbuea8zTq2rE7w,35786 +pip/_internal/req/req_set.py,sha256=j3esG0s6SzoVReX9rWn4rpYNtyET_fwxbwJPRimvRxo,2858 +pip/_internal/req/req_uninstall.py,sha256=qzDIxJo-OETWqGais7tSMCDcWbATYABT-Tid3ityF0s,23853 +pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/resolution/__pycache__/base.cpython-310.pyc,, +pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583 +pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc,, +pip/_internal/resolution/legacy/resolver.py,sha256=3HZiJBRd1FTN6jQpI4qRO8-TbLYeIbUTS6PFvXnXs2w,24068 +pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/base.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc,, +pip/_internal/resolution/resolvelib/base.py,sha256=DCf669FsqyQY5uqXeePDHQY1e4QO-pBzWH8O0s9-K94,5023 +pip/_internal/resolution/resolvelib/candidates.py,sha256=5UZ1upNnmqsP-nmEZaDYxaBgCoejw_e2WVGmmAvBxXc,20001 +pip/_internal/resolution/resolvelib/factory.py,sha256=MJOLSZJY8_28PPdcutoQ6gjJ_1eBDt6Z1edtfTJyR4E,32659 +pip/_internal/resolution/resolvelib/found_candidates.py,sha256=9hrTyQqFvl9I7Tji79F1AxHv39Qh1rkJ_7deSHSMfQc,6383 +pip/_internal/resolution/resolvelib/provider.py,sha256=bcsFnYvlmtB80cwVdW1fIwgol8ZNr1f1VHyRTkz47SM,9935 +pip/_internal/resolution/resolvelib/reporter.py,sha256=00JtoXEkTlw0-rl_sl54d71avwOsJHt9GGHcrj5Sza0,3168 +pip/_internal/resolution/resolvelib/requirements.py,sha256=7JG4Z72e5Yk4vU0S5ulGvbqTy4FMQGYhY5zQhX9zTtY,8065 +pip/_internal/resolution/resolvelib/resolver.py,sha256=nLJOsVMEVi2gQUVJoUFKMZAeu2f7GRMjGMvNSWyz0Bc,12592 +pip/_internal/self_outdated_check.py,sha256=1PFtttvLAeyCVR3tPoBq2sOlPD0IJ-KSqU6bc1HUk9c,8318 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/utils/__pycache__/_jaraco_text.cpython-310.pyc,, +pip/_internal/utils/__pycache__/_log.cpython-310.pyc,, +pip/_internal/utils/__pycache__/appdirs.cpython-310.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-310.pyc,, +pip/_internal/utils/__pycache__/compatibility_tags.cpython-310.pyc,, +pip/_internal/utils/__pycache__/datetime.cpython-310.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc,, +pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc,, +pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc,, +pip/_internal/utils/__pycache__/entrypoints.cpython-310.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc,, +pip/_internal/utils/__pycache__/filetypes.cpython-310.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-310.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-310.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-310.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-310.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-310.pyc,, +pip/_internal/utils/__pycache__/retry.cpython-310.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-310.pyc,, +pip/_internal/utils/__pycache__/subprocess.cpython-310.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-310.pyc,, +pip/_internal/utils/__pycache__/unpacking.cpython-310.pyc,, +pip/_internal/utils/__pycache__/urls.cpython-310.pyc,, +pip/_internal/utils/__pycache__/virtualenv.cpython-310.pyc,, +pip/_internal/utils/__pycache__/wheel.cpython-310.pyc,, +pip/_internal/utils/_jaraco_text.py,sha256=M15uUPIh5NpP1tdUGBxRau6q1ZAEtI8-XyLEETscFfE,3350 +pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015 +pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665 +pip/_internal/utils/compat.py,sha256=ckkFveBiYQjRWjkNsajt_oWPS57tJvE8XxoC4OIYgCY,2399 +pip/_internal/utils/compatibility_tags.py,sha256=OWq5axHpW-MEEPztGdvgADrgJPAcV9a88Rxm4Z8VBs8,6272 +pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242 +pip/_internal/utils/deprecation.py,sha256=k7Qg_UBAaaTdyq82YVARA6D7RmcGTXGv7fnfcgigj4Q,3707 +pip/_internal/utils/direct_url_helpers.py,sha256=r2MRtkVDACv9AGqYODBUC9CjwgtsUU1s68hmgfCJMtA,3196 +pip/_internal/utils/egg_link.py,sha256=0FePZoUYKv4RGQ2t6x7w5Z427wbA_Uo3WZnAkrgsuqo,2463 +pip/_internal/utils/entrypoints.py,sha256=YlhLTRl2oHBAuqhc-zmL7USS67TPWVHImjeAQHreZTQ,3064 +pip/_internal/utils/filesystem.py,sha256=ajvA-q4ocliW9kPp8Yquh-4vssXbu-UKbo5FV9V4X64,4950 +pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716 +pip/_internal/utils/glibc.py,sha256=vUkWq_1pJuzcYNcGKLlQmABoUiisK8noYY1yc8Wq4w4,3734 +pip/_internal/utils/hashes.py,sha256=XGGLL0AG8-RhWnyz87xF6MFZ--BKadHU35D47eApCKI,4972 +pip/_internal/utils/logging.py,sha256=ONfbrhaD248akkosK79if97n20EABxwjOxp5dE5RCRY,11845 +pip/_internal/utils/misc.py,sha256=DWnYxBUItjRp7hhxEg4ih6P6YpKrykM86dbi_EcU8SQ,23450 +pip/_internal/utils/packaging.py,sha256=cm-X_0HVHV_jRwUVZh6AuEWqSitzf8EpaJ7Uv2UGu6A,2142 +pip/_internal/utils/retry.py,sha256=mhFbykXjhTnZfgzeuy-vl9c8nECnYn_CMtwNJX2tYzQ,1392 +pip/_internal/utils/setuptools_build.py,sha256=ouXpud-jeS8xPyTPsXJ-m34NPvK5os45otAzdSV_IJE,4435 +pip/_internal/utils/subprocess.py,sha256=EsvqSRiSMHF98T8Txmu6NLU3U--MpTTQjtNgKP0P--M,8988 +pip/_internal/utils/temp_dir.py,sha256=5qOXe8M4JeY6vaFQM867d5zkp1bSwMZ-KT5jymmP0Zg,9310 +pip/_internal/utils/unpacking.py,sha256=_gVdyzTRDMYktpnYljn4OoxrZTtMCf4xknSm4rK0WaA,11967 +pip/_internal/utils/urls.py,sha256=qceSOZb5lbNDrHNsv7_S4L4Ytszja5NwPKUMnZHbYnM,1599 +pip/_internal/utils/virtualenv.py,sha256=S6f7csYorRpiD6cvn3jISZYc3I8PJC43H5iMFpRAEDU,3456 +pip/_internal/utils/wheel.py,sha256=b442jkydFHjXzDy6cMR7MpzWBJ1Q82hR5F33cmcHV3g,4494 +pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596 +pip/_internal/vcs/__pycache__/__init__.cpython-310.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-310.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-310.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-310.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-310.pyc,, +pip/_internal/vcs/__pycache__/versioncontrol.cpython-310.pyc,, +pip/_internal/vcs/bazaar.py,sha256=EKStcQaKpNu0NK4p5Q10Oc4xb3DUxFw024XrJy40bFQ,3528 +pip/_internal/vcs/git.py,sha256=3tpc9LQA_J4IVW5r5NvWaaSeDzcmJOrSFZN0J8vIKfU,18177 +pip/_internal/vcs/mercurial.py,sha256=oULOhzJ2Uie-06d1omkL-_Gc6meGaUkyogvqG9ZCyPs,5249 +pip/_internal/vcs/subversion.py,sha256=ddTugHBqHzV3ebKlU5QXHPN4gUqlyXbOx8q8NgXKvs8,11735 +pip/_internal/vcs/versioncontrol.py,sha256=cvf_-hnTAjQLXJ3d17FMNhQfcO1AcKWUF10tfrYyP-c,22440 +pip/_internal/wheel_builder.py,sha256=DL3A8LKeRj_ACp11WS5wSgASgPFqeyAeXJKdXfmaWXU,11799 +pip/_vendor/__init__.py,sha256=JYuAXvClhInxIrA2FTp5p-uuWVL7WV6-vEpTs46-Qh4,4873 +pip/_vendor/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/__pycache__/typing_extensions.cpython-310.pyc,, +pip/_vendor/cachecontrol/__init__.py,sha256=LMC5CBe94ZRL5xhlzwyPDmHXvBD0p7lT4R3Z73D6a_I,677 +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-310.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-310.pyc,, +pip/_vendor/cachecontrol/_cmd.py,sha256=iist2EpzJvDVIhMAxXq8iFnTBsiZAd6iplxfmNboNyk,1737 +pip/_vendor/cachecontrol/adapter.py,sha256=febjY4LV87iiCIK3jcl8iH58iaSA7b9WkovsByIDK0Y,6348 +pip/_vendor/cachecontrol/cache.py,sha256=OXwv7Fn2AwnKNiahJHnjtvaKLndvVLv_-zO-ltlV9qI,1953 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=dtrrroK5BnADR1GWjCZ19aZ0tFsMfvFBtLQQU1sp_ag,303 +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-310.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-310.pyc,, +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=b7oMgsRSqPmEsonVJw6uFEYUlFgD6GF8TyacOGG1x3M,5399 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=9rmqwtYu_ljVkW6_oLqbC7EaX_a8YT_yLuna-eS0dgo,1386 +pip/_vendor/cachecontrol/controller.py,sha256=glbPj2iZlGqdBg8z09D2DtQOzoOGXnWvy7K2LEyBsEQ,18576 +pip/_vendor/cachecontrol/filewrapper.py,sha256=2ktXNPE0KqnyzF24aOsKCA58HQq1xeC6l2g6_zwjghc,4291 +pip/_vendor/cachecontrol/heuristics.py,sha256=gqMXU8w0gQuEQiSdu3Yg-0vd9kW7nrWKbLca75rheGE,4881 +pip/_vendor/cachecontrol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/cachecontrol/serialize.py,sha256=HQd2IllQ05HzPkVLMXTF2uX5mjEQjDBkxCqUJUODpZk,5163 +pip/_vendor/cachecontrol/wrapper.py,sha256=hsGc7g8QGQTT-4f8tgz3AM5qwScg6FO0BSdLSRdEvpU,1417 +pip/_vendor/certifi/__init__.py,sha256=p_GYZrjUwPBUhpLlCZoGb0miKBKSqDAyZC5DvIuqbHQ,94 +pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255 +pip/_vendor/certifi/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/certifi/__pycache__/__main__.cpython-310.pyc,, +pip/_vendor/certifi/__pycache__/core.cpython-310.pyc,, +pip/_vendor/certifi/cacert.pem,sha256=lO3rZukXdPyuk6BWUJFOKQliWaXH6HGh9l1GGrUgG0c,299427 +pip/_vendor/certifi/core.py,sha256=2SRT5rIcQChFDbe37BQa-kULxAgJ8qN6l1jfqTp4HIs,4486 +pip/_vendor/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/distlib/__init__.py,sha256=dcwgYGYGQqAEawBXPDtIx80DO_3cOmFv8HTc8JMzknQ,625 +pip/_vendor/distlib/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-310.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-310.pyc,, +pip/_vendor/distlib/compat.py,sha256=2jRSjRI4o-vlXeTK2BCGIUhkc6e9ZGhSsacRM5oseTw,41467 +pip/_vendor/distlib/database.py,sha256=mHy_LxiXIsIVRb-T0-idBrVLw3Ffij5teHCpbjmJ9YU,51160 +pip/_vendor/distlib/index.py,sha256=lTbw268rRhj8dw1sib3VZ_0EhSGgoJO3FKJzSFMOaeA,20797 +pip/_vendor/distlib/locators.py,sha256=oBeAZpFuPQSY09MgNnLfQGGAXXvVO96BFpZyKMuK4tM,51026 +pip/_vendor/distlib/manifest.py,sha256=3qfmAmVwxRqU1o23AlfXrQGZzh6g_GGzTAP_Hb9C5zQ,14168 +pip/_vendor/distlib/markers.py,sha256=X6sDvkFGcYS8gUW8hfsWuKEKAqhQZAJ7iXOMLxRYjYk,5164 +pip/_vendor/distlib/metadata.py,sha256=zil3sg2EUfLXVigljY2d_03IJt-JSs7nX-73fECMX2s,38724 +pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820 +pip/_vendor/distlib/scripts.py,sha256=BJliaDAZaVB7WAkwokgC3HXwLD2iWiHaVI50H7C6eG8,18608 +pip/_vendor/distlib/t32.exe,sha256=a0GV5kCoWsMutvliiCKmIgV98eRZ33wXoS-XrqvJQVs,97792 +pip/_vendor/distlib/t64-arm.exe,sha256=68TAa32V504xVBnufojh0PcenpR3U4wAqTqf-MZqbPw,182784 +pip/_vendor/distlib/t64.exe,sha256=gaYY8hy4fbkHYTTnA4i26ct8IQZzkBG2pRdy0iyuBrc,108032 +pip/_vendor/distlib/util.py,sha256=vMPGvsS4j9hF6Y9k3Tyom1aaHLb0rFmZAEyzeAdel9w,66682 +pip/_vendor/distlib/version.py,sha256=s5VIs8wBn0fxzGxWM_aA2ZZyx525HcZbMvcTlTyZ3Rg,23727 +pip/_vendor/distlib/w32.exe,sha256=R4csx3-OGM9kL4aPIzQKRo5TfmRSHZo6QWyLhDhNBks,91648 +pip/_vendor/distlib/w64-arm.exe,sha256=xdyYhKj0WDcVUOCb05blQYvzdYIKMbmJn2SZvzkcey4,168448 +pip/_vendor/distlib/w64.exe,sha256=ejGf-rojoBfXseGLpya6bFTFPWRG21X5KvU8J5iU-K0,101888 +pip/_vendor/distlib/wheel.py,sha256=DFIVguEQHCdxnSdAO0dfFsgMcvVZitg7bCOuLwZ7A_s,43979 +pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981 +pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64 +pip/_vendor/distro/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/distro/__pycache__/__main__.cpython-310.pyc,, +pip/_vendor/distro/__pycache__/distro.cpython-310.pyc,, +pip/_vendor/distro/distro.py,sha256=XqbefacAhDT4zr_trnbA15eY8vdK4GTghgmvUGrEM_4,49430 +pip/_vendor/distro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868 +pip/_vendor/idna/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/codec.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/compat.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/core.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/idnadata.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/intranges.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/package_data.cpython-310.pyc,, +pip/_vendor/idna/__pycache__/uts46data.cpython-310.pyc,, +pip/_vendor/idna/codec.py,sha256=PEew3ItwzjW4hymbasnty2N2OXvNcgHB-JjrBuxHPYY,3422 +pip/_vendor/idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 +pip/_vendor/idna/core.py,sha256=YJYyAMnwiQEPjVC4-Fqu_p4CJ6yKKuDGmppBNQNQpFs,13239 +pip/_vendor/idna/idnadata.py,sha256=W30GcIGvtOWYwAjZj4ZjuouUutC6ffgNuyjJy7fZ-lo,78306 +pip/_vendor/idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 +pip/_vendor/idna/package_data.py,sha256=q59S3OXsc5VI8j6vSD0sGBMyk6zZ4vWFREE88yCJYKs,21 +pip/_vendor/idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/idna/uts46data.py,sha256=rt90K9J40gUSwppDPCrhjgi5AA6pWM65dEGRSf6rIhM,239289 +pip/_vendor/msgpack/__init__.py,sha256=reRaiOtEzSjPnr7TpxjgIvbfln5pV66FhricAs2eC-g,1109 +pip/_vendor/msgpack/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/msgpack/__pycache__/exceptions.cpython-310.pyc,, +pip/_vendor/msgpack/__pycache__/ext.cpython-310.pyc,, +pip/_vendor/msgpack/__pycache__/fallback.cpython-310.pyc,, +pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081 +pip/_vendor/msgpack/ext.py,sha256=kteJv03n9tYzd5oo3xYopVTo4vRaAxonBQQJhXohZZo,5726 +pip/_vendor/msgpack/fallback.py,sha256=0g1Pzp0vtmBEmJ5w9F3s_-JMVURP8RS4G1cc5TRaAsI,32390 +pip/_vendor/packaging/__init__.py,sha256=dk4Ta_vmdVJxYHDcfyhvQNw8V3PgSBomKNXqg-D2JDY,494 +pip/_vendor/packaging/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_elffile.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_parser.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/_tokenizer.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/metadata.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/tags.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-310.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-310.pyc,, +pip/_vendor/packaging/_elffile.py,sha256=cflAQAkE25tzhYmq_aCi72QfbT_tn891tPzfpbeHOwE,3306 +pip/_vendor/packaging/_manylinux.py,sha256=vl5OCoz4kx80H5rwXKeXWjl9WNISGmr4ZgTpTP9lU9c,9612 +pip/_vendor/packaging/_musllinux.py,sha256=p9ZqNYiOItGee8KcZFeHF_YcdhVwGHdK6r-8lgixvGQ,2694 +pip/_vendor/packaging/_parser.py,sha256=s_TvTvDNK0NrM2QB3VKThdWFM4Nc0P6JnkObkl3MjpM,10236 +pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +pip/_vendor/packaging/_tokenizer.py,sha256=J6v5H7Jzvb-g81xp_2QACKwO7LxHQA6ikryMU7zXwN8,5273 +pip/_vendor/packaging/licenses/__init__.py,sha256=A116-FU49_Dz4162M4y1uAiZN4Rgdc83FxNd8EjlfqI,5727 +pip/_vendor/packaging/licenses/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/packaging/licenses/__pycache__/_spdx.cpython-310.pyc,, +pip/_vendor/packaging/licenses/_spdx.py,sha256=oAm1ztPFwlsmCKe7lAAsv_OIOfS1cWDu9bNBkeu-2ns,48398 +pip/_vendor/packaging/markers.py,sha256=c89TNzB7ZdGYhkovm6PYmqGyHxXlYVaLW591PHUNKD8,10561 +pip/_vendor/packaging/metadata.py,sha256=YJibM7GYe4re8-0a3OlXmGS-XDgTEoO4tlBt2q25Bng,34762 +pip/_vendor/packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/packaging/requirements.py,sha256=gYyRSAdbrIyKDY66ugIDUQjRMvxkH2ALioTmX3tnL6o,2947 +pip/_vendor/packaging/specifiers.py,sha256=hGU6kuCd77bL-msIL6yLCp6MNT75RSMUKZDuju26c8U,40098 +pip/_vendor/packaging/tags.py,sha256=CFqrJzAzc2XNGexerH__T-Y5Iwq7WbsYXsiLERLWxY0,21014 +pip/_vendor/packaging/utils.py,sha256=0F3Hh9OFuRgrhTgGZUl5K22Fv1YP2tZl1z_2gO6kJiA,5050 +pip/_vendor/packaging/version.py,sha256=oiHqzTUv_p12hpjgsLDVcaF5hT7pDaSOViUNMD4GTW0,16688 +pip/_vendor/pkg_resources/__init__.py,sha256=jrhDRbOubP74QuPXxd7U7Po42PH2l-LZ2XfcO7llpZ4,124463 +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/platformdirs/__init__.py,sha256=JueR2cRLkxY7iwik-qNWJCwKOrAlBgVgcZ_IHQzqGLE,22344 +pip/_vendor/platformdirs/__main__.py,sha256=jBJ8zb7Mpx5ebcqF83xrpO94MaeCpNGHVf9cvDN2JLg,1505 +pip/_vendor/platformdirs/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/__main__.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/android.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/api.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/macos.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/unix.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/version.cpython-310.pyc,, +pip/_vendor/platformdirs/__pycache__/windows.cpython-310.pyc,, +pip/_vendor/platformdirs/android.py,sha256=kV5oL3V3DZ6WZKu9yFiQupv18yp_jlSV2ChH1TmPcds,9007 +pip/_vendor/platformdirs/api.py,sha256=2dfUDNbEXeDhDKarqtR5NY7oUikUZ4RZhs3ozstmhBQ,9246 +pip/_vendor/platformdirs/macos.py,sha256=UlbyFZ8Rzu3xndCqQEHrfsYTeHwYdFap1Ioz-yxveT4,6154 +pip/_vendor/platformdirs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/platformdirs/unix.py,sha256=uRPJWRyQEtv7yOSvU94rUmsblo5XKDLA1SzFg55kbK0,10393 +pip/_vendor/platformdirs/version.py,sha256=oH4KgTfK4AklbTYVcV_yynvJ9JLI3pyvDVay0hRsLCs,411 +pip/_vendor/platformdirs/windows.py,sha256=IFpiohUBwxPtCzlyKwNtxyW4Jk8haa6W8o59mfrDXVo,10125 +pip/_vendor/pygments/__init__.py,sha256=7N1oiaWulw_nCsTY4EEixYLz15pWY5u4uPAFFi-ielU,2983 +pip/_vendor/pygments/__main__.py,sha256=isIhBxLg65nLlXukG4VkMuPfNdd7gFzTZ_R_z3Q8diY,353 +pip/_vendor/pygments/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/__main__.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/cmdline.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/console.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/filter.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/formatter.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/lexer.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/modeline.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/plugin.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/regexopt.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/scanner.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/sphinxext.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/style.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/token.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/unistring.cpython-310.pyc,, +pip/_vendor/pygments/__pycache__/util.cpython-310.pyc,, +pip/_vendor/pygments/cmdline.py,sha256=LIVzmAunlk9sRJJp54O4KRy9GDIN4Wu13v9p9QzfGPM,23656 +pip/_vendor/pygments/console.py,sha256=yhP9UsLAVmWKVQf2446JJewkA7AiXeeTf4Ieg3Oi2fU,1718 +pip/_vendor/pygments/filter.py,sha256=_ADNPCskD8_GmodHi6_LoVgPU3Zh336aBCT5cOeTMs0,1910 +pip/_vendor/pygments/filters/__init__.py,sha256=RdedK2KWKXlKwR7cvkfr3NUj9YiZQgMgilRMFUg2jPA,40392 +pip/_vendor/pygments/filters/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pygments/formatter.py,sha256=jDWBTndlBH2Z5IYZFVDnP0qn1CaTQjTWt7iAGtCnJEg,4390 +pip/_vendor/pygments/formatters/__init__.py,sha256=8No-NUs8rBTSSBJIv4hSEQt2M0cFB4hwAT0snVc2QGE,5385 +pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/groff.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/html.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/img.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/irc.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/latex.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/other.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/svg.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-310.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-310.pyc,, +pip/_vendor/pygments/formatters/_mapping.py,sha256=1Cw37FuQlNacnxRKmtlPX4nyLoX9_ttko5ZwscNUZZ4,4176 +pip/_vendor/pygments/formatters/bbcode.py,sha256=3JQLI45tcrQ_kRUMjuab6C7Hb0XUsbVWqqbSn9cMjkI,3320 +pip/_vendor/pygments/formatters/groff.py,sha256=M39k0PaSSZRnxWjqBSVPkF0mu1-Vr7bm6RsFvs-CNN4,5106 +pip/_vendor/pygments/formatters/html.py,sha256=SE2jc3YCqbMS3rZW9EAmDlAUhdVxJ52gA4dileEvCGU,35669 +pip/_vendor/pygments/formatters/img.py,sha256=MwA4xWPLOwh6j7Yc6oHzjuqSPt0M1fh5r-5BTIIUfsU,23287 +pip/_vendor/pygments/formatters/irc.py,sha256=dp1Z0l_ObJ5NFh9MhqLGg5ptG5hgJqedT2Vkutt9v0M,4981 +pip/_vendor/pygments/formatters/latex.py,sha256=XMmhOCqUKDBQtG5mGJNAFYxApqaC5puo5cMmPfK3944,19306 +pip/_vendor/pygments/formatters/other.py,sha256=56PMJOliin-rAUdnRM0i1wsV1GdUPd_dvQq0_UPfF9c,5034 +pip/_vendor/pygments/formatters/pangomarkup.py,sha256=y16U00aVYYEFpeCfGXlYBSMacG425CbfoG8oKbKegIg,2218 +pip/_vendor/pygments/formatters/rtf.py,sha256=ZT90dmcKyJboIB0mArhL7IhE467GXRN0G7QAUgG03To,11957 +pip/_vendor/pygments/formatters/svg.py,sha256=KKsiophPupHuxm0So-MsbQEWOT54IAiSF7hZPmxtKXE,7174 +pip/_vendor/pygments/formatters/terminal.py,sha256=AojNG4MlKq2L6IsC_VnXHu4AbHCBn9Otog6u45XvxeI,4674 +pip/_vendor/pygments/formatters/terminal256.py,sha256=kGkNUVo3FpwjytIDS0if79EuUoroAprcWt3igrcIqT0,11753 +pip/_vendor/pygments/lexer.py,sha256=TYHDt___gNW4axTl2zvPZff-VQi8fPaIh5OKRcVSjUM,35349 +pip/_vendor/pygments/lexers/__init__.py,sha256=pIlxyQJuu_syh9lE080cq8ceVbEVcKp0osAFU5fawJU,12115 +pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-310.pyc,, +pip/_vendor/pygments/lexers/__pycache__/python.cpython-310.pyc,, +pip/_vendor/pygments/lexers/_mapping.py,sha256=61-h3zr103m01OS5BUq_AfUiL9YI06Ves9ipQ7k4vr4,76097 +pip/_vendor/pygments/lexers/python.py,sha256=2J_YJrPTr_A6fJY_qKiKv0GpgPwHMrlMSeo59qN3fe4,53687 +pip/_vendor/pygments/modeline.py,sha256=gtRYZBS-CKOCDXHhGZqApboHBaZwGH8gznN3O6nuxj4,1005 +pip/_vendor/pygments/plugin.py,sha256=ioeJ3QeoJ-UQhZpY9JL7vbxsTVuwwM7BCu-Jb8nN0AU,1891 +pip/_vendor/pygments/regexopt.py,sha256=Hky4EB13rIXEHQUNkwmCrYqtIlnXDehNR3MztafZ43w,3072 +pip/_vendor/pygments/scanner.py,sha256=NDy3ofK_fHRFK4hIDvxpamG871aewqcsIb6sgTi7Fhk,3092 +pip/_vendor/pygments/sphinxext.py,sha256=iOptJBcqOGPwMEJ2p70PvwpZPIGdvdZ8dxvq6kzxDgA,7981 +pip/_vendor/pygments/style.py,sha256=rSCZWFpg1_DwFMXDU0nEVmAcBHpuQGf9RxvOPPQvKLQ,6420 +pip/_vendor/pygments/styles/__init__.py,sha256=qUk6_1z5KmT8EdJFZYgESmG6P_HJF_2vVrDD7HSCGYY,2042 +pip/_vendor/pygments/styles/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-310.pyc,, +pip/_vendor/pygments/styles/_mapping.py,sha256=6lovFUE29tz6EsV3XYY4hgozJ7q1JL7cfO3UOlgnS8w,3312 +pip/_vendor/pygments/token.py,sha256=qZwT7LSPy5YBY3JgDjut642CCy7JdQzAfmqD9NmT5j0,6226 +pip/_vendor/pygments/unistring.py,sha256=p5c1i-HhoIhWemy9CUsaN9o39oomYHNxXll0Xfw6tEA,63208 +pip/_vendor/pygments/util.py,sha256=2tj2nS1X9_OpcuSjf8dOET2bDVZhs8cEKd_uT6-Fgg8,10031 +pip/_vendor/pyproject_hooks/__init__.py,sha256=cPB_a9LXz5xvsRbX1o2qyAdjLatZJdQ_Lc5McNX-X7Y,691 +pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-310.pyc,, +pip/_vendor/pyproject_hooks/_impl.py,sha256=jY-raxnmyRyB57ruAitrJRUzEexuAhGTpgMygqx67Z4,14936 +pip/_vendor/pyproject_hooks/_in_process/__init__.py,sha256=MJNPpfIxcO-FghxpBbxkG1rFiQf6HOUbV4U5mq0HFns,557 +pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-310.pyc,, +pip/_vendor/pyproject_hooks/_in_process/_in_process.py,sha256=qcXMhmx__MIJq10gGHW3mA4Tl8dy8YzHMccwnNoKlw0,12216 +pip/_vendor/pyproject_hooks/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/requests/__init__.py,sha256=HlB_HzhrzGtfD_aaYUwUh1zWXLZ75_YCLyit75d0Vz8,5057 +pip/_vendor/requests/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/__version__.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/_internal_utils.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/help.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/packages.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-310.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-310.pyc,, +pip/_vendor/requests/__version__.py,sha256=FVfglgZmNQnmYPXpOohDU58F5EUb_-VnSTaAesS187g,435 +pip/_vendor/requests/_internal_utils.py,sha256=nMQymr4hs32TqVo5AbCrmcJEhvPUh7xXlluyqwslLiQ,1495 +pip/_vendor/requests/adapters.py,sha256=J7VeVxKBvawbtlX2DERVo05J9BXTcWYLMHNd1Baa-bk,27607 +pip/_vendor/requests/api.py,sha256=_Zb9Oa7tzVIizTKwFrPjDEY9ejtm_OnSRERnADxGsQs,6449 +pip/_vendor/requests/auth.py,sha256=kF75tqnLctZ9Mf_hm9TZIj4cQWnN5uxRz8oWsx5wmR0,10186 +pip/_vendor/requests/certs.py,sha256=kHDlkK_beuHXeMPc5jta2wgl8gdKeUWt5f2nTDVrvt8,441 +pip/_vendor/requests/compat.py,sha256=Mo9f9xZpefod8Zm-n9_StJcVTmwSukXR2p3IQyyVXvU,1485 +pip/_vendor/requests/cookies.py,sha256=bNi-iqEj4NPZ00-ob-rHvzkvObzN3lEpgw3g6paS3Xw,18590 +pip/_vendor/requests/exceptions.py,sha256=D1wqzYWne1mS2rU43tP9CeN1G7QAy7eqL9o1god6Ejw,4272 +pip/_vendor/requests/help.py,sha256=hRKaf9u0G7fdwrqMHtF3oG16RKktRf6KiwtSq2Fo1_0,3813 +pip/_vendor/requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733 +pip/_vendor/requests/models.py,sha256=x4K4CmH-lC0l2Kb-iPfMN4dRXxHEcbOaEWBL_i09AwI,35483 +pip/_vendor/requests/packages.py,sha256=_ZQDCJTJ8SP3kVWunSqBsRZNPzj2c1WFVqbdr08pz3U,1057 +pip/_vendor/requests/sessions.py,sha256=ykTI8UWGSltOfH07HKollH7kTBGw4WhiBVaQGmckTw4,30495 +pip/_vendor/requests/status_codes.py,sha256=iJUAeA25baTdw-6PfD0eF4qhpINDJRJI-yaMqxs4LEI,4322 +pip/_vendor/requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912 +pip/_vendor/requests/utils.py,sha256=L79vnFbzJ3SFLKtJwpoWe41Tozi3RlZv94pY1TFIyow,33631 +pip/_vendor/resolvelib/__init__.py,sha256=h509TdEcpb5-44JonaU3ex2TM15GVBLjM9CNCPwnTTs,537 +pip/_vendor/resolvelib/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/resolvelib/__pycache__/providers.cpython-310.pyc,, +pip/_vendor/resolvelib/__pycache__/reporters.cpython-310.pyc,, +pip/_vendor/resolvelib/__pycache__/resolvers.cpython-310.pyc,, +pip/_vendor/resolvelib/__pycache__/structs.cpython-310.pyc,, +pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-310.pyc,, +pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156 +pip/_vendor/resolvelib/providers.py,sha256=fuuvVrCetu5gsxPB43ERyjfO8aReS3rFQHpDgiItbs4,5871 +pip/_vendor/resolvelib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/resolvelib/reporters.py,sha256=TSbRmWzTc26w0ggsV1bxVpeWDB8QNIre6twYl7GIZBE,1601 +pip/_vendor/resolvelib/resolvers.py,sha256=G8rsLZSq64g5VmIq-lB7UcIJ1gjAxIQJmTF4REZleQ0,20511 +pip/_vendor/resolvelib/structs.py,sha256=0_1_XO8z_CLhegP3Vpf9VJ3zJcfLm0NOHRM-i0Ykz3o,4963 +pip/_vendor/rich/__init__.py,sha256=dRxjIL-SbFVY0q3IjSMrfgBTHrm1LZDgLOygVBwiYZc,6090 +pip/_vendor/rich/__main__.py,sha256=eO7Cq8JnrgG8zVoeImiAs92q3hXNMIfp0w5lMsO7Q2Y,8477 +pip/_vendor/rich/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/__main__.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_cell_widths.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_emoji_codes.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_emoji_replace.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_export_format.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_extension.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_fileno.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_inspect.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_log_render.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_loop.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_null_file.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_palettes.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_pick.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_ratio.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_spinners.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_stack.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_timer.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_win32_console.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_windows.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_windows_renderer.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/_wrap.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/abc.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/align.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/ansi.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/bar.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/box.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/cells.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/color.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/color_triplet.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/columns.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/console.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/constrain.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/containers.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/control.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/default_styles.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/diagnose.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/emoji.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/errors.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/file_proxy.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/filesize.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/highlighter.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/json.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/jupyter.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/layout.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/live.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/live_render.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/logging.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/markup.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/measure.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/padding.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/pager.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/palette.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/panel.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/pretty.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/progress.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/progress_bar.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/prompt.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/protocol.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/region.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/repr.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/rule.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/scope.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/screen.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/segment.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/spinner.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/status.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/style.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/styled.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/syntax.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/table.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/terminal_theme.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/text.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/theme.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/themes.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/traceback.cpython-310.pyc,, +pip/_vendor/rich/__pycache__/tree.cpython-310.pyc,, +pip/_vendor/rich/_cell_widths.py,sha256=fbmeyetEdHjzE_Vx2l1uK7tnPOhMs2X1lJfO3vsKDpA,10209 +pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235 +pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064 +pip/_vendor/rich/_export_format.py,sha256=RI08pSrm5tBSzPMvnbTqbD9WIalaOoN5d4M1RTmLq1Y,2128 +pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265 +pip/_vendor/rich/_fileno.py,sha256=HWZxP5C2ajMbHryvAQZseflVfQoGzsKOHzKGsLD8ynQ,799 +pip/_vendor/rich/_inspect.py,sha256=QM05lEFnFoTaFqpnbx-zBEI6k8oIKrD3cvjEOQNhKig,9655 +pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225 +pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236 +pip/_vendor/rich/_null_file.py,sha256=ADGKp1yt-k70FMKV6tnqCqecB-rSJzp-WQsD7LPL-kg,1394 +pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063 +pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423 +pip/_vendor/rich/_ratio.py,sha256=Zt58apszI6hAAcXPpgdWKpu3c31UBWebOeR4mbyptvU,5471 +pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919 +pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351 +pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417 +pip/_vendor/rich/_win32_console.py,sha256=BSaDRIMwBLITn_m0mTRLPqME5q-quGdSMuYMpYeYJwc,22755 +pip/_vendor/rich/_windows.py,sha256=aBwaD_S56SbgopIvayVmpk0Y28uwY2C5Bab1wl3Bp-I,1925 +pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783 +pip/_vendor/rich/_wrap.py,sha256=FlSsom5EX0LVkA3KWy34yHnCfLtqX-ZIepXKh-70rpc,3404 +pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890 +pip/_vendor/rich/align.py,sha256=Rh-3adnDaN1Ao07EjR2PhgE62PGLPgO8SMwJBku1urQ,10469 +pip/_vendor/rich/ansi.py,sha256=Avs1LHbSdcyOvDOdpELZUoULcBiYewY76eNBp6uFBhs,6921 +pip/_vendor/rich/bar.py,sha256=ldbVHOzKJOnflVNuv1xS7g6dLX2E3wMnXkdPbpzJTcs,3263 +pip/_vendor/rich/box.py,sha256=nr5fYIUghB_iUCEq6y0Z3LlCT8gFPDrzN9u2kn7tJl4,10831 +pip/_vendor/rich/cells.py,sha256=KrQkj5-LghCCpJLSNQIyAZjndc4bnEqOEmi5YuZ9UCY,5130 +pip/_vendor/rich/color.py,sha256=3HSULVDj7qQkXUdFWv78JOiSZzfy5y1nkcYhna296V0,18211 +pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054 +pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131 +pip/_vendor/rich/console.py,sha256=nKjrEx_7xy8KGmDVT-BgNII0R5hm1cexhAHDwdwNVqg,100156 +pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288 +pip/_vendor/rich/containers.py,sha256=c_56TxcedGYqDepHBMTuZdUIijitAQgnox-Qde0Z1qo,5502 +pip/_vendor/rich/control.py,sha256=DSkHTUQLorfSERAKE_oTAEUFefZnZp4bQb4q8rHbKws,6630 +pip/_vendor/rich/default_styles.py,sha256=dZxgaSD9VUy7SXQShO33aLYiAWspCr2sCQZFX_JK1j4,8159 +pip/_vendor/rich/diagnose.py,sha256=an6uouwhKPAlvQhYpNNpGq9EJysfMIOvvCbO3oSoR24,972 +pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501 +pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642 +pip/_vendor/rich/file_proxy.py,sha256=Tl9THMDZ-Pk5Wm8sI1gGg_U5DhusmxD-FZ0fUbcU0W0,1683 +pip/_vendor/rich/filesize.py,sha256=_iz9lIpRgvW7MNSeCZnLg-HwzbP4GETg543WqD8SFs0,2484 +pip/_vendor/rich/highlighter.py,sha256=G_sn-8DKjM1sEjLG_oc4ovkWmiUpWvj8bXi0yed2LnY,9586 +pip/_vendor/rich/json.py,sha256=vVEoKdawoJRjAFayPwXkMBPLy7RSTs-f44wSQDR2nJ0,5031 +pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252 +pip/_vendor/rich/layout.py,sha256=ajkSFAtEVv9EFTcFs-w4uZfft7nEXhNzL7ZVdgrT5rI,14004 +pip/_vendor/rich/live.py,sha256=DhzAPEnjTxQuq9_0Y2xh2MUwQcP_aGPkenLfKETslwM,14270 +pip/_vendor/rich/live_render.py,sha256=zJtB471jGziBtEwxc54x12wEQtH4BuQr1SA8v9kU82w,3666 +pip/_vendor/rich/logging.py,sha256=ZgpKMMBY_BuMAI_BYzo-UtXak6t5oH9VK8m9Q2Lm0f4,12458 +pip/_vendor/rich/markup.py,sha256=3euGKP5s41NCQwaSjTnJxus5iZMHjxpIM0W6fCxra38,8451 +pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305 +pip/_vendor/rich/padding.py,sha256=KVEI3tOwo9sgK1YNSuH__M1_jUWmLZwRVV_KmOtVzyM,4908 +pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828 +pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396 +pip/_vendor/rich/panel.py,sha256=fFRHcviXvWhk3V3zx5Zwmsb_RL9KJ3esD-sU0NYEVyw,11235 +pip/_vendor/rich/pretty.py,sha256=gy3S72u4FRg2ytoo7N1ZDWDIvB4unbzd5iUGdgm-8fc,36391 +pip/_vendor/rich/progress.py,sha256=MtmCjTk5zYU_XtRHxRHTAEHG6hF9PeF7EMWbEPleIC0,60357 +pip/_vendor/rich/progress_bar.py,sha256=mZTPpJUwcfcdgQCTTz3kyY-fc79ddLwtx6Ghhxfo064,8162 +pip/_vendor/rich/prompt.py,sha256=l0RhQU-0UVTV9e08xW1BbIj0Jq2IXyChX4lC0lFNzt4,12447 +pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391 +pip/_vendor/rich/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166 +pip/_vendor/rich/repr.py,sha256=5MZJZmONgC6kud-QW-_m1okXwL2aR6u6y-pUcUCJz28,4431 +pip/_vendor/rich/rule.py,sha256=0fNaS_aERa3UMRc3T5WMpN_sumtDxfaor2y3of1ftBk,4602 +pip/_vendor/rich/scope.py,sha256=TMUU8qo17thyqQCPqjDLYpg_UU1k5qVd-WwiJvnJVas,2843 +pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591 +pip/_vendor/rich/segment.py,sha256=otnKeKGEV-WRlQVosfJVeFDcDxAKHpvJ_hLzSu5lumM,24743 +pip/_vendor/rich/spinner.py,sha256=PT5qgXPG3ZpqRj7n3EZQ6NW56mx3ldZqZCU7gEMyZk4,4364 +pip/_vendor/rich/status.py,sha256=kkPph3YeAZBo-X-4wPp8gTqZyU466NLwZBA4PZTTewo,4424 +pip/_vendor/rich/style.py,sha256=aSoUNbVgfP1PAnduAqgbbl4AMQy668qs2S1FEwr3Oqs,27067 +pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258 +pip/_vendor/rich/syntax.py,sha256=qqAnEUZ4K57Po81_5RBxnsuU4KRzSdvDPAhKw8ma_3E,35763 +pip/_vendor/rich/table.py,sha256=yXYUr0YsPpG466N50HCAw2bpb5ZUuuzdc-G66Zk-oTc,40103 +pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370 +pip/_vendor/rich/text.py,sha256=AO7JPCz6-gaN1thVLXMBntEmDPVYFgFNG1oM61_sanU,47552 +pip/_vendor/rich/theme.py,sha256=oNyhXhGagtDlbDye3tVu3esWOWk0vNkuxFw-_unlaK0,3771 +pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102 +pip/_vendor/rich/traceback.py,sha256=z8UoN7NbTQKW6YDDUVwOh7F8snZf6gYnUWtOrKsLE1w,31797 +pip/_vendor/rich/tree.py,sha256=yWnQ6rAvRGJ3qZGqBrxS2SW2TKBTNrP0SdY8QxOFPuw,9451 +pip/_vendor/tomli/__init__.py,sha256=PhNw_eyLgdn7McJ6nrAN8yIm3dXC75vr1sVGVVwDSpA,314 +pip/_vendor/tomli/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/tomli/__pycache__/_parser.cpython-310.pyc,, +pip/_vendor/tomli/__pycache__/_re.cpython-310.pyc,, +pip/_vendor/tomli/__pycache__/_types.cpython-310.pyc,, +pip/_vendor/tomli/_parser.py,sha256=9w8LG0jB7fwmZZWB0vVXbeejDHcl4ANIJxB2scEnDlA,25591 +pip/_vendor/tomli/_re.py,sha256=sh4sBDRgO94KJZwNIrgdcyV_qQast50YvzOAUGpRDKA,3171 +pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254 +pip/_vendor/tomli/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26 +pip/_vendor/truststore/__init__.py,sha256=WIDeyzWm7EVX44g354M25vpRXbeY1lsPH6EmUJUcq4o,1264 +pip/_vendor/truststore/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/truststore/__pycache__/_api.cpython-310.pyc,, +pip/_vendor/truststore/__pycache__/_macos.cpython-310.pyc,, +pip/_vendor/truststore/__pycache__/_openssl.cpython-310.pyc,, +pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-310.pyc,, +pip/_vendor/truststore/__pycache__/_windows.cpython-310.pyc,, +pip/_vendor/truststore/_api.py,sha256=GeXRNTlxPZ3kif4kNoh6JY0oE4QRzTGcgXr6l_X_Gk0,10555 +pip/_vendor/truststore/_macos.py,sha256=nZlLkOmszUE0g6ryRwBVGY5COzPyudcsiJtDWarM5LQ,20503 +pip/_vendor/truststore/_openssl.py,sha256=LLUZ7ZGaio-i5dpKKjKCSeSufmn6T8pi9lDcFnvSyq0,2324 +pip/_vendor/truststore/_ssl_constants.py,sha256=NUD4fVKdSD02ri7-db0tnO0VqLP9aHuzmStcW7tAl08,1130 +pip/_vendor/truststore/_windows.py,sha256=rAHyKYD8M7t-bXfG8VgOVa3TpfhVhbt4rZQlO45YuP8,17993 +pip/_vendor/truststore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/typing_extensions.py,sha256=78hFl0HpDY-ylHUVCnWdU5nTHxUP2-S-3wEZk6CQmLk,134499 +pip/_vendor/urllib3/__init__.py,sha256=iXLcYiJySn0GNbWOOZDDApgBL1JgP44EZ8i1760S8Mc,3333 +pip/_vendor/urllib3/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/_collections.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/_version.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/connection.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/connectionpool.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/exceptions.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/fields.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/filepost.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/poolmanager.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/request.cpython-310.pyc,, +pip/_vendor/urllib3/__pycache__/response.cpython-310.pyc,, +pip/_vendor/urllib3/_collections.py,sha256=pyASJJhW7wdOpqJj9QJA8FyGRfr8E8uUUhqUvhF0728,11372 +pip/_vendor/urllib3/_version.py,sha256=t9wGB6ooOTXXgiY66K1m6BZS1CJyXHAU8EoWDTe6Shk,64 +pip/_vendor/urllib3/connection.py,sha256=ttIA909BrbTUzwkqEe_TzZVh4JOOj7g61Ysei2mrwGg,20314 +pip/_vendor/urllib3/connectionpool.py,sha256=e2eiAwNbFNCKxj4bwDKNK-w7HIdSz3OmMxU_TIt-evQ,40408 +pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957 +pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-310.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632 +pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922 +pip/_vendor/urllib3/contrib/appengine.py,sha256=VR68eAVE137lxTgjBDwCna5UiBZTOKa01Aj_-5BaCz4,11036 +pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=NlfkW7WMdW8ziqudopjHoW299og1BTWi0IeIibquFwk,4528 +pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=hDJh4MhyY_p-oKlFcYcQaVQRDv6GMmBGuW9yjxyeejM,17081 +pip/_vendor/urllib3/contrib/securetransport.py,sha256=Fef1IIUUFHqpevzXiDPbIGkDKchY2FVKeVeLGR1Qq3g,34446 +pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097 +pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217 +pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579 +pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440 +pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/packages/__pycache__/six.cpython-310.pyc,, +pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-310.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-310.pyc,, +pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417 +pip/_vendor/urllib3/packages/backports/weakref_finalize.py,sha256=tRCal5OAhNSRyb0DhHp-38AtIlCsRP8BxF3NX-6rqIA,5343 +pip/_vendor/urllib3/packages/six.py,sha256=b9LM0wBXv7E7SrbCjAm4wwN-hrH-iNxv18LgWNMMKPo,34665 +pip/_vendor/urllib3/poolmanager.py,sha256=aWyhXRtNO4JUnCSVVqKTKQd8EXTvUm1VN9pgs2bcONo,19990 +pip/_vendor/urllib3/request.py,sha256=YTWFNr7QIwh7E1W9dde9LM77v2VWTJ5V78XuTTw7D1A,6691 +pip/_vendor/urllib3/response.py,sha256=fmDJAFkG71uFTn-sVSTh2Iw0WmcXQYqkbRjihvwBjU8,30641 +pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155 +pip/_vendor/urllib3/util/__pycache__/__init__.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/connection.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/proxy.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/queue.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/request.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/response.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/retry.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/timeout.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/url.cpython-310.pyc,, +pip/_vendor/urllib3/util/__pycache__/wait.cpython-310.pyc,, +pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901 +pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605 +pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498 +pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997 +pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510 +pip/_vendor/urllib3/util/retry.py,sha256=6ENvOZ8PBDzh8kgixpql9lIrb2dxH-k7ZmBanJF2Ng4,22050 +pip/_vendor/urllib3/util/ssl_.py,sha256=QDuuTxPSCj1rYtZ4xpD7Ux-r20TD50aHyqKyhQ7Bq4A,17460 +pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758 +pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895 +pip/_vendor/urllib3/util/timeout.py,sha256=cwq4dMk87mJHSBktK1miYJ-85G-3T3RmT20v7SFCpno,10168 +pip/_vendor/urllib3/util/url.py,sha256=lCAE7M5myA8EDdW0sJuyyZhVB9K_j38ljWhHAnFaWoE,14296 +pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403 +pip/_vendor/vendor.txt,sha256=EW-E3cE5XEAtVFzGInikArOMDxGP0DLUWzXpY4RZfFY,333 +pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py b/venv/Lib/site-packages/pip-25.0.1.dist-info/REQUESTED similarity index 100% rename from venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py rename to venv/Lib/site-packages/pip-25.0.1.dist-info/REQUESTED diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/WHEEL b/venv/Lib/site-packages/pip-25.0.1.dist-info/WHEEL similarity index 65% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/WHEEL rename to venv/Lib/site-packages/pip-25.0.1.dist-info/WHEEL index becc9a6..505164b 100644 --- a/venv/Lib/site-packages/pip-22.2.1.dist-info/WHEEL +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/WHEEL @@ -1,5 +1,5 @@ Wheel-Version: 1.0 -Generator: bdist_wheel (0.37.1) +Generator: setuptools (75.8.0) Root-Is-Purelib: true Tag: py3-none-any diff --git a/venv/Lib/site-packages/pip-22.2.1.dist-info/entry_points.txt b/venv/Lib/site-packages/pip-25.0.1.dist-info/entry_points.txt similarity index 70% rename from venv/Lib/site-packages/pip-22.2.1.dist-info/entry_points.txt rename to venv/Lib/site-packages/pip-25.0.1.dist-info/entry_points.txt index d3ad2e2..25fcf7e 100644 --- a/venv/Lib/site-packages/pip-22.2.1.dist-info/entry_points.txt +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/entry_points.txt @@ -1,4 +1,3 @@ [console_scripts] pip = pip._internal.cli.main:main pip3 = pip._internal.cli.main:main -pip3.8 = pip._internal.cli.main:main diff --git a/venv/Lib/site-packages/pip-25.0.1.dist-info/top_level.txt b/venv/Lib/site-packages/pip-25.0.1.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/pip-25.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pip/__init__.py b/venv/Lib/site-packages/pip/__init__.py index 2451926..d628f93 100644 --- a/venv/Lib/site-packages/pip/__init__.py +++ b/venv/Lib/site-packages/pip/__init__.py @@ -1,6 +1,6 @@ from typing import List, Optional -__version__ = "22.2.1" +__version__ = "25.0.1" def main(args: Optional[List[str]] = None) -> int: diff --git a/venv/Lib/site-packages/pip/__main__.py b/venv/Lib/site-packages/pip/__main__.py index fe34a7b..5991326 100644 --- a/venv/Lib/site-packages/pip/__main__.py +++ b/venv/Lib/site-packages/pip/__main__.py @@ -1,6 +1,5 @@ import os import sys -import warnings # Remove '' and current working directory from the first entry # of sys.path, if present to avoid using current directory @@ -20,12 +19,6 @@ if __package__ == "": sys.path.insert(0, path) if __name__ == "__main__": - # Work around the error reported in #9540, pending a proper fix. - # Note: It is essential the warning filter is set *before* importing - # pip, as the deprecation happens at import time, not runtime. - warnings.filterwarnings( - "ignore", category=DeprecationWarning, module=".*packaging\\.version" - ) from pip._internal.cli.main import main as _main sys.exit(_main()) diff --git a/venv/Lib/site-packages/pip/__pip-runner__.py b/venv/Lib/site-packages/pip/__pip-runner__.py index 280e99f..c633787 100644 --- a/venv/Lib/site-packages/pip/__pip-runner__.py +++ b/venv/Lib/site-packages/pip/__pip-runner__.py @@ -4,24 +4,38 @@ This file is named as it is, to ensure that this module can't be imported via an import statement. """ -import runpy +# /!\ This version compatibility check section must be Python 2 compatible. /!\ + import sys -import types -from importlib.machinery import ModuleSpec, PathFinder -from os.path import dirname -from typing import Optional, Sequence, Union + +# Copied from pyproject.toml +PYTHON_REQUIRES = (3, 8) + + +def version_str(version): # type: ignore + return ".".join(str(v) for v in version) + + +if sys.version_info[:2] < PYTHON_REQUIRES: + raise SystemExit( + "This version of pip does not support python {} (requires >={}).".format( + version_str(sys.version_info[:2]), version_str(PYTHON_REQUIRES) + ) + ) + +# From here on, we can use Python 3 features, but the syntax must remain +# Python 2 compatible. + +import runpy # noqa: E402 +from importlib.machinery import PathFinder # noqa: E402 +from os.path import dirname # noqa: E402 PIP_SOURCES_ROOT = dirname(dirname(__file__)) class PipImportRedirectingFinder: @classmethod - def find_spec( - self, - fullname: str, - path: Optional[Sequence[Union[bytes, str]]] = None, - target: Optional[types.ModuleType] = None, - ) -> Optional[ModuleSpec]: + def find_spec(self, fullname, path=None, target=None): # type: ignore if fullname != "pip": return None @@ -30,7 +44,6 @@ class PipImportRedirectingFinder: return spec -# TODO https://github.com/pypa/pip/issues/11294 sys.meta_path.insert(0, PipImportRedirectingFinder()) assert __name__ == "__main__", "Cannot run __pip-runner__.py as a non-main module" diff --git a/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-310.pyc index 0cbdfcf055c3ef1eefb199e989bd65e7cb4dc594..44aa3f3f888fbe0093731240dbacf7aac9afe245 100644 GIT binary patch delta 26 gcmaFF@`!~ipO=@50SLZ5p2$_gY^rClvGE}z0A&&f`~Uy| delta 26 gcmaFF@`!~ipO=@50SH9ICvufA8|fKsY<$QF08jk}O#lD@ diff --git a/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-310.pyc b/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-310.pyc index e6e85544f59164cb99a1d636d140a06a8e8b21f5..33cbc69bccbfdc1d5530d54f1398ab4c882f8fa7 100644 GIT binary patch delta 284 zcmXX=!AiqG5S^K9+O;M@iUcbDKtLk+1>U>~B6!GUDefw(X7pOqyNw! z@a}1^p8NrCLMPFInR)YgZ)P@P6J_%>9RbJB*XQk3^p+hyzw)F(V-3|`#|jPJk%kFq zGSEgIZs-Brq+?s5!6Sl+HQkdd4KO$OuS1U>E9!MpgCS3>+|dy$Px*$ZN3-23VGi5W zBrn~jV?KS^XAysQpPdH?QmNV0HcAy3M2Ctj(0m!9<{L#$Kg7K^2=i!H@8HJFx$*h~FAj2s5+vq>1f|%IGnACz9*N&AlV?Rv delta 392 zcmXYrzfJ-{5XNVA_l_0eKtmLaQfP$*h0kDOV@wEz$;ISyVVBFnaYy#>4>lCm7KGM< zD{XuN9>c=y8~6m4x_3Cm&de|0eEV(ahB-;KS_V^%!_VM@EuG`Vo7n^ijKJM?bg|fp zOC*k{fEEZMVa+lak_S*HIbB-l?#YO&UDXLB!w`N4RuFKj>VJ)z4V)dcJzw^X58Z`I3i66$Er|mF^6D6M; z-SeqG82dpO2Y1~EsnRfsJ4Ew=Ka)YC=GvYl;y#ic)GWX4>}isunx^wq^G9E?*jz5Z zuFjlc7|o$dP4^Yrz=EU!GL=6_Bcg zzU(I(m)E$EZs0qZRvz<$TGf-4^50-Y)RzO-$J0286somjl}0Pco`X= zWpCV?Z`WOEoy1weq7}NK#R4uZKZq>Z48uS~R@jQ_fp2YYTf>5{HeG@K%FWH~kutuX znW;wgyROf;P_-~u_|*olA^f?e`Wi=(gQz&cu_89*S_vmhQLR2-XNu@lG8jMC24Om` z(gi5QU+Hi>K?jC(8S>gcEs8z_yP{ClY@0Nm*KR;6eyd#{J#w81KjKEwB6?5_shlpA zLnstM^u(k31oXzM`lWVXVmJ;9YL1g=vL)@p%)Zu#2h z9KJ{06<%Sn_5i6+MQ@ObRz&nPIq82`S6KH}=pzB@K=BvE-rq$kUg6hR9^0ROCC?vywH0yJ!x*z&E=Rn{$y6?(<&<*-_tMWx|(PgJgs190xkVB zIuPxE*_cFP=lE>Kr@I6jKI8!FVD>5i zM+6f_FgquN{2oy9i!*W_2K}Ec&v7ZstogxiFT23r9}~yTypmN`Y8Pikt&Ow`J07}7 zN;REG=>piFEkNLNebDznLPUTL$qkVs)$L{qyp%j#nTZxXo>y2-1f z|9j=KmWO$vr8GUDU1*C-U1!q&>%zRU+SF#~b0l72*}jfTy|+i<55Vy|7n}DmMD_{* WLp int: +def main(args: Optional[List[str]] = None) -> int: """This is preserved for old console scripts that may still be referencing it. diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-310.pyc index d522d809df2915448c4cf9d4bcb704f8aad06620..5d9c05f929107afb7c48fc2c61a6e5678c48ed86 100644 GIT binary patch delta 170 zcmcc3x`358pO=@50SLZ5zLL&3kyn<{WumrZKrTxZ3nN1+%L3Mg42%pZ94RcROsR~i zY?2I;3@NOs>}f11Y$@z5tWg{(%)tzroG(E}XfoYm@yRSMxy9jMP?DLSmzbl;c#9=I zCqLb9EBLPm}W&TS;X>W?p&`6Hugx8AwbnW{TqB05Sv^ Kc$hd?6qo@(IwX|< delta 206 zcmZ3$dYhFupO=@50SH9IucX^fkM$wt#&h10zEU zM+!?SQz~OBha`g}LkepuXBtZiTMBy%YZO-s)5HR4PCre?TP*Q8`RN;{)G|hK1I;aF z0TMiH985(Zo+hK8CigA2lFEY2y!0X_phyujkhrB)kXfJ?pP5&ZT9lWVqgPsznNzHn vnU|HCToPZLnp|3xT2hplS6q-^RC0?MsCKdyQxqS_-2x08OgxMnEDFp3#>X+* diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-310.pyc index 16b127b19d2eff5baeb5604f9ae3a619cebac74c..d35e4dff77e7e12a1ff48cc62df7dd6c69626d84 100644 GIT binary patch delta 4293 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 delta 3623 zcmZt|Yi}G^b?(gU?CjIK_S)<9D}JowY!W*!l9b@233-*0I8|aAx(y8Ly<>aUGqamJ zv#ASfT;xD$(-6Xi541$J5eTJxpwxkW;SYcS38@m&0H6542Lw_jq#^_@=iG7P#OaRi z*>lf1_uPA)_kR2QZ_e(jr&4hVe!2X6b5D*+(qD1%@K1%waTwlHw|DK|uGpFrEk}t& z2~};~iIrmlkJxc1QBDY4vv02qFGua1(^>8m6y5G}^5wk1V|KSwC>I1Cw|ku4a-YBx zcE2-F9uRoa-sTLJ2c4nvkTYB!7POQ-;uOn8XS6&j=4pGoGgclGc$>Y$DV0mk&hkzo znJM-XCDSxx?{apRcLRZ}j++x}q`c>>M6*G2Qd z%LDHK%(`g-W(D)WicP*Em1HEBae8j*W^;(5_ zLDZ`Y4VeSbA4t zCE)(&sgp;pG+4c6R(-)P*~skoycW!aSw_V0R;N2N6l)TqM4dkZ?dYn zMOBbBFjTDRy5fKhtARUsI)IF(%es=5*%RwOihYU5D&bmUewk`CdR_9sTY+w4Yh+3~?g)U73iVahjmXo64>H zlG0LE^M3bgfu`0-t)~T=Y8p-7l-CH6E=yEWha^>6QJ_d5%=;woD=z>8zvp0x(6{jq z6EkP;lBtp!x&>Vk234)qE%&Y*$P;@RbOz}z33T6d8X}|^G=|0pvB^2pH5VJ~*m3^T zOK-GM)xNlafT^ze=3eH!n3DwBF{F$s2@jpkwBPPM`3t}`0ulMEl#wL+LiUcWeGVl3FHk!gQ)3Vvsm2? z6i5vfJd?X;ic?3JiAo~iKF13k zBeW`wdZVO;+H6$mAaGGO3dJufJ65-;ajjxE9}6LrtGS5f`pSB#^Bt1HKu!e_hz6?! z{O?^uJwbH7;#GW~u})Ns0xX9h#fS4d$SD78et@KTE#IpNi+p|~e`aKhMeWsjv$|lg z&F1QTkN+$GGC9Iq-86Ls^npjtq1qAtkM7=sPatK(s#lSG1Ho$uP?%jouw|1Re}5oH z-sKky&n_dsiVXyR1V$PL*1hP$K2UtA1|1ddMVTs8Z7DVAxO4ha#8+0;HOY_Ev<1St zTanc$)v!Kk^py04{w2-VTcj3iX)E$l6u5D!x3tv+jnVj;oR?@~HR-2X%hASunw*EG zy+&q5d0*{;W$7iorL)UoS*oSebU~UET)^9?^mVx)!6vb#n2^Y{Vj=hHIX5B>lEs67 zo;D#B7gFu5_=c1LoQ&WkmIbS$mDpg}z{;|(3MIJ>CGG4RV%{m{Xs5n`#arS~w9D^U zku0*5^m8=dQs0p7$SdSlZYkw=wj#7Uq_k44BrV)jH#%6@zPN)C!yP*bfnnhI@JJ$2d!b=e1mFE(WS?xeI}c8?e`L?e`Hpn%L|n(0&WU`+Odt z8kgZd4L=qB)qkhs{Pw``U|i0?RSWG7M)+lfm>$Ca@;?n6T;7fP#}P~b2%?5T>s7;G z;yPYHI#vlwAT#x8xB*TtR?UWQ)m?_=#5@Gp>6y5R<0-`tx-f z-co3RuxfOxZJz`V`pbJ3fG(*dF2@h^d)qEVkW;;#E%2ei_eUpTB9`7IVXNEXB0PSK zA09e6eh(!dh_heZUl?vIE(kO;2`zyAlK*6=Sg}#$LDziHHGm4q9Ci=v8thTc_dEEb ztGAkm?rP(^hfnT%boIxbD~MKYv*I=z@bbp9tqu=&ip(nD?l%y;hTsVQA^JO?01RO_}4&r8TW zkKr3Sh(TRLxz1X1;mbAR!yDccrwcT|Eq9K8xj51nbihMz!ng+Si8`BrYWA&JizQLT zFn_bym45gdf@|#c;z%ZqTm{y#Ho(|^{=4EJ$?$&``*(?l2tH)RyCmom$}PN~-HJT{ zSzdu#y&~>J-Wq*5tgt&M--AGu30`Lm6PlszALp__pLFW9X`9EuZSZsfph~);!?PK` er1**?DGLl>4xZFW7%Jd#Ijy7<>5R0TJO6)XuSP`x diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-310.pyc index 77b2d5214638b9ab170fbfd639e7a139e6c7d83e..bf346a37e99711e52931d7bd2821cf2855fa08b9 100644 GIT binary patch delta 4094 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 X?lCg25d;eEBP&f19O9rjnYR7|zl@$* delta 1307 zcmZ9MUrbwd6vyxR-P=;ya#tJZKf3a-S_%b$OpK5S>li}jkm$0hi))y-?ZB>uUt4h4 z$~Kbu=f#B+eOm%Nn8iO2ri;@jjqynyd?8b>#;6Y_JQ#ggVxkc|=fYg#P41`X_x+vU z`Tg!W=hvO*Z=cZ%4Gm6(o<{$6_PZk=>3?bi57E$oin0i@!4T_8McIHVl%N8uaFz6R zVSu4-h-Z|zHf2KZ@_BsBcDnhMYOHlOUo53(jFBCn7;)9KXA1J-ObIt_6J9q-4iLgF z#6J$r4Kjhdwms;@UHjF;Jv1qM84nXowRov$+UI3DGyAga!y9$qz(}p^_*;X1Txhrv zImVvR|L`DN#|dRN#xbEM!ZObGezc1-^QI=#^HLsVF^Nlh(tcomrZ>X`ey@KEM{BnZ zwE!e*+a8yIMC~WL#zwp<<`;f%7U=RF&p9jB&F}xn~!_T#wp^u?+h=YU} zyn|V1q!;t$Tuv5PT4bDMB=K5!fL4AQ?u6g)m+&OniNkkVmUxjTmFJ@7W|z}O>ZSCh zV%)xe!ZB=%#B3Gv(P}3n^-yQp(oz;Ao^5Hr_eHBMGI))*_+Rm^kfx*Fy5+Hs*vu}x zn_R`6)?VnS1=>CY+bSt>{HlEidhk}qFs$Jp9Rb^QQXj>J=+i4}WL;58ly0j>#fGR- z*BYV>vazJjX%)yqMx3Uk=j}YsD*K}nMXm}`>=lc_1Dy(2=T-^>6)5ymRL6RK1vbE~ zRMm%n6lnx33a9eZkOeDaCZ_~etv zr{Zp_B=T+g1XInXOY(lLMo5zZhSjsyHF<-FenyaR&?Kho#X>$an@weAb7}c1O_=`T zg+e)Jq;iEB10At&Y?;(ipbq6W5SMj_13ciSTj^CDst($orh0`>#S^g=s`^%}6VBn? z*lp^m4?6qdJpS1E7F01GABK5+FTM$7JlQozH|UeDL9&1EYLC87fhD(r{+E*phLzq?wxZbA)rgUv G6aNAQYb_%H diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-310.pyc index 8ce47258c66189604b910116a4887fd4321dc29c..5b3ecb62d733c7391cba41757d9fef42bb6d73ac 100644 GIT binary patch delta 12680 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 ZfveJ8?Do1!T@|i&R{=h)`0gmP{4d#*fqwu1 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-310.pyc index f5176d38ad63e7129fe21e08384f386155cc7a91..cfb0a67814d66d3ec863d267f306a30be6412992 100644 GIT binary patch delta 19 Zcmcb@a)pH}pO=@50SLZ5-pJ*}1OPN~1ug&p delta 19 Zcmcb@a)pH}pO=@50SH9IH*$F~0RSs01AqVk diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-310.pyc index 02a0d52d45c2d8eb26b2516624445cd89fea17ed..d0af0c82831ce286c60c77273a8d781ba687599e 100644 GIT binary patch delta 1120 zcmYjP&u<(x6t+E{-TC2}{gK^dH`%5MkitT>iBu>#KtSbyK-_vkbLeV|z00JYnZ=%6 z)UZ(mDJO(VWdR2e6fPX7xPZhz!Lg?~QT2c-apu+*dm=>{$)Df*{Jl4R@A<3Vcjv+^ z2t1&_{~q3-%zJmj-qGLMqkuvVB3SMyLgj8nmfjJ^i5=O{Xe?eys!=s@A}4Vp7XoJO zdlcWW#f37$kNmWvEt``hi2O39!o#E%)k?d{>q#SOB+aOqEJaHtH*t6?X-94CxU5P& zwminvr{ornR%pOFn(1gJq&3ZSnN8~xKpQ{9V-&5@CUe57h7qwp%|ckcXq@jQBD>0%%G8v3xX^DN=9Hk$9G^AV4!+J)Dav|pRBd??sQvskc% zrMdbB{sLQS54{gp)VJu;TXmhFz&w_DVU0NNLlJ65v`(RI1hru-hekBa#zUElWlc(? zp$A1*1(v9c8=xA->%%S)p z4;B`!e+hM@Lu*}d=;qrLTG&j8 zOo&aRdDg%)2F}b+y+=9~b0Tl4eR8=)Fd`5=B?vtxRg5uo5LWld?n|TsLnPkN%6_j1 z<7AqNTwiuD%VREHFNI5+=Sp3i=1im`Uj9K2rlSvTj3#k9DSJ`i>$>G94QiO^bpxh1-o7{)u@*=}j4-A`CPmKD?$mzah4$pJXX!RS#AYDw5E&MXwCv`)Ji$fAjQ zF&@Os#Y7X41Dcq4@oK#3!DzgA>cKz2#IqiqDG_bb-^@JoJk$4W`*e7_V*8e5DB>!W zzb)?$J+>=%-iZ}fFrbP9l2LV3F{(7>K?ef4m!fG;b2KmGWIWx`6AjWH&v1-no~EXU z9OPM!m8>;tds!#z<(!LL zO=)WS?PeIUoDf4*paNK#&!yOz{)0dgO;Sa#b%Qj6jez;9jp@17MGTNRMV-K_$v>eB?jV7tHV2+Cuy3w=>#v zIJ8*^Nz@4<->2d1%<0L-RAVwu-&!Gr@?S>HtjadWB&vMOoB-qeig|u?KnjBbvF3(t zmlD<^7tjyL8q>s-zcPB{CAj0`)9AEayigj!M*c4NZY6Uqtn@6oe4ys>Xk#sbiK7Y?Vz5N4-C`T`%xiMBSxECvqt} zDNmEt^95_%HUl?kG}p-*_8HUoo^@PH>eKmGtBPey`<2T^Vz?yU(SAEwxl@slg(T1V kuf%`$Fe_s8r`C+j_9)38r-tHw5m1xH6@%!up zLe{)~f509Pa@HI4OLj@fx;NyP?Xr+_-a&uZ9u~6URs0cqM95vlB;>qj`iJeq zLN0hm{4sk>$VG45pRgx{+}-w$`p4{J{-ixA6g{5hAGeSDQ}&cUZBGkbuQ%h*+Oz%% z`-DGd&k>19jd|Kf58NmA0#kQSvQvA+K27`C89Knu)Kof1OYf`pA{`PMsUd-`Ob>$Y zrK=Jhrj_?4TG^59v#f1^VuX%@VsuB|A@(_XNDO)zhM4p)3^`AaurWHuGK~u`eK$K( zmTDRurxReiNRP6!^cXBiqLZwbTCA`tJ@JvtlJGwV{suixr@;S}XXm1%rWNTlodLtE zl-!i8+2nJwsAq389@WDjnU!hsK>qa&C9N#I7c(BXp11j?8@Q{CE(Q1MJPdpm#OYA= zE~~CNY~RQ6J5H&=f~d)vL+kvXS=fAwq$+hcql7E(mMfr0b8BqVS=o$Pl&XR2vj-BN zNFFI(dlIaX2B4E7Q3*eW-r0H-Qa5H*0&h=$D5K+Lc%puQ7}BvzTGFme36=NcJ&aA+ z`sL*?xW{;Gx`BD^=38bh5)VaBN+nkKKTla7Z+rp9N#@%}Lu33-FAcWbQ>+2zp88ufn&CsKa zo3I88q`)IK=|=K))|!oB zi=b|yPIt(*+#)S`NZM9fN-VFbd>ji>*p;#b+ovXf%-&kH6h4oinFdHR&hpaIH!ZdE zF0?X@q8KfAyl;Yc+`VZ(^`a2?hGb=~7a?v;rHGGTPCm&U zJ>A0>P&0sV65$j;nuSioHsWPe;g~eHUtfGNIc$`!9YPaE&BqbW0$5rniMTr)Gnr;Y zF{Ek?U7eEJ|79;?@tx%RMnBP#pBl@{7jcZf&ck(Ru+7e5kK<(6n0yK0TL@p(hmf#Z z`3%4!JW(D%m->j@+e3zw$^kx;Tt{oq@Cx> zIh?2qAnn2~0RrM{&2|1Zs^3Atvj?(x9$m69(5d<~)u2P`)vqge4lV3BA0)3AzG2_M z@i!4}A$%LB=yn`8fYEM@o$NSVEZ{q6|GE&D!LS2Qqyrd|F6*RE=F7kRte_E6O#V|G z8+5<|jrA6spRgG1zI;=B z)XHAp8onMv#rR>&M72Cg1@L(@pvk{_7s;LENZ)vMzfP>2DArW-!qrvA(+p)R%~esm zX<^;v5p$l*!6{@R&96W$?yGQ{MSZ}Ybn=A?ju0ge`fhhUn_uI=X#Xc*ijcvLtWGqd z6N9M9nFFKk7U-%nz|$XYKh~Jw&ksO|p`dnwlwb?wmK+%rqTb5H@(z&8vJ@CVCCVn; zmO6xk)(uE~oN1AUMwR;{&Ni~UI$*A0>;d;Sy5jt9AqGN%ZJI%LQ<03R+$8+9xVzCq zGw`O-Y@Ja3K5!aNiI0^_)c#M~cVJD|;TXW91UUJ{@IkvJPrxCMoplTD0U00`?pnRP z2qx|#3?Y;dFnqxaVmgjYk}5&Ck?P3pTVcRbr5RUwh=yFP8B~wQVdzEB+AfdluE#~q z#%RuNxIBR485Y&4|K!tw@#l7;FgSemAK)4x9p$qsTsLIci9GCx{8&~DaRE`qoAyZ8 zhlu)^{|H>IOJZgG2Ox73VKE5@O-<18E6Gm=Z)@1^{9f|e;3&x@U8NCXBvxsdbR|or zF_KT}rO8SGT+%_Hq**v*JGZP^pT#a5-EQ)y(!bjxEy(9-4x^{ci(P(2yu%sxhA31n zNDAW>^(Ssi;*{)U5eqX_S0F{5vej<8UXw+gEQw@eJkPYhC{#>Gsu$1uA#Hl>BHpv2 zS~6cYuaUf*hx~N@J)~dlCwa|~`;>mIn3Lb=A$>!#Aw%{claDpo_)@OOvizm0$p4j9 Q`B5<=f1zo{=anP>13)9!-2eap delta 2830 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 delta 3665 zcmZ`*O>i4Y6`mfA#-oue|0%ZR$dZ!yCvqG)&VRCYHn#J#+5ABqc8kgGim|$_Ogtlr zo>7d0f?&P7oG1v*Ws6ExvQjnu(Na!7#dB} zq4zXvj_zh-G{a`;FgqiA44S1m=$V&2ZEl|K0c1fUZC-13S*LsHK7h|{660((t$^VX zItu7{iH@-p7(ENzak?MS3$(yGHWx5K4*+se@+NUvR0ZBaS_JepiB17}2$nVtE}Ts( z^zi2Y5jNWbBXI=xNj5} z|FY=^*{jQ43Hl110s0lHE-Hmt@v(ZYTMr|1)wR%AuwB<)a@j^Ca*j+!LX%bf24^Me z@Gy4U_HUP#9hZf@j$c~6&6rzqs(t`t7~LpoXNZx9aDSrkQSp-~yDnj@^SbJ zBbo!_UJHGzRk)jr6s3o^R*J#sjV_vjsSP-gSrO41^D?Nhzt7J%ln$jqmIYQ zqS93E7<@mCfTlK;b>bfj)JGAj0j@n(G4d9bAhxdfa}tlfh~ub&E`(lh-CI~(aq4xa zTFFbF@=FcJrTOI=&yV_(dD>w4pq7_wbeNxCV#uV9kNec7IYIH>^{@DdyR2fD*Ye{& z3mWxeeJ#JaLF3!@fL3Ptx?NteD=a_0n#O$`&pUp;S_`)5j1~)~h<3c)3eASkN_AF0 zHhqE*!7dacd_Vm00*VO~quT;^JnSs_w`&cTmZTp=fczN{x~{1@(cr71e5Prd3P@BV zx@xGpsu2TzTYb=0L04PaQ!T2g{3uu`6A)V;)T8i|2a^OPfb*avAXNPx?rr4S%_r*T zi!8KFgb6t1ReQ}Z1-!uur0vQM2eL1$U!;vbS_bp&K#K4apqDYIwmzu8WFgJZ7jl6g z0}f1vPQXIs_U+s`v1W|+I6&}q5UQpV{W(9m@x=HJNlyd94}l0Z*Qu_AI)wk-vd?p3 z!MtW*XcsiTUwmk0vO8SaK8vyqq0Ysh&2h3I{%wBRzZcELB#ha`PvIO3;j8xkmUUG)PMSbBK75@(?l2 zFlD9->b0A464i4->^!F3_p^r~?u*a)&%t*U7si zFoIZ zw0KVsx|%xJ=y+49c56z|z4i`K@OufeU;nZ4P`z&i$)#84sIUSZ7eGH3xmr$rE_$zc=3zd5(#KX=)@|%13{mFa<@)9-i$IcmYT*Q+H(%9Tg z*+MTjaFeD`^opy=!BQuvp$-Mavjg6Zco!lOKj2}5-x;+-y)DG;@7K|sy z<0$a$5Sk9u3n;NrGYYYGGC*=lqsjMy(Ol8-ctBbhIy8U3D+Pn%?kxz-cJ!5a7C60T;(a9}$-a_DQ6z`xYp}>R- z4VwqfvRw{B!uVx`cLcuKu5jq+@5R4*=167Zbnnjz`I`89UyDqM<bj-Yl&%mNV<+B?M}_9@-(Wtf4dPlZm4-R*tw$k^{%NAnc~v(olXbLtIL9LS(yD(>1DL| zMZY-(>@#tr|9wKmU;6Kpl6YgFaceg+ae;F0c@Z_~T?RF|13qYBl;Htw-6FW%p;>mB zT`k$X;_sX*fc|MQHaJRxjVps?bplO3QA4$O=%uwgHdA3$_Ki9}b5nde#3$s^TQG)y z8^sqr3C$VT@q=>BtDjjFjopiHzPC;Ke`EOjKxsnJ;vawl$tO=tdRxQ611O~5SnzlS z#k9y}7UDgqW>K6HUM4>>32La@^*XE4g2}&yJy>;L3`X(G%;=;%tnml{{e6dSA{*CF)<=Sl`~!!-yO~+I9@Ki1Hs+mPs9D<<6&KwNPIsxp<@t+StKU>#!{Wv%FOq9M*KCmmkh&*wBF#Z&$D7rexQ{@atto7D`1oH z&?uFvw#Q1P&FX=1fv-*T(#31nZ=7G4gW9qWCzN+*|Ga!P&b1$nU*e29WjkPDd>)@~ zH<;gW1O8>C;{`46e))LdC$R}P-W!U%6XkU#t6V!+FuOR0J;!5w;h1IYjsX@LGqAl4 zmz}}8)Bgm7rWg^dq6W!}f9BKkDOpXiqC!nolkiQE-Uz(2i27Vr)n{r%eX45af7D}b d#C!%Xu?tV?pid%bb{1;5sULpVh diff --git a/venv/Lib/site-packages/pip/_internal/build_env.py b/venv/Lib/site-packages/pip/_internal/build_env.py index 6d4f6a5..e8d1aca 100644 --- a/venv/Lib/site-packages/pip/_internal/build_env.py +++ b/venv/Lib/site-packages/pip/_internal/build_env.py @@ -4,21 +4,21 @@ import logging import os import pathlib +import site import sys import textwrap from collections import OrderedDict -from sysconfig import get_paths from types import TracebackType -from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type +from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union -from pip._vendor.certifi import where -from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.version import Version from pip import __file__ as pip_location from pip._internal.cli.spinners import open_spinner -from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib +from pip._internal.locations import get_platlib, get_purelib, get_scheme from pip._internal.metadata import get_default_environment, get_environment +from pip._internal.utils.logging import VERBOSE +from pip._internal.utils.packaging import get_requirement from pip._internal.utils.subprocess import call_subprocess from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds @@ -28,18 +28,20 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +def _dedup(a: str, b: str) -> Union[Tuple[str], Tuple[str, str]]: + return (a, b) if a != b else (a,) + + class _Prefix: def __init__(self, path: str) -> None: self.path = path self.setup = False - self.bin_dir = get_paths( - "nt" if os.name == "nt" else "posix_prefix", - vars={"base": path, "platbase": path}, - )["scripts"] - self.lib_dirs = get_prefixed_libs(path) + scheme = get_scheme("", prefix=path) + self.bin_dir = scheme.scripts + self.lib_dirs = _dedup(scheme.purelib, scheme.platlib) -def _get_runnable_pip() -> str: +def get_runnable_pip() -> str: """Get a file to pass to a Python executable, to run the currently-running pip. This is used to run a pip subprocess, for installing requirements into the build @@ -55,6 +57,26 @@ def _get_runnable_pip() -> str: return os.fsdecode(source / "__pip-runner__.py") +def _get_system_sitepackages() -> Set[str]: + """Get system site packages + + Usually from site.getsitepackages, + but fallback on `get_purelib()/get_platlib()` if unavailable + (e.g. in a virtualenv created by virtualenv<20) + + Returns normalized set of strings. + """ + if hasattr(site, "getsitepackages"): + system_sites = site.getsitepackages() + else: + # virtualenv < 20 overwrites site.py without getsitepackages + # fallback on get_purelib/get_platlib. + # this is known to miss things, but shouldn't in the cases + # where getsitepackages() has been removed (inside a virtualenv) + system_sites = [get_purelib(), get_platlib()] + return {os.path.normcase(path) for path in system_sites} + + class BuildEnvironment: """Creates and manages an isolated environment to install build deps""" @@ -75,9 +97,8 @@ class BuildEnvironment: # Customize site to: # - ensure .pth files are honored # - prevent access to system site packages - system_sites = { - os.path.normcase(site) for site in (get_purelib(), get_platlib()) - } + system_sites = _get_system_sitepackages() + self._site_dir = os.path.join(temp_dir.path, "site") if not os.path.exists(self._site_dir): os.mkdir(self._site_dir) @@ -162,7 +183,7 @@ class BuildEnvironment: else get_default_environment() ) for req_str in reqs: - req = Requirement(req_str) + req = get_requirement(req_str) # We're explicitly evaluating with an empty extra value, since build # environments are not provided any mechanism to select specific extras. if req.marker is not None and not req.marker.evaluate({"extra": ""}): @@ -194,7 +215,7 @@ class BuildEnvironment: if not requirements: return self._install_requirements( - _get_runnable_pip(), + get_runnable_pip(), finder, requirements, prefix, @@ -219,8 +240,15 @@ class BuildEnvironment: "--prefix", prefix.path, "--no-warn-script-location", + "--disable-pip-version-check", + # The prefix specified two lines above, thus + # target from config file or env var should be ignored + "--target", + "", ] if logger.getEffectiveLevel() <= logging.DEBUG: + args.append("-vv") + elif logger.getEffectiveLevel() <= VERBOSE: args.append("-v") for format_control in ("no_binary", "only_binary"): formats = getattr(finder.format_control, format_control) @@ -241,21 +269,25 @@ class BuildEnvironment: for link in finder.find_links: args.extend(["--find-links", link]) + if finder.proxy: + args.extend(["--proxy", finder.proxy]) for host in finder.trusted_hosts: args.extend(["--trusted-host", host]) + if finder.custom_cert: + args.extend(["--cert", finder.custom_cert]) + if finder.client_cert: + args.extend(["--client-cert", finder.client_cert]) if finder.allow_all_prereleases: args.append("--pre") if finder.prefer_binary: args.append("--prefer-binary") args.append("--") args.extend(requirements) - extra_environ = {"_PIP_STANDALONE_CERT": where()} with open_spinner(f"Installing {kind}") as spinner: call_subprocess( args, command_desc=f"pip subprocess to install {kind}", spinner=spinner, - extra_environ=extra_environ, ) diff --git a/venv/Lib/site-packages/pip/_internal/cache.py b/venv/Lib/site-packages/pip/_internal/cache.py index e51edd5..6b45126 100644 --- a/venv/Lib/site-packages/pip/_internal/cache.py +++ b/venv/Lib/site-packages/pip/_internal/cache.py @@ -6,14 +6,13 @@ import json import logging import os from pathlib import Path -from typing import Any, Dict, List, Optional, Set +from typing import Any, Dict, List, Optional from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version from pip._vendor.packaging.utils import canonicalize_name from pip._internal.exceptions import InvalidWheelFilename from pip._internal.models.direct_url import DirectUrl -from pip._internal.models.format_control import FormatControl from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds @@ -33,31 +32,19 @@ def _hash_dict(d: Dict[str, str]) -> str: class Cache: """An abstract class - provides cache directories for data from links - :param cache_dir: The root of the cache. - :param format_control: An object of FormatControl class to limit - binaries being read from the cache. - :param allowed_formats: which formats of files the cache should store. - ('binary' and 'source' are the only allowed values) """ - def __init__( - self, cache_dir: str, format_control: FormatControl, allowed_formats: Set[str] - ) -> None: + def __init__(self, cache_dir: str) -> None: super().__init__() assert not cache_dir or os.path.isabs(cache_dir) self.cache_dir = cache_dir or None - self.format_control = format_control - self.allowed_formats = allowed_formats - - _valid_formats = {"source", "binary"} - assert self.allowed_formats.union(_valid_formats) == _valid_formats def _get_cache_path_parts(self, link: Link) -> List[str]: """Get parts of part that must be os.path.joined with cache_dir""" # We want to generate an url to use as our cache key, we don't want to - # just re-use the URL because it might have other items in the fragment + # just reuse the URL because it might have other items in the fragment # and we don't care about those. key_parts = {"url": link.url_without_fragment} if link.hash_name is not None and link.hash is not None: @@ -91,16 +78,10 @@ class Cache: if can_not_cache: return [] - formats = self.format_control.get_allowed_formats(canonical_package_name) - if not self.allowed_formats.intersection(formats): - return [] - - candidates = [] path = self.get_path_for_link(link) if os.path.isdir(path): - for candidate in os.listdir(path): - candidates.append((candidate, path)) - return candidates + return [(candidate, path) for candidate in os.listdir(path)] + return [] def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached items in for link.""" @@ -121,8 +102,8 @@ class Cache: class SimpleWheelCache(Cache): """A cache of wheels for future installs.""" - def __init__(self, cache_dir: str, format_control: FormatControl) -> None: - super().__init__(cache_dir, format_control, {"binary"}) + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached wheels for link @@ -191,13 +172,13 @@ class SimpleWheelCache(Cache): class EphemWheelCache(SimpleWheelCache): """A SimpleWheelCache that creates it's own temporary cache directory""" - def __init__(self, format_control: FormatControl) -> None: + def __init__(self) -> None: self._temp_dir = TempDirectory( kind=tempdir_kinds.EPHEM_WHEEL_CACHE, globally_managed=True, ) - super().__init__(self._temp_dir.path, format_control) + super().__init__(self._temp_dir.path) class CacheEntry: @@ -211,7 +192,17 @@ class CacheEntry: self.origin: Optional[DirectUrl] = None origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME if origin_direct_url_path.exists(): - self.origin = DirectUrl.from_json(origin_direct_url_path.read_text()) + try: + self.origin = DirectUrl.from_json( + origin_direct_url_path.read_text(encoding="utf-8") + ) + except Exception as e: + logger.warning( + "Ignoring invalid cache entry origin file %s for %s (%s)", + origin_direct_url_path, + link.filename, + e, + ) class WheelCache(Cache): @@ -221,10 +212,10 @@ class WheelCache(Cache): when a certain link is not found in the simple wheel cache first. """ - def __init__(self, cache_dir: str, format_control: FormatControl) -> None: - super().__init__(cache_dir, format_control, {"binary"}) - self._wheel_cache = SimpleWheelCache(cache_dir, format_control) - self._ephem_cache = EphemWheelCache(format_control) + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) + self._wheel_cache = SimpleWheelCache(cache_dir) + self._ephem_cache = EphemWheelCache() def get_path_for_link(self, link: Link) -> str: return self._wheel_cache.get_path_for_link(link) @@ -274,16 +265,26 @@ class WheelCache(Cache): @staticmethod def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None: origin_path = Path(cache_dir) / ORIGIN_JSON_NAME - if origin_path.is_file(): - origin = DirectUrl.from_json(origin_path.read_text()) - # TODO: use DirectUrl.equivalent when https://github.com/pypa/pip/pull/10564 - # is merged. - if origin.url != download_info.url: + if origin_path.exists(): + try: + origin = DirectUrl.from_json(origin_path.read_text(encoding="utf-8")) + except Exception as e: logger.warning( - "Origin URL %s in cache entry %s does not match download URL %s. " - "This is likely a pip bug or a cache corruption issue.", - origin.url, - cache_dir, - download_info.url, + "Could not read origin file %s in cache entry (%s). " + "Will attempt to overwrite it.", + origin_path, + e, ) + else: + # TODO: use DirectUrl.equivalent when + # https://github.com/pypa/pip/pull/10564 is merged. + if origin.url != download_info.url: + logger.warning( + "Origin URL %s in cache entry %s does not match download URL " + "%s. This is likely a pip bug or a cache corruption issue. " + "Will overwrite it with the new value.", + origin.url, + cache_dir, + download_info.url, + ) origin_path.write_text(download_info.to_json(), encoding="utf-8") diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-310.pyc index 9d80e46dbdb21c92414359afabec1de6b0c6ad33..a509729265735542aee860362f5f2e2928b60f78 100644 GIT binary patch delta 18 Ycmey(_?wX{pO=@50SLZ5p2+nP05n(y`v3p{ delta 18 Ycmey(_?wX{pO=@50SH9ICvtrR04%-)O#lD@ diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc index 80d092c8b596476dcf5e427bd14a3d3ccd9ac583..b56a39dcc794b3433921cbdcd8ce090fe8f03156 100644 GIT binary patch delta 1656 zcmZuw>uVfU6u;-rGqca^Ce3crw9!7dB~~a@w6#TBrM5KDHndtAmo;~j?xxvI?o3l# z?hs+sY(5mKS4B`^7at%9Ra)?`s1N9;`6A+{B7PMSG@dgXO+Prp{O-Bu-1GXKJ71LU z?n^aODUadv`!DzBe*7kN7t(p$x%e6Q`G4r|VQ{6xh0z6>4_F;gHoM>t3Vx2!UKmBz zF}h4xg1^O!Yz+c4)|*Avf{@*C+n~@|U}$3(SR-Mwz`FhvFnWc(#$I6!xW)pz#X<<2 zz(p@U$3jE!&}_pAHofA7ma-IIX7a4ELKDzo>7+6RzY4cN?nTL&=du#?bv$8p0a%-L z62k35k~QmS?OSG{t!(*jki;YoT2o!N##dpL&vN03#G9^i>S>V_shgM(3viVy-&HOq zx5K`bAfx(P7Rbv)JmdZl?P3=c zqn&N4zYAgR-?3qw3o3`qnu|f%4~;OKJE%Xjr{J9a&AteG^hxJYn9}o31xos!GYaSRug>L> z3VCsa0Vb*12PEI%;80&6(!H;+1Mp&7j8r7{N14%<_KXr9DaTz+LBW3|l$KaeRP- z4d!3A<3So+e8;#8Nu5ZJWiL|HIMXSTUcPfUncxElNX{Wl{0Rr-PTB#oQP47d1a|A& z=~1|;@1;*oK0~Hw5h4TUB6pGGEL4Naaz#c)rE$GvJsh1*Q!^1XdmL^O`5da1p3Uq^ zkkn&f>dpt5&p8~_M{H+u@YQH{%2;Yz8{%q%af<&3?7J_D>Xk5H7Q@9on7-ONo3W0)Ro+gVst9Me`j2M zACX_CGrb}NC5i9hQIy`(m-6E~NWy!Yz-6K|6glOxXwH<&GG;6;?MeMrUJu3tC{ut# b1ab36_0+(z{DKX99cQ;rtIfT?w-x>YH6w$x delta 1499 zcmZWoO>7%Q6rMM`_O92z@lRqWO~^0BX(Ldjs%ju0l&BF@O-OSHfdu1voFAvLlkt+! zYL-NDP@F?W#0aDcq1p$Kazw4fg%dXmYD7O>m9Ok#bNcwtnk85Op*E0huRd*e15GMjWvHwt>6oGI2CU9lZ_{ zWYKbb!YAk!;S<8==z#H?qXPLpfWsZ&ooE_sl+W5`Bf#_~0I8FP#mpvzNM!+616#!L z3qRkpgGgfFYN$yL=sxVzCCV%o+%tty3bPOk-$6nwz!WCm6DE@Toq!z?ff{Dr{P6z_ zJ4kT{DI#msv4q8&cC=1dv_`$HLEIYjwtjZ9)s6`rDMBJtYAeMtF5`qnxRkJyrPP|n zzel?rpNZ7i7~P8{EQh8zM{w5-r3C}$@gN=RQOC)SuuS7QuMeGGA8Ykd0JTeFX2nvabRWdF1;NF33s$syu7F4O4R0cn1dM zuSP#i%O^%2o|o^N-7q6RGFQ45)K5YYl7y>t50!nJj*Rd=34tOk$>qS+OD~|44=5N` z(52vvf^LMWGKLVcy)La(U87juTIH28@0WiDeh&Nd8ym$kbA9DJUzXol!<3K6zpNfB z<@yTS70&p}G99dkwaSL=8VI?n&E>t|WL)RxRO*a^P6cP><6xKXb2Kg47n&K0K^*9A zrxu4e#S19-L4T|p7DT|ryO)|^$-AN6*!;6ZlggUA|3fH9ljoHkN0@p9FY-S11*kgx zY4jBskYmwqsLOYwZ%&V?l~)m54Qu25$}-lAc77|*T`ga}mG!l%Y$aFGGb#outyZ1% zYaHF%^6%(SP+2W~v-byMU(w4iDMv4YYnCf~y^yaKdAstdz8`^WF0I}ymhhP^?y6{d#WtD!+lju5ojR(04uH>xPb)Xv`DD62+$%lai&)?pEckP{tx6&ipO(F=UpbI83MVsh^f5rY+(xtbq z4|gS7a-w>appb0GoVXr$5_-Z(>Pb$E*s7D#Qyf z2c5j0cM5ue&l7ghDd{Drte2gNUU7!>Ax=-)!_J64(sf4lQD;mabH?>?N7FTDLZ9FQ zsy*o((T{LEWgm5>^eK*~?P=$je#|+pALsJ{d&W7TpKwmMKj+NqRgPx?Kc$~? zPV1-nJZH~2XY@0G53UjYEG2uR&(m}JME}G!!OWY34}d{)yORD%Q(P8i3PFdwI4y

N7$x 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 XL+~d#QYN#Cn#_TOEu>0HEE4HIHNiew diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc index dc27bd06c537129484304a05e978cf3a2d35a6f1..9f60568f37e879a29d91ab01368786b693511590 100644 GIT binary patch delta 7654 zcmZ`-34D~*wV(UVlF4KtLLeJ~k3ExQA_PbvB!Q3xg%Fk?%dm`-IXB6`WG3915HcnX z2vtz1+WTyah$3PwZPiMwT7539`fO`!?R(az(^^}XYTIYk=k`Q_cg~$J%fy=b-NRk} z=iGD8IrrT2@z+P#Umj*9p^OZN3I9HQ^QDf{JtoteG#LGtkAr2{!iOFxDPggj7}P;N z&wv761`|MQx4~p6JZN=a3YTyPOyMOk725<}(ryPGrX94n=l+Y8=`aIV=B+TnOqg}h z1hcr~fZ1KnQ&7fim;*)lb3*Y^n|nUL1WLH0UCT4^1rRH(HYtz`%HUGSgSjvdK?{>W zWd^1k<}1tsg{erw%r`I#p#mxuY7wGR+?7eF#RjShmLR4YiepEu?nOzEB?hDhYGElX zJ8E$+PFk-u*6Uz7)I$R>XjB_jC86pKR1>UF%3P*YUXp}aftVN>=yF&Is}R<#3{;&2 zT4e}Y4K1)nZMRl!SCfQVW1!Z-dT8x1!G==|u7HiO2`x~Ygj}zX<**sHfE%{PU>p9n z!;YhN_tGTbRzsu*u2d)RsuL_r!dz)!+Q5gK0&dEo9Xil~bxAm%f$Ic6?1WtqfG)%= zM@(!a6#ND#2qEZ(-5?aGK1oo>z=RA)p8dl*597PpYsxbd1+^DR1ld|S29vgibZX9O08NP)q&Bhrd{2Pu|8>3s` z+c;`5M&E(&;%JRAItI7mXsx=S$BnC-#naWrcED|L0$0~5TigzJz)83>2B+|(ck#jl zCOFO4!QJq^qv`JTNhi4n)%reW2+9W&cot@eGw=fx)cQ5s{1ASGs~f&%^ zj@=JG#^FX|_yC;6(I#c8L3j{;0uP}p9)?HI5u1~gdJvULB&KYh&9^{_N+_77@=Vlg zx4=)~QIzHW8Z{n+f5+9WF}2m>@C5!&^Q{=28qb6$4={M@XsUZ#(w0vczW*8g9Df=- zjb698w7T^3N&dcO;>nMdg3N)6gw34K@8G{0epPs5Cr*&%l}I;nz5G zrD2udzzaC?D!=^}UgVSEE_B-O;6KqSZApS(M8Tue_K5HQ3tmDQK6TvR!;5%WAG{3z z9m5kql89G~6TAv>_=AeoKdOYolTfc2s6WB$i1{-nE~~pe3Gupt_zS!NZ^B#fwu<`?z+R z`_Z+j@B!LvmscDsW1DmE z1>~d8zl8H>)nF3l3j=cjE+QfyUtJS6b~I*lhmwF76F^+l$RhZ!8Jh*o+dUeGbJk&` z%|NCY$lYU*_F-fyA{+)fjVu*&i!orwFgP8-8Q3z7Hm*a%UKX}X@OMwDzG6+p zkH`z1i62U@Jlu`^JcJ z4y#yL5UQ2jf@eP;WlA1^Be| zj}f$Rc+(0*RAL+AU4;F`%28DY@4y&dEO2n8n$PD8c}0v@^2NN0SMwUalrQ6Td^xY@ z4ZM-B=1qJBZ{xrPU&5ojpAU3UIM&>zxv%Eqc?rG*s)oZktcj2=<(Ko7d=+o*Ad3<% zHU_s0&91eYik35z$y<-aF}OSJnAO%Kim)P;TeFK;L>|m;DJ<_d?R10}^lPF5duicC zkyJ1rVAtSHXf+MKo&9UZ+U40v>k9Rd(0juEV23`( z;+gFs(dCVJe4$`OgaUF^PC;P`LOlqLJ0f1u!6P2<3#V0SAxdR5$IoizTRF2cvzUfI z%SFqDbSA1~Zti098P*~<=IXX3sIjP)H&;%OH|9>rXs41|LxRBN^4{Fyv>F0r5~)+D zPjU+~b`GKJOw`K{XJ^ZKd8_l5;%q#<+w0rq?ckoEw~LEL;#(@elefxNPu=D6$vHXs zq5=CsY+XA;ahr7AY-|puyA_Dd37944rQxob;&3LB4^92W4j?*01LczE>)ZQL9 z3vaKu5|^UQ@<`#Ld8Il|Y}bp7vsdY%pc7q765^IfUpJ4Z_&P&=9}kOGoD667ei!#xpeIw8Smmo=7Ne z2Y=Yx7T^%K`MbJ9A`*9md)g3&n}&s-biJoBNCgm?^_`Pby z*g=m4{B6Q3`gDIgMmra1;qIP@?hor|=1?z(GQCw7}eMqrVJ)u~sKBCz6vQb8xWth+Dw4mu`qn&`Pk+2vYAO+njLVNq-*2F*Na74&c zQ<}4stCZ;s^In+p)eaooN7zR;q+k|G1cksECMpCM#&hZ;*gA4X@`+rTu0-ZR33S)D3u+S z8AZgtps3S!WC)rge>>ZndJDmi;+%Yc_9U4Azf)9X8z9)X5s=KM>;E zM5^Vql9}V4z>UHd9H+BvCT^7*O8(&-@!H7gl|fGsAB92O92P!tOm>#8$%&_64);bP zLd6*7i(`b!S84aP((H`i(+(;*YvQE*vum=bx#n9R#W23iHl4n?m>b#L5Z0`6N=2F9_{>rykTx3y9>9P zJVX2dC!8rQ(F~U>6b$sa+WbLGCJA0cg?Hy}U^{+DxUcMVhGhPT$e4ZTm>ODD+)Ilz ziaIbWVBV(}S6qq{ar^LaK;ByZH2cQjj`>WpE8{V-TXrmTvMPD=!s}SI%&S<&W=eO( zoT-l@tB;O3^p}DiE4F%U;aYjJVv;Klw0`Zl2IhY2anlLQfGxuM&Hbi+8y3rEX6m=} zn|Ep+Gq6^Z(<)!DsARg#snlzuT9tlAO9Wv7io*lbc48J06*pxxn=(2~X(^A$Pv!o~ zs?s_?Wq*3et$!uK?cub(Ize6R8dt5D7zNh8YWJ`y;bP>2_E za)5W?Q=nc>F;CvV_QeTUe5AU* zQrUl8cb~`5#p4g6UkI$&@J*aV{Sje_C0SmxfjzBm{PCLlv~`GSingv5yj{LulUo}O z^#~u=hf0T1o$ulJ;wPA*thoJjv87p_?bmzA;wgU6Tsk;QDtHXLu;aL}&->tP}Tv;j-R zqyo(XW(qX03|J%hH3qhWrhaRK=>R*x!bOk*_LEw_^-gx&1gR&?U*U3Kc$z&H6`pC) z!wwz))+Q;pc57g2HL{jje%LU1JEqCA2#=>2z8rhKAH>CpW)w=&wSD=f zXpskt3J73{8uDOK;pyhx3+GjqRR=;oZy;P-R^7pad~dg?jh4$(4dvUSR;&|2kERV( zgjlFFp{K}ySfB?2LdTwRV%#wz5Pdz$mxNGvk1i|blSGvqmWvx_FE~#wrYN?jTUe&e zVj0gg&CYBWwTqdSbhCH`m!jz|7s_@eloc<_8yb5P5jW!d#4VILO{MHM+0eAP#nPX$ z$0RO`*!olYEqSI$$^lK(Ci*As{kA(9`W?-gnCZ85Xw<`x8=6x*iN4d)a*oxUllL{b zR;I>NyS*afr=nO)r&HZQL`ASl58uUM+~LQM8LXazJ|4FO{8&^C;Iz{|IvdH%6}fD+ zy6sgfa*G#|kLYq_neA*m#0--ijTYJ4Ch(&5gFeLcsVxHy`H7VLo zF#^iMBK~A^Av-9aXfCQ5Z!ty8eKQ#bJw5~GlXy@2=@wc}n8|NjOhML*&qKtzhlz!1 z-Fnj2&%kyvC1RD+R!_C2;FDpOjjMO3JwU?$KqqaK&#&%jCU3=Uo!)RKem+d2MU{}0 zJ9E@p;$u?Js;_3s(r4p9Q=k;}Rd18HWS~RuY8;-bucZcQs>+Akyfo-^SW$P6g=>gv1_4T=Y zTtve1_SXB#oUF;YFP`G@K*;Cu#4{5gGWda1))Vmu#P3k&cuFAD(SaXpqINL0;WUdi z(WH$g@iR9_r&3Qy2~AttFtds(np{q#o=5|cHAv#)JRWZ_7)m_JVUI_wrKJr-HWJxH zWHXU1M79#42SaQpvV#bZ5$zz-Nu-NNH<1XDULp#z4|^CistoY-h=ABnOV<)PM1(#Y z#7#tQCL)R4LgZE=w-Y%@gla>f%C@_xcUqlTz4NN#G-kMK2L6lTXdb8E3D?|ApuY z@LHTRg|C+8%`QiNdVW#9CCj3v$=f#rN|?j_c?4d)Fyqd zWgu>izWXPEi-uq5f^CQlC5c|&@8!hTlyvM Qb%7 delta 7712 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 KlKwv9{67GO3m$R+ diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-310.pyc index 997856522a13c8221de7194d6966ecb129ff1d0f..60fcb4f797ebf611939fa1b3f7ba05f9936c3ece 100644 GIT binary patch delta 19 ZcmeC?>gM9g=jG*M0D^CiH*ztu0sty%1Y!UH delta 19 YcmeC?>gM9g=jG*M00I&5ja-bZ03jj*v;Y7A diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4c44557576453d2cbb58ec23ef785512863b8e0 GIT binary patch literal 4940 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 b0o+<0H&AEzg9AgX%Mj%`(+dk9EqMO}zmzBA literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-310.pyc index c85fdfa6c0d715f3d0ce85edc2854d3b460b8e3d..40a9fc19b771cad4abffdac1d664785478c556fa 100644 GIT binary patch delta 617 zcmY*VO=}ZD7@l`#KPH=Glcs5EY>P^fvaz&x5%J(f#9jmoix5L*x@6stGCQp#-OxjO z?IG+@gpEJIyGIY+>dn)76a??$Rc8|r9GGXG=lyu*o%w8isoHV9ZXvaPfB))1b!KnE z``NwTISzDJXTV5cgr;kT)TMxw)`CiCxz>W~K{c$owFNhVdT6`$f}24jY`V<_r@>0t za$A5n&R2PR4(=MOvkIr&(54euDbR!Wel`Ecm3c*E@dg^#xDj6EWn8LkeRsl%qH*=x`vp7mIOW zgfTk_c;@4$_ty)OjFUne2=BC@Zw4Y7MP5?aN25S;@lUrN^JBr4gK|1t7G6b#g+;cW)ORxx=q|vO0-I7 sXLq&hM|a9BNu(&qD3YS=7ta6CD@*8uVj_1*bu`*Y8;fmUzp$M~bQ^tbWt z^6s72Jknx4&|@Po5F|;z6z>yaCKf!EYV+=lH zKy73wwTzvD)ZegN%e1na(VsM(arhf)qT(}q==Lg}F49UIC*#xNfPcZA;tzk+-6s4V z?R1}#i9VXVI1;;ib$^J5!|RnX8p-*K(J0xZR%Jx<@pv*DCtbQFe(_0sdwQb=c&d_$ qPi88qsmad&X}5l29>jBb5{36`Q)$f-U@{ZyXrs$qT!+mDxBdYyJ$JhR diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc index d5b2c3ed587576b92fe474987d73494252efa86b..ccee3d27a3e49d6396804e320e95f693b04c8c63 100644 GIT binary patch delta 1792 zcmZWpOK%)S5bo~jdF<@NYp>sVZOB6`2}T6CM3E&D5{QI0R+cEzh-kFlZad@5i=JLP zwr1G~gT#eH*b7n=w7wv5;Dp41-vK1_m4Cp28-(iF5G7$oQ&atQO?6exSM{j=?LsZ7 zR$TD6BOwWug&x&l%#t1MPI#J0h6}lO^QQ0dO zx)oNUs#lF_UaeT$;Z#)j>d~|}U96pOCTe(%LNA50(VRCI&3p5(c3F9ocnhq;s~dz> znS1eb>MgPwUjoSDOG{{jvME*vbeTc-3u;*I2c zB#w-B3?H{fkBrr_4FeBhSQ9t<^v@ zMvv*4p_T5++ezHRfc$qEpqTJnf+t%8A<-5dlN=pjak|irLO;pyd+1hUfD4S~D8~n6 zK%QC?us)s>f-vf!PihQg4v&7fNV`S$-1Q(HzA-s}Z>G}|K`OJS>lJ>Nw@gKnOwqI} zZ!3%6g$icM3^Eo7@hU{sGQ?SUDFbX3Nq1jLQXL8yk7cm2>rc*rGDn`B_-=Gf7$fQ*KA!0-jc z=)l@@Wohi@<^dkqxxG~$ST|9;M3F3QRV0vg_a;UI2P3evn3>ZDh*`M<2T<*w!QQ9N z4&FhsHlE5Y?H>ZD3o(?nt?BVhj<@O>oUGvB#$+{~I)LAo8{%GWFbZV1?-22&oXw4W z%p9#l?sM8kJD%8TyFn>0$$7~B2f2`!Aa|Dm0ztVCjZHi#=dSoJFOL`55Y!1=9B8r1 zcquO*;G!zP6^6cmo*Gp0%6K_16>*pH%7*T&YTH}(*RHPl*Kf4jSKIIVSKEH)#>KVk z*DhV|boNeOO8Oyd#))i(Nv|t;bFE-{^EnnY)hYa@(A3{sywVLq&YCi5LN_*{5u5#( zanal(=bK+!=ZA-ircrL%6&d$6H465L*ELma9&ZN%8c!2Pl(opS<;uv+!2A~$_|5= zXFOF#$iZhSAUFRu4^vUnA!w>9tDB|}LeVkG5jm_8vU#q=MSx|9}(i)Z0> z?vW=h8O_@#hKH5y`z-1Ceo;el0i1|;K`2Y^ra`&$r5ZcP5iD87UtoMVE z`B3nOWn z2vO>xsf5LZ7|tY<&&_6c`(0aYrP5EVQm6-&9uz!@mwL)2EIYGn>g0n-wziOE!RoT0OUUw8&Q?oyMcbrpi5q&(} zx-!(57GWPpy00UJAcC0@nZ8-sIQ9mywYw^DiTw)uQ>0EYot{^K)#>!up6aUeN*5E4I3SrJ>b|nkC=K+; zQw4q;X1UOx_ESc`9HCuxW)k8TZYPPNc1(gW?k1lUzEFPC0<>1H;Jum-0&YmCl?*R6 zWX8fgq&y3gnB(#--a}^j3-8RYNzuXuEK17-Xq7kgt?RhWdszp8f4(d*~Q;w}S7Wf1WbOOvfh3N0K9vT>h&i4yrRDVFg9MjbgJz|a;g>i;X&`VS( z1isf$-GNz{qh^7nroe^Sl{L1WaG6~hTX%=8DskbYZJyCUX3m%4OlaA0CX6g6Ngvwq zf`>U3YLW?)g)z-&Dlk0?bD=RB!(|@EdGL&~l$&sw%X$f;ou)J<+?LF0#c&!Whjhc@ zo03}xD2Mjd@~gePe5o6CIJ*rylNSx-+2y9Qa&K0cK|qpD5bzz~`7Hop;D8(EZQOwe^b$5i^%0PMNUoM+xaOx+fcu%>iJ=(k#?OuG*9c+fqGk Gb?FbQGTmSR diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-310.pyc index 90e1d49be3f0f86f9364b0ff095b75242e13f736..3237ab5feef5e2463b5734afa5e4406cd0485a70 100644 GIT binary patch delta 2911 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 Zwf^Pc9{|8WgUFiS- diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc index 4d14640e85c5c95d1c4b97934217b87e573d6acd..a6455ff4235ef9fc332ce84a4d7ea6fbbf6af6ac 100644 GIT binary patch delta 1269 zcmZux&2Jk;6rVR=-Z&eRG#`#b0*U$|wxy zZDb(1_7Lp_2`VKQq~4H_ICJEP1X88F(!ZfXYN5PYtLcY2()-QKo8Qd*=DoN3XXV$K zN<1-9CfM%({nzI0@CV>z|6htH(^$-HiX>_nYJKps|51gAt2aVIi?sPa^OnEfZ zoegJ;v54ln)vyXgGcELdjckIJu5Z&C32RD@ysD%Zl&4GjcQAaMz|R(^!%j;yt%dPz<0%kUKi8zh)IxPQ+dztT+fr=4ym(dL)C z@Ed^0zGv4?O=A#pIp`}~&RL{;foEpWXJ#GDIatXSc>w3KOS}W~+0XpL;dykoFkVG- zeF;sXwb1O>2;X8P6O0}jQv?NZCHDC)RdSc5(4WGdCn$Umc1224mhwFcBqg7atBbob zWeH8?9=uDCEe_ccvF9D=F%oA9wfQgG8pDuw4;H&5l~adJ4Ra0xlsYH<0!8b#75u5#fcxG&vJwX zsK8FpFwL#wwZ`?Psjo(Hs~OqhTK(CL#^qoW4ci~goDO5FlR@N%g>;eM)W=?SKfd^&kfe({V#<2(d zfq4&???6#cu11RH^59IMeT-(`L`bo4FwMTp2^IlKLD5@m!}%HdtIj`}U=1mLi*AsF zV_HOZQGECLJnp_jpVV#6Fn;EJ^kP89+JjyziQ~xTrGC>Son~ZQ6&J#C?!F51ftx?| z-0UB5a^(s-t@~AYrAd5B1voY9I1OGk?%n1>_LkgQTIhHB^#%rAn_e@jx1vtn_B*|v zHrAZTev&INo&7F@ZS%I>O2*IZ`p8iGeWScVJKpYUOhQYL{u hqKy74IeqAh@&kIxc_ey#UVccc@)31&$D)=0{s(bt7DNC5 delta 563 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 literal 13070 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 p%Rhc!0Ds<3lSuad7Iu{{mxh9Y_EG diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-310.pyc index f83b84e6bdefbb9fe742e856952b46a7d74cd0fa..4b34f7d9855f34dd85a2f6b2a90b092c338e8f16 100644 GIT binary patch delta 1969 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 None: # Don't complete if user hasn't sourced bash_completion file. if "PIP_AUTO_COMPLETE" not in os.environ: return + # Don't complete if autocompletion environment variables + # are not present + if not os.environ.get("COMP_WORDS") or not os.environ.get("COMP_CWORD"): + return cwords = os.environ["COMP_WORDS"].split()[1:] cword = int(os.environ["COMP_CWORD"]) try: @@ -71,8 +75,9 @@ def autocomplete() -> None: for opt in subcommand.parser.option_list_all: if opt.help != optparse.SUPPRESS_HELP: - for opt_str in opt._long_opts + opt._short_opts: - options.append((opt_str, opt.nargs)) + options += [ + (opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts + ] # filter out previously specified options from available options prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] diff --git a/venv/Lib/site-packages/pip/_internal/cli/base_command.py b/venv/Lib/site-packages/pip/_internal/cli/base_command.py index 0774f26..362f84b 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/base_command.py +++ b/venv/Lib/site-packages/pip/_internal/cli/base_command.py @@ -1,6 +1,5 @@ """Base Command class, and related routines""" -import functools import logging import logging.config import optparse @@ -8,8 +7,9 @@ import os import sys import traceback from optparse import Values -from typing import Any, Callable, List, Optional, Tuple +from typing import List, Optional, Tuple +from pip._vendor.rich import reconfigure from pip._vendor.rich import traceback as rich_traceback from pip._internal.cli import cmdoptions @@ -28,8 +28,8 @@ from pip._internal.exceptions import ( InstallationError, NetworkConnectionError, PreviousBuildDirError, - UninstallationError, ) +from pip._internal.utils.deprecation import deprecated from pip._internal.utils.filesystem import check_path_owner from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging from pip._internal.utils.misc import get_prog, normalize_path @@ -91,6 +91,63 @@ class Command(CommandContextMixIn): def run(self, options: Values, args: List[str]) -> int: raise NotImplementedError + def _run_wrapper(self, level_number: int, options: Values, args: List[str]) -> int: + def _inner_run() -> int: + try: + return self.run(options, args) + finally: + self.handle_pip_version_check(options) + + if options.debug_mode: + rich_traceback.install(show_locals=True) + return _inner_run() + + try: + status = _inner_run() + assert isinstance(status, int) + return status + except DiagnosticPipError as exc: + logger.error("%s", exc, extra={"rich": True}) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except ( + InstallationError, + BadCommand, + NetworkConnectionError, + ) as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical("%s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BrokenStdoutLoggingError: + # Bypass our logger and write any remaining messages to + # stderr because stdout no longer works. + print("ERROR: Pipe to stdout was broken", file=sys.stderr) + if level_number <= logging.DEBUG: + traceback.print_exc(file=sys.stderr) + + return ERROR + except KeyboardInterrupt: + logger.critical("Operation cancelled by user") + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BaseException: + logger.critical("Exception:", exc_info=True) + + return UNKNOWN_ERROR + def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]: # factored out for testability return self.parser.parse_args(args) @@ -116,12 +173,33 @@ class Command(CommandContextMixIn): # Set verbosity so that it can be used elsewhere. self.verbosity = options.verbose - options.quiet + reconfigure(no_color=options.no_color) level_number = setup_logging( verbosity=self.verbosity, no_color=options.no_color, user_log_file=options.log, ) + always_enabled_features = set(options.features_enabled) & set( + cmdoptions.ALWAYS_ENABLED_FEATURES + ) + if always_enabled_features: + logger.warning( + "The following features are always enabled: %s. ", + ", ".join(sorted(always_enabled_features)), + ) + + # Make sure that the --python argument isn't specified after the + # subcommand. We can tell, because if --python was specified, + # we should only reach this point if we're running in the created + # subprocess, which has the _PIP_RUNNING_IN_SUBPROCESS environment + # variable set. + if options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: + logger.critical( + "The --python option must be placed before the pip subcommand name" + ) + sys.exit(ERROR) + # TODO: Try to get these passing down from the command? # without resorting to os.environ to hold these. # This also affects isolated builds and it should. @@ -151,73 +229,12 @@ class Command(CommandContextMixIn): ) options.cache_dir = None - if "2020-resolver" in options.features_enabled: - logger.warning( - "--use-feature=2020-resolver no longer has any effect, " - "since it is now the default dependency resolver in pip. " - "This will become an error in pip 21.0." + if options.no_python_version_warning: + deprecated( + reason="--no-python-version-warning is deprecated.", + replacement="to remove the flag as it's a no-op", + gone_in="25.1", + issue=13154, ) - def intercepts_unhandled_exc( - run_func: Callable[..., int] - ) -> Callable[..., int]: - @functools.wraps(run_func) - def exc_logging_wrapper(*args: Any) -> int: - try: - status = run_func(*args) - assert isinstance(status, int) - return status - except DiagnosticPipError as exc: - logger.error("[present-rich] %s", exc) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except PreviousBuildDirError as exc: - logger.critical(str(exc)) - logger.debug("Exception information:", exc_info=True) - - return PREVIOUS_BUILD_DIR_ERROR - except ( - InstallationError, - UninstallationError, - BadCommand, - NetworkConnectionError, - ) as exc: - logger.critical(str(exc)) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except CommandError as exc: - logger.critical("%s", exc) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except BrokenStdoutLoggingError: - # Bypass our logger and write any remaining messages to - # stderr because stdout no longer works. - print("ERROR: Pipe to stdout was broken", file=sys.stderr) - if level_number <= logging.DEBUG: - traceback.print_exc(file=sys.stderr) - - return ERROR - except KeyboardInterrupt: - logger.critical("Operation cancelled by user") - logger.debug("Exception information:", exc_info=True) - - return ERROR - except BaseException: - logger.critical("Exception:", exc_info=True) - - return UNKNOWN_ERROR - - return exc_logging_wrapper - - try: - if not options.debug_mode: - run = intercepts_unhandled_exc(self.run) - else: - run = self.run - rich_traceback.install(show_locals=True) - return run(options, args) - finally: - self.handle_pip_version_check(options) + return self._run_wrapper(level_number, options, args) diff --git a/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py index 47ed927..eeb7e65 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py +++ b/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -59,31 +59,6 @@ def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> Opti return option_group -def check_install_build_global( - options: Values, check_options: Optional[Values] = None -) -> None: - """Disable wheels if per-setup.py call options are set. - - :param options: The OptionParser options to update. - :param check_options: The options to check, if not supplied defaults to - options. - """ - if check_options is None: - check_options = options - - def getname(n: str) -> Optional[Any]: - return getattr(check_options, n, None) - - names = ["build_options", "global_options", "install_options"] - if any(map(getname, names)): - control = options.format_control - control.disallow_binaries() - logger.warning( - "Disabling all use of wheels due to the use of --build-option " - "/ --global-option / --install-option.", - ) - - def check_dist_restriction(options: Values, check_target: bool = False) -> None: """Function for determining if custom platform options are allowed. @@ -117,10 +92,10 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None: ) if check_target: - if dist_restriction_set and not options.target_dir: + if not options.dry_run and dist_restriction_set and not options.target_dir: raise CommandError( "Can not use any platform or abi specific options unless " - "installing via '--target'" + "installing via '--target' or using '--dry-run'" ) @@ -189,6 +164,21 @@ require_virtualenv: Callable[..., Option] = partial( ), ) +override_externally_managed: Callable[..., Option] = partial( + Option, + "--break-system-packages", + dest="override_externally_managed", + action="store_true", + help="Allow pip to modify an EXTERNALLY-MANAGED Python installation", +) + +python: Callable[..., Option] = partial( + Option, + "--python", + dest="python", + help="Run pip with the specified Python interpreter.", +) + verbose: Callable[..., Option] = partial( Option, "-v", @@ -236,9 +226,9 @@ progress_bar: Callable[..., Option] = partial( "--progress-bar", dest="progress_bar", type="choice", - choices=["on", "off"], + choices=["on", "off", "raw"], default="on", - help="Specify whether the progress bar should be used [on, off] (default: on)", + help="Specify whether the progress bar should be used [on, off, raw] (default: on)", ) log: Callable[..., Option] = partial( @@ -262,6 +252,19 @@ no_input: Callable[..., Option] = partial( help="Disable prompting for input.", ) +keyring_provider: Callable[..., Option] = partial( + Option, + "--keyring-provider", + dest="keyring_provider", + choices=["auto", "disabled", "import", "subprocess"], + default="auto", + help=( + "Enable the credential lookup via the keyring library if user input is allowed." + " Specify which mechanism to use [auto, disabled, import, subprocess]." + " (default: %default)" + ), +) + proxy: Callable[..., Option] = partial( Option, "--proxy", @@ -579,10 +582,7 @@ def _handle_python_version( """ version_info, error_msg = _convert_python_version(value) if error_msg is not None: - msg = "invalid --python-version value: {!r}: {}".format( - value, - error_msg, - ) + msg = f"invalid --python-version value: {value!r}: {error_msg}" raise_option_error(parser, option=option, msg=msg) parser.values.python_version = version_info @@ -667,7 +667,10 @@ def prefer_binary() -> Option: dest="prefer_binary", action="store_true", default=False, - help="Prefer older binary packages over newer source packages.", + help=( + "Prefer binary packages over source packages, even if the " + "source packages are newer." + ), ) @@ -780,10 +783,14 @@ def _handle_no_use_pep517( """ raise_option_error(parser, option=option, msg=msg) - # If user doesn't wish to use pep517, we check if setuptools is installed + # If user doesn't wish to use pep517, we check if setuptools and wheel are installed # and raise error if it is not. - if not importlib.util.find_spec("setuptools"): - msg = "It is not possible to use --no-use-pep517 without setuptools installed." + packages = ("setuptools", "wheel") + if not all(importlib.util.find_spec(package) for package in packages): + msg = ( + f"It is not possible to use --no-use-pep517 " + f"without {' and '.join(packages)} installed." + ) raise_option_error(parser, option=option, msg=msg) # Otherwise, --no-use-pep517 was passed via the command-line. @@ -816,16 +823,23 @@ def _handle_config_settings( ) -> None: key, sep, val = value.partition("=") if sep != "=": - parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa + parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") dest = getattr(parser.values, option.dest) if dest is None: dest = {} setattr(parser.values, option.dest, dest) - dest[key] = val + if key in dest: + if isinstance(dest[key], list): + dest[key].append(val) + else: + dest[key] = [dest[key], val] + else: + dest[key] = val config_settings: Callable[..., Option] = partial( Option, + "-C", "--config-settings", dest="config_settings", type=str, @@ -837,19 +851,6 @@ config_settings: Callable[..., Option] = partial( "to pass multiple keys to the backend.", ) -install_options: Callable[..., Option] = partial( - Option, - "--install-option", - dest="install_options", - action="append", - metavar="options", - help="Extra arguments to be supplied to the setup.py install " - 'command (use like --install-option="--install-scripts=/usr/local/' - 'bin"). Use multiple --install-option options to pass multiple ' - "options to setup.py install. If you are using an option with a " - "directory path, be sure to use absolute path.", -) - build_options: Callable[..., Option] = partial( Option, "--build-option", @@ -902,7 +903,7 @@ root_user_action: Callable[..., Option] = partial( dest="root_user_action", default="warn", choices=["warn", "ignore"], - help="Action if pip is run as a root user. By default, a warning message is shown.", + help="Action if pip is run as a root user [warn, ignore] (default: warn)", ) @@ -917,13 +918,13 @@ def _handle_merge_hash( algo, digest = value.split(":", 1) except ValueError: parser.error( - "Arguments to {} must be a hash name " # noqa + f"Arguments to {opt_str} must be a hash name " "followed by a value, like --hash=sha256:" - "abcde...".format(opt_str) + "abcde..." ) if algo not in STRONG_HASHES: parser.error( - "Allowed hash algorithms for {} are {}.".format( # noqa + "Allowed hash algorithms for {} are {}.".format( opt_str, ", ".join(STRONG_HASHES) ) ) @@ -993,6 +994,12 @@ no_python_version_warning: Callable[..., Option] = partial( ) +# Features that are now always on. A warning is printed if they are used. +ALWAYS_ENABLED_FEATURES = [ + "truststore", # always on since 24.2 + "no-binary-enable-wheel-cache", # always on since 23.1 +] + use_new_feature: Callable[..., Option] = partial( Option, "--use-feature", @@ -1000,7 +1007,10 @@ use_new_feature: Callable[..., Option] = partial( metavar="feature", action="append", default=[], - choices=["2020-resolver", "fast-deps", "truststore"], + choices=[ + "fast-deps", + ] + + ALWAYS_ENABLED_FEATURES, help="Enable new functionality, that may be backward incompatible.", ) @@ -1013,6 +1023,7 @@ use_deprecated_feature: Callable[..., Option] = partial( default=[], choices=[ "legacy-resolver", + "legacy-certs", ], help=("Enable deprecated functionality, that will be removed in the future."), ) @@ -1029,11 +1040,13 @@ general_group: Dict[str, Any] = { debug_mode, isolated_mode, require_virtualenv, + python, verbose, version, quiet, log, no_input, + keyring_provider, proxy, retries, timeout, diff --git a/venv/Lib/site-packages/pip/_internal/cli/index_command.py b/venv/Lib/site-packages/pip/_internal/cli/index_command.py new file mode 100644 index 0000000..295108e --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/index_command.py @@ -0,0 +1,171 @@ +""" +Contains command classes which may interact with an index / the network. + +Unlike its sister module, req_command, this module still uses lazy imports +so commands which don't always hit the network (e.g. list w/o --outdated or +--uptodate) don't need waste time importing PipSession and friends. +""" + +import logging +import os +import sys +from optparse import Values +from typing import TYPE_CHECKING, List, Optional + +from pip._vendor import certifi + +from pip._internal.cli.base_command import Command +from pip._internal.cli.command_context import CommandContextMixIn + +if TYPE_CHECKING: + from ssl import SSLContext + + from pip._internal.network.session import PipSession + +logger = logging.getLogger(__name__) + + +def _create_truststore_ssl_context() -> Optional["SSLContext"]: + if sys.version_info < (3, 10): + logger.debug("Disabling truststore because Python version isn't 3.10+") + return None + + try: + import ssl + except ImportError: + logger.warning("Disabling truststore since ssl support is missing") + return None + + try: + from pip._vendor import truststore + except ImportError: + logger.warning("Disabling truststore because platform isn't supported") + return None + + ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.load_verify_locations(certifi.where()) + return ctx + + +class SessionCommandMixin(CommandContextMixIn): + """ + A class mixin for command classes needing _build_session(). + """ + + def __init__(self) -> None: + super().__init__() + self._session: Optional[PipSession] = None + + @classmethod + def _get_index_urls(cls, options: Values) -> Optional[List[str]]: + """Return a list of index urls from user-provided options.""" + index_urls = [] + if not getattr(options, "no_index", False): + url = getattr(options, "index_url", None) + if url: + index_urls.append(url) + urls = getattr(options, "extra_index_urls", None) + if urls: + index_urls.extend(urls) + # Return None rather than an empty list + return index_urls or None + + def get_default_session(self, options: Values) -> "PipSession": + """Get a default-managed session.""" + if self._session is None: + self._session = self.enter_context(self._build_session(options)) + # there's no type annotation on requests.Session, so it's + # automatically ContextManager[Any] and self._session becomes Any, + # then https://github.com/python/mypy/issues/7696 kicks in + assert self._session is not None + return self._session + + def _build_session( + self, + options: Values, + retries: Optional[int] = None, + timeout: Optional[int] = None, + ) -> "PipSession": + from pip._internal.network.session import PipSession + + cache_dir = options.cache_dir + assert not cache_dir or os.path.isabs(cache_dir) + + if "legacy-certs" not in options.deprecated_features_enabled: + ssl_context = _create_truststore_ssl_context() + else: + ssl_context = None + + session = PipSession( + cache=os.path.join(cache_dir, "http-v2") if cache_dir else None, + retries=retries if retries is not None else options.retries, + trusted_hosts=options.trusted_hosts, + index_urls=self._get_index_urls(options), + ssl_context=ssl_context, + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = timeout if timeout is not None else options.timeout + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + session.trust_env = False + session.pip_proxy = options.proxy + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + session.auth.keyring_provider = options.keyring_provider + + return session + + +def _pip_self_version_check(session: "PipSession", options: Values) -> None: + from pip._internal.self_outdated_check import pip_self_version_check as check + + check(session, options) + + +class IndexGroupCommand(Command, SessionCommandMixin): + """ + Abstract base class for commands with the index_group options. + + This also corresponds to the commands that permit the pip version check. + """ + + def handle_pip_version_check(self, options: Values) -> None: + """ + Do the pip version check if not disabled. + + This overrides the default behavior of not doing the check. + """ + # Make sure the index_group options are present. + assert hasattr(options, "no_index") + + if options.disable_pip_version_check or options.no_index: + return + + try: + # Otherwise, check if we're using the latest version of pip available. + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout), + ) + with session: + _pip_self_version_check(session, options) + except Exception: + logger.warning("There was an error checking the latest version of pip.") + logger.debug("See below for error", exc_info=True) diff --git a/venv/Lib/site-packages/pip/_internal/cli/main.py b/venv/Lib/site-packages/pip/_internal/cli/main.py index 0e31221..563ac79 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/main.py +++ b/venv/Lib/site-packages/pip/_internal/cli/main.py @@ -1,9 +1,11 @@ """Primary application entrypoint. """ + import locale import logging import os import sys +import warnings from typing import List, Optional from pip._internal.cli.autocompletion import autocomplete @@ -46,6 +48,14 @@ def main(args: Optional[List[str]] = None) -> int: if args is None: args = sys.argv[1:] + # Suppress the pkg_resources deprecation warning + # Note - we use a module of .*pkg_resources to cover + # the normal case (pip._vendor.pkg_resources) and the + # devendored case (a bare pkg_resources) + warnings.filterwarnings( + action="ignore", category=DeprecationWarning, module=".*pkg_resources" + ) + # Configure our deprecation warnings to be sent through loggers deprecation.install_warning_logger() diff --git a/venv/Lib/site-packages/pip/_internal/cli/main_parser.py b/venv/Lib/site-packages/pip/_internal/cli/main_parser.py index 3666ab0..5ade356 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/main_parser.py +++ b/venv/Lib/site-packages/pip/_internal/cli/main_parser.py @@ -2,9 +2,11 @@ """ import os +import subprocess import sys -from typing import List, Tuple +from typing import List, Optional, Tuple +from pip._internal.build_env import get_runnable_pip from pip._internal.cli import cmdoptions from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter from pip._internal.commands import commands_dict, get_similar_commands @@ -45,6 +47,25 @@ def create_main_parser() -> ConfigOptionParser: return parser +def identify_python_interpreter(python: str) -> Optional[str]: + # If the named file exists, use it. + # If it's a directory, assume it's a virtual environment and + # look for the environment's Python executable. + if os.path.exists(python): + if os.path.isdir(python): + # bin/python for Unix, Scripts/python.exe for Windows + # Try both in case of odd cases like cygwin. + for exe in ("bin/python", "Scripts/python.exe"): + py = os.path.join(python, exe) + if os.path.exists(py): + return py + else: + return python + + # Could not find the interpreter specified + return None + + def parse_command(args: List[str]) -> Tuple[str, List[str]]: parser = create_main_parser() @@ -57,6 +78,32 @@ def parse_command(args: List[str]) -> Tuple[str, List[str]]: # args_else: ['install', '--user', 'INITools'] general_options, args_else = parser.parse_args(args) + # --python + if general_options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: + # Re-invoke pip using the specified Python interpreter + interpreter = identify_python_interpreter(general_options.python) + if interpreter is None: + raise CommandError( + f"Could not locate Python interpreter {general_options.python}" + ) + + pip_cmd = [ + interpreter, + get_runnable_pip(), + ] + pip_cmd.extend(args) + + # Set a flag so the child doesn't re-invoke itself, causing + # an infinite loop. + os.environ["_PIP_RUNNING_IN_SUBPROCESS"] = "1" + returncode = 0 + try: + proc = subprocess.run(pip_cmd) + returncode = proc.returncode + except (subprocess.SubprocessError, OSError) as exc: + raise CommandError(f"Failed to run pip under {interpreter}: {exc}") + sys.exit(returncode) + # --version if general_options.version: sys.stdout.write(parser.version) diff --git a/venv/Lib/site-packages/pip/_internal/cli/parser.py b/venv/Lib/site-packages/pip/_internal/cli/parser.py index c762cf2..bc4aca0 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/parser.py +++ b/venv/Lib/site-packages/pip/_internal/cli/parser.py @@ -6,7 +6,7 @@ import shutil import sys import textwrap from contextlib import suppress -from typing import Any, Dict, Generator, List, Tuple +from typing import Any, Dict, Generator, List, NoReturn, Optional, Tuple from pip._internal.cli.status_codes import UNKNOWN_ERROR from pip._internal.configuration import Configuration, ConfigurationError @@ -67,7 +67,7 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter): msg = "\nUsage: {}\n".format(self.indent_lines(textwrap.dedent(usage), " ")) return msg - def format_description(self, description: str) -> str: + def format_description(self, description: Optional[str]) -> str: # leave full control over description to us if description: if hasattr(self.parser, "main"): @@ -85,7 +85,7 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter): else: return "" - def format_epilog(self, epilog: str) -> str: + def format_epilog(self, epilog: Optional[str]) -> str: # leave full control over epilog to us if epilog: return epilog @@ -229,9 +229,9 @@ class ConfigOptionParser(CustomOptionParser): val = strtobool(val) except ValueError: self.error( - "{} is not a valid value for {} option, " # noqa + f"{val} is not a valid value for {key} option, " "please specify a boolean value like yes/no, " - "true/false or 1/0 instead.".format(val, key) + "true/false or 1/0 instead." ) elif option.action == "count": with suppress(ValueError): @@ -240,10 +240,10 @@ class ConfigOptionParser(CustomOptionParser): val = int(val) if not isinstance(val, int) or val < 0: self.error( - "{} is not a valid value for {} option, " # noqa + f"{val} is not a valid value for {key} option, " "please instead specify either a non-negative integer " "or a boolean value like yes/no or false/true " - "which is equivalent to 1/0.".format(val, key) + "which is equivalent to 1/0." ) elif option.action == "append": val = val.split() @@ -289,6 +289,6 @@ class ConfigOptionParser(CustomOptionParser): defaults[option.dest] = option.check_value(opt_str, default) return optparse.Values(defaults) - def error(self, msg: str) -> None: + def error(self, msg: str) -> NoReturn: self.print_usage(sys.stderr) self.exit(UNKNOWN_ERROR, f"{msg}\n") diff --git a/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py index 0ad1403..3d9dde8 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py +++ b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py @@ -1,4 +1,5 @@ import functools +import sys from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple from pip._vendor.rich.progress import ( @@ -14,6 +15,7 @@ from pip._vendor.rich.progress import ( TransferSpeedColumn, ) +from pip._internal.cli.spinners import RateLimiter from pip._internal.utils.logging import get_indentation DownloadProgressRenderer = Callable[[Iterable[bytes]], Iterator[bytes]] @@ -23,7 +25,7 @@ def _rich_progress_bar( iterable: Iterable[bytes], *, bar_type: str, - size: int, + size: Optional[int], ) -> Generator[bytes, None, None]: assert bar_type == "on", "This should only be used in the default mode." @@ -47,7 +49,7 @@ def _rich_progress_bar( TimeRemainingColumn(), ) - progress = Progress(*columns, refresh_per_second=30) + progress = Progress(*columns, refresh_per_second=5) task_id = progress.add_task(" " * (get_indentation() + 2), total=total) with progress: for chunk in iterable: @@ -55,6 +57,28 @@ def _rich_progress_bar( progress.update(task_id, advance=len(chunk)) +def _raw_progress_bar( + iterable: Iterable[bytes], + *, + size: Optional[int], +) -> Generator[bytes, None, None]: + def write_progress(current: int, total: int) -> None: + sys.stdout.write(f"Progress {current} of {total}\n") + sys.stdout.flush() + + current = 0 + total = size or 0 + rate_limiter = RateLimiter(0.25) + + write_progress(current, total) + for chunk in iterable: + current += len(chunk) + if rate_limiter.ready() or current == total: + write_progress(current, total) + rate_limiter.reset() + yield chunk + + def get_download_progress_renderer( *, bar_type: str, size: Optional[int] = None ) -> DownloadProgressRenderer: @@ -64,5 +88,7 @@ def get_download_progress_renderer( """ if bar_type == "on": return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size) + elif bar_type == "raw": + return functools.partial(_raw_progress_bar, size=size) else: return iter # no-op, when passed an iterator diff --git a/venv/Lib/site-packages/pip/_internal/cli/req_command.py b/venv/Lib/site-packages/pip/_internal/cli/req_command.py index 1044809..92900f9 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/req_command.py +++ b/venv/Lib/site-packages/pip/_internal/cli/req_command.py @@ -1,21 +1,19 @@ -"""Contains the Command base classes that depend on PipSession. +"""Contains the RequirementCommand base class. -The classes in this module are in a separate module so the commands not -needing download / PackageFinder capability don't unnecessarily import the +This class is in a separate module so the commands that do not always +need PackageFinder capability don't unnecessarily import the PackageFinder machinery and all its vendored dependencies, etc. """ import logging -import os -import sys from functools import partial from optparse import Values -from typing import TYPE_CHECKING, Any, List, Optional, Tuple +from typing import Any, List, Optional, Tuple from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import Command -from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.cli.index_command import IndexGroupCommand +from pip._internal.cli.index_command import SessionCommandMixin as SessionCommandMixin from pip._internal.exceptions import CommandError, PreviousBuildDirError from pip._internal.index.collector import LinkCollector from pip._internal.index.package_finder import PackageFinder @@ -33,163 +31,15 @@ from pip._internal.req.constructors import ( from pip._internal.req.req_file import parse_requirements from pip._internal.req.req_install import InstallRequirement from pip._internal.resolution.base import BaseResolver -from pip._internal.self_outdated_check import pip_self_version_check from pip._internal.utils.temp_dir import ( TempDirectory, TempDirectoryTypeRegistry, tempdir_kinds, ) -from pip._internal.utils.virtualenv import running_under_virtualenv - -if TYPE_CHECKING: - from ssl import SSLContext logger = logging.getLogger(__name__) -def _create_truststore_ssl_context() -> Optional["SSLContext"]: - if sys.version_info < (3, 10): - raise CommandError("The truststore feature is only available for Python 3.10+") - - try: - import ssl - except ImportError: - logger.warning("Disabling truststore since ssl support is missing") - return None - - try: - import truststore - except ImportError: - raise CommandError( - "To use the truststore feature, 'truststore' must be installed into " - "pip's current environment." - ) - - return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - - -class SessionCommandMixin(CommandContextMixIn): - - """ - A class mixin for command classes needing _build_session(). - """ - - def __init__(self) -> None: - super().__init__() - self._session: Optional[PipSession] = None - - @classmethod - def _get_index_urls(cls, options: Values) -> Optional[List[str]]: - """Return a list of index urls from user-provided options.""" - index_urls = [] - if not getattr(options, "no_index", False): - url = getattr(options, "index_url", None) - if url: - index_urls.append(url) - urls = getattr(options, "extra_index_urls", None) - if urls: - index_urls.extend(urls) - # Return None rather than an empty list - return index_urls or None - - def get_default_session(self, options: Values) -> PipSession: - """Get a default-managed session.""" - if self._session is None: - self._session = self.enter_context(self._build_session(options)) - # there's no type annotation on requests.Session, so it's - # automatically ContextManager[Any] and self._session becomes Any, - # then https://github.com/python/mypy/issues/7696 kicks in - assert self._session is not None - return self._session - - def _build_session( - self, - options: Values, - retries: Optional[int] = None, - timeout: Optional[int] = None, - fallback_to_certifi: bool = False, - ) -> PipSession: - cache_dir = options.cache_dir - assert not cache_dir or os.path.isabs(cache_dir) - - if "truststore" in options.features_enabled: - try: - ssl_context = _create_truststore_ssl_context() - except Exception: - if not fallback_to_certifi: - raise - ssl_context = None - else: - ssl_context = None - - session = PipSession( - cache=os.path.join(cache_dir, "http") if cache_dir else None, - retries=retries if retries is not None else options.retries, - trusted_hosts=options.trusted_hosts, - index_urls=self._get_index_urls(options), - ssl_context=ssl_context, - ) - - # Handle custom ca-bundles from the user - if options.cert: - session.verify = options.cert - - # Handle SSL client certificate - if options.client_cert: - session.cert = options.client_cert - - # Handle timeouts - if options.timeout or timeout: - session.timeout = timeout if timeout is not None else options.timeout - - # Handle configured proxies - if options.proxy: - session.proxies = { - "http": options.proxy, - "https": options.proxy, - } - - # Determine if we can prompt the user for authentication or not - session.auth.prompting = not options.no_input - - return session - - -class IndexGroupCommand(Command, SessionCommandMixin): - - """ - Abstract base class for commands with the index_group options. - - This also corresponds to the commands that permit the pip version check. - """ - - def handle_pip_version_check(self, options: Values) -> None: - """ - Do the pip version check if not disabled. - - This overrides the default behavior of not doing the check. - """ - # Make sure the index_group options are present. - assert hasattr(options, "no_index") - - if options.disable_pip_version_check or options.no_index: - return - - # Otherwise, check if we're using the latest version of pip available. - session = self._build_session( - options, - retries=0, - timeout=min(5, options.timeout), - # This is set to ensure the function does not fail when truststore is - # specified in use-feature but cannot be loaded. This usually raises a - # CommandError and shows a nice user-facing error, but this function is not - # called in that try-except block. - fallback_to_certifi=True, - ) - with session: - pip_self_version_check(session, options) - - KEEPABLE_TEMPDIR_TYPES = [ tempdir_kinds.BUILD_ENV, tempdir_kinds.EPHEM_WHEEL_CACHE, @@ -197,36 +47,6 @@ KEEPABLE_TEMPDIR_TYPES = [ ] -def warn_if_run_as_root() -> None: - """Output a warning for sudo users on Unix. - - In a virtual environment, sudo pip still writes to virtualenv. - On Windows, users may run pip as Administrator without issues. - This warning only applies to Unix root users outside of virtualenv. - """ - if running_under_virtualenv(): - return - if not hasattr(os, "getuid"): - return - # On Windows, there are no "system managed" Python packages. Installing as - # Administrator via pip is the correct way of updating system environments. - # - # We choose sys.platform over utils.compat.WINDOWS here to enable Mypy platform - # checks: https://mypy.readthedocs.io/en/stable/common_issues.html - if sys.platform == "win32" or sys.platform == "cygwin": - return - - if os.getuid() != 0: - return - - logger.warning( - "Running pip as the 'root' user can result in broken permissions and " - "conflicting behaviour with the system package manager. " - "It is recommended to use a virtual environment instead: " - "https://pip.pypa.io/warnings/venv" - ) - - def with_cleanup(func: Any) -> Any: """Decorator for common logic related to managing temporary directories. @@ -267,7 +87,7 @@ class RequirementCommand(IndexGroupCommand): if "legacy-resolver" in options.deprecated_features_enabled: return "legacy" - return "2020-resolver" + return "resolvelib" @classmethod def make_requirement_preparer( @@ -286,9 +106,10 @@ class RequirementCommand(IndexGroupCommand): """ temp_build_dir_path = temp_build_dir.path assert temp_build_dir_path is not None + legacy_resolver = False resolver_variant = cls.determine_resolver_variant(options) - if resolver_variant == "2020-resolver": + if resolver_variant == "resolvelib": lazy_wheel = "fast-deps" in options.features_enabled if lazy_wheel: logger.warning( @@ -299,6 +120,7 @@ class RequirementCommand(IndexGroupCommand): "production." ) else: + legacy_resolver = True lazy_wheel = False if "fast-deps" in options.features_enabled: logger.warning( @@ -319,6 +141,7 @@ class RequirementCommand(IndexGroupCommand): use_user_site=use_user_site, lazy_wheel=lazy_wheel, verbosity=verbosity, + legacy_resolver=legacy_resolver, ) @classmethod @@ -343,13 +166,12 @@ class RequirementCommand(IndexGroupCommand): install_req_from_req_string, isolated=options.isolated_mode, use_pep517=use_pep517, - config_settings=getattr(options, "config_settings", None), ) resolver_variant = cls.determine_resolver_variant(options) # The long import name and duplicated invocation is needed to convince # Mypy into correctly typechecking. Otherwise it would complain the # "Resolver" class being redefined. - if resolver_variant == "2020-resolver": + if resolver_variant == "resolvelib": import pip._internal.resolution.resolvelib.resolver return pip._internal.resolution.resolvelib.resolver.Resolver( @@ -410,7 +232,7 @@ class RequirementCommand(IndexGroupCommand): for req in args: req_to_add = install_req_from_line( req, - None, + comes_from=None, isolated=options.isolated_mode, use_pep517=options.use_pep517, user_supplied=True, @@ -438,6 +260,11 @@ class RequirementCommand(IndexGroupCommand): isolated=options.isolated_mode, use_pep517=options.use_pep517, user_supplied=True, + config_settings=( + parsed_req.options.get("config_settings") + if parsed_req.options + else None + ), ) requirements.append(req_to_add) diff --git a/venv/Lib/site-packages/pip/_internal/cli/spinners.py b/venv/Lib/site-packages/pip/_internal/cli/spinners.py index a50e6ad..cf2b976 100644 --- a/venv/Lib/site-packages/pip/_internal/cli/spinners.py +++ b/venv/Lib/site-packages/pip/_internal/cli/spinners.py @@ -3,7 +3,7 @@ import itertools import logging import sys import time -from typing import IO, Generator +from typing import IO, Generator, Optional from pip._internal.utils.compat import WINDOWS from pip._internal.utils.logging import get_indentation @@ -23,7 +23,7 @@ class InteractiveSpinner(SpinnerInterface): def __init__( self, message: str, - file: IO[str] = None, + file: Optional[IO[str]] = None, spin_chars: str = "-\\|/", # Empirically, 8 updates/second looks nice min_update_interval_seconds: float = 0.125, diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-310.pyc index 2e100c0872084cfd429f14c90af236bf0cb4b3c7..7586205cf2b880b23b0185c65fa077b360d473a4 100644 GIT binary patch delta 19 ZcmbOyIZu)+pO=@50SLZ5-pDnD2LLcZ1wa4* delta 19 ZcmbOyIZu)+pO=@50SH9IH*!tk0RSfX1Cjs$ diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-310.pyc index bd3061b268c7022917d8604b4a9b73a3176370e8..93614b9ecaeeaa021fce553be5e5bfa00b55ba03 100644 GIT binary patch delta 2246 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 R=qd}Km$0k3*jAR*{{WTJ9!UTI delta 714 zcmZuvOKVd>6rR_e`^e3sHQ1y+SC&}FB9v0JxQS2|kwOLGQVB6LjcM;AnS0ZP%+*D@ zbQ1=*QV|6Ih6@+2T)4Ume~af-@0{~7^RfQkuO-#0hhR0=evLoyW$ijX zU2Z<^MSkF8B#^MfYE%nq7)f+qmyJ(2SlL6u5$+ihuH*|EtO|U9I^Oczc9RqQ)(1<^0W!2eha{&t%dn;k48E0fZ9POU*K%7^4Hb_`?r5v@AX>@Y zj0&u6?Pyn!Hd-)@X02IObGTi<#Nq!qwL_YFc_sI^fC?pn>T6F|796O(*@m{#N1B5% z^(12l2(s7$W0YAiyk+jwSLQpt)#J*6iIojd*r!sZlO$H98fBHh0Xo%!r7}EHl``U+ z=WM&~PgQa(N7*1AMpD(x7q-d1BGod#*^ByB$V+zsJmO=An0@Q+4c}wnGW@2|FJGab zMA0x7T{VxNbv*Og>h4?f6rM$qvIzw!Xqu^lPU1|hm$BAmXqU(Gdo;k(QiOvTX5=Ql zh<2`+9X>Zd`0cl)whNU-YdV>B2T)O}co=r)*(6N6(Ig#RC@$Qw%$_D=7(!hGPQk;! ihqBB6+854ll!$pKA7IExR{w!F(o0ylPqfnHZo>^RyT7Y;8K8sw9>rflFa-(h4_NZg81b8+=84` zFu%GQu0}y2CqFqcN1;5wD5Y2-8AKt;6{RMoDCjySL!>bzlJn4Xa4IMir55B=+G}E3-4h}}2 l&GtMC7#WKonGCKOJ1U#& zdg_CRCH??!nm^!QP&|1O^yCjv@Pk+*+C{x8x*oi$_oe&(Mm4QeT!Qc0=MVi>>vi>< z53kH6|NK)$HGfF5X3iAT{Dds&0*;{Yay}HAoe;&#UqzQ(31vN}K<*Mn_6R4rHM<66 zE`Sua7DIb_RWmK_*+)2^izng`ki&=0Z2uq2L5-5R@m~db8-Iz1By`MMzrFhdg5vT{ zl*lB_WqJ@N68l&U@-&k@%t-bI<5(uqB$oHnB##EkAnD7%EvO9kL-;7B590B-Xq&Ho zn})8bHD=~TquXlX?Jl^~fifs_fUhZ+Pz4Kvg7eG+56thz%{w+ycQB{d5ptqo0h*0i zR##X{D{@#6tW49=o~1qKIht77rkN5Wnr&%N)@d|J!yXB3bG+Gwj(NA)xlmNLWjlTp zO%BHK6&Vyxc|~u~mjw;N>>>(gfDp3mw%Km_Fg3f)v-R)gHZ_D()S82 za_Fg-`3Lk*2>uzph5QM<^jv!AFWR@z&M+Sy^FHvt@4o%Hm5nkPo8T#KJ@m`lciCqS ze9-$&?P_LAwltNYSf8!{$ZO)0E@4Ebrn^956UZ#B%+vIwfsXkmy}*8KUYh5C4m-7` z$Nwx#8a`caplh$-1{Uz&J13senQb3O@6UWbiX`^~8Hiyx3V3gyojYv^vN&gQZA zNXMmVI&~6>VNdFBrMBy0Xd7&5fd!NnAqy$I6s+q!(gyZNzb!x4p9&jC2dGM-aJVuC zhA8;3#7fc|qUg$qnZzZNU+;e=oP-g+8h@U(VwlUJovM!|_>g z$lZC&-$kR7u+QhQ>xn%aBLLws@hYju333TC$*(Dr%%YY+=(|ew@mDM-dBi5A6yNXl pmr5Q0)<2$Rzzmay-sHa^)F0g~&8tl)=uXvv!8%03g}!w=e*tTRX)XW& diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-310.pyc index da8e69fe1f3bb12e5037220ebb09e193e72e9e36..e4231794582f65b4e5888e3705cbd26da3be6eae 100644 GIT binary patch delta 3009 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 Yl7UOIK}u>NQ%Y9{jNyV-s27X>1H_wA-T(jq diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-310.pyc index a9d4f26d44db4937afc16456672dd9eb8a1bc71f..7686766f725b9c56bd8eb38d110d5908e6262f32 100644 GIT binary patch delta 1007 zcmZuvOK;Oa5Z-lOjvsln={srDN-YgYrIfZH6&0uuNCxsx{OYE)QcwQFnxn_HcRZ8X_9e zpCF=BwG%1l3BH9&sl(5Yia01#w`g_SuxPDP-7{S3wVFnA&v2Ta>Dcbu4g4~W7x>S_ zCZ6GUbh{|K=&%FMm?BMuR**7rc5Tb4kWwUw6UsM~`KfT1zS%M@VtA}l-KLD46Up)W zrcGdx<*$^JnTrq#D}+jHntxT+@f1I!uBe)zvcjo+S6#xh{IxoaQ~bR;vCPD!2P2Kj zHZ>UCX_<^Rs102)+N>~8zbttDn0FoP0mP>HpmrLM@~hgVdQd!0H7wKKrsQ80*JwDP zp$my<-7#$@11zQ3JbaFtT^2|jhn*KLJjE)YAW5K=s^_r1APSASY>j`==EoOAR_M-( ztO#q_Hvza?;NlX`>obyq`I^2Q%}7y+Kh*O$!=LLbn~P#&LO4md2)H2PdMt>Tw#N(+ z`>Xw@080bW2j+?)$|#DXnv#%C6miIu3PHkhYBkfYu@YZQeVHs5nr3s(08Ps5iZutV z3xj~`RV<4sTuYB(qxyC#2Lu@VKMj z8lUnOXC$a(yU1%aBa5KX)pbazq(CC`LP6$)! zkg;IpVYw`OsCO-adIgc`V~m8=91#Y?%s5PS?FQ-+VK+y6V|{cD-7R*hpv@vf9mHP% zD*?mNhvPaD515E-(s6F->PqWoG&X)zwfsh1UdQ3I+I%ii7PLkRWKu=6`qp2_KIyQ zA*aBSAMK@*G9=V%#~$CThp_F&+*D~QDVdZDq+D1ZSc0u>Z>SG~Q`%0ErlYuE_&>TE3&psWg^9X&Dbm(^*-)sA{qbQVKMHM2ljcXns59ca`?9 z?cd(qfyA(U>J)|*tBfbvR@i9x?FOHd$IkauGA6$axw*iP>RkPud@wsAKMzgUD8z}` w@Zt?9fqC3hv99VNQ0@MAVq&ZYA?vifH4KiZ1YjTo6ZNJD&JCCgXr)~3H!5$sIsgCw diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-310.pyc index 83181fadbb311a7fb673f6b0459f8e49806aa8ec..1d113308e9d2af24711897b23082ef94016d5a6b 100644 GIT binary patch delta 1226 zcmZuwOK;so6rS;8{Pw+Rk|q%;DUe85ZPHe)x8lH}u>#RBa>DsN1aMrZE9IL(mT^bnIK!mEOLANo*I|#CB8NFSgDR@1_1cO5z)-zcIh2m|z4}2zw`+H~`QSEE|HrhvfikrUC>2+3LQD1bffWqoV z4)9zY9jA_PY}7kj;%|Deix1USC!uUNQ4wVd8-QS<`Pk6-EErEw0vi#Kt03a4T*vdP zMoefxEo#GESa3Twb(zE51w>8eZ4&BHA0j>_z%i5$@W=Ru^t9ELIY_}(e>cXe(0`WF z9gx20@8k#C9c_ZXf2@6mhtGkVt3L2k3YO$uf>j`u=yEo2T$^Zri}^q<-7Jpt8aW1$WQFGndxk+tT;Es3gRNC-P z&&r0cE8p>$Khf0m@RI-wAR+{?k%0{YqPg1hm-<*V%LDncvozmljHh5=*WkB-!pbyX z8|Rrka2CQ*Dp)eEiXts3C-Ng_8C&ujX9e5x7w7c*s@a_}s;a#IXZV|7_xOjJ9TDfO)^-a zTBL>Iu>|T>>q+n+i0F^-B6u470ebfbm<&=qI0Ik4_g>!nzJweNeXQ5AYSjnks}FtK z*bfeBr{UJY%=iuj3^1IyDTzqQ-NZ|2L`zPRO6o^`$-N{=uwbm@^p;BFI4GFc=}`M3|w-Wg#QX+rtrIlzXhgDX$D0|J+|Er2`xV%r)9o z9ikWd5M2tZb~q7S<)W*sj0Sk2tgBp_k;BRtJYto%A-Bl9f zyV+~0PC?c)k+xKUH?z1~(1pdd=ABzhtNNTbi{Anv6>9 zNZw;D#l^S{DBo%)Ipb24P6yi^-hS9T_WQ?$@N9RVg&_;WwiTBLs>U))%sAFeGsZ=! zisTb{w;)onELVm5Sj0w-n4X3!CT)Mi!bJ;L3=}wtyIf4!xP)n&L?Z7l8zLtRP)MM! zUsh(lnu%5#q5fLA+;MZ++TcZyWE)MX1aGBMTrhRvSU?8M*_9|z+*QK9ihneYg+yoy zcB-_50t_+1j_;hgR#qA(#C845AJa#E9b)~-KM!5~-5}90n1r654$j^zFW25@+44V? bg3g)y$rC;gt(1K+6okva9)5bpO=@50SLZ5-pJ+30RS~o1w8-& delta 19 ZcmX>va9)5bpO=@50SH9IH*&dh001lr1CIaz diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-310.pyc index 6f27589d95c6bbbecfd59236e37b4fc8c87ba32e..f177212a81d863497b3958a1fab243a3cf909b87 100644 GIT binary patch delta 19 ZcmeC+>fqwa=jG*M0D^CiH*)=B0RSua1y}$8 delta 19 YcmeC+>fqwa=jG*M00I&5ja>g&03xpgssI20 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-310.pyc index 17e4b24cbd869d66a25e0f3841770c4c8df71bf0..763a27df295b4a51d999e39ff82e832552ad164f 100644 GIT binary patch delta 1497 zcmZWo%WoS+9Nt;)uDxroch`2(yqY?3(`1v@w3HSoQA&l%Ln@Y_6`-NWax)XN(yZ;y zt|OWng*FkW$1)NZ)GCn>H%{dOg1>=F56Bk|2&Dc42oL^LsyLzo~sy zbGxqVX!7~(=lkvJx7~y2*V`+{wvk3OVz69nV_R{PIdLB66}MO+cCo8?mK9?Ud$Esw zb*!T#3iYWbhG!E^1-v0d&*|(a?IU#riY} z4RIVD(nEBwjeN9yQ);P(5z(+t5Y7-C8zh5GQYIG3?i$!4IhrLl%~5+&&Vf1`7I8>k zYVx*eo1~)j1zI33b!k!B6y?`bw*H1gJmT+~IQTD02{go%Q36uhwGCV*rmS;J{Gq>& zE{Rt&KcbwNGrmU);wPhts`t*Cf1)|q3-`p~-!)v(`CnrIeSzeFh)^ZFVI7vmgZ@J`L~! zz$(BR6`P(!?CUq%nbm-da)!1!Fdqwk=bh}gv0)zZ9p-Z^!q0CM6EY>CA?#tuSS zS|Hw@OZ>g!Ah(b9k&<}>V_@&-ux>e^puvxdFPu}p>UX3b@xXa|YNQNV)zDsT(+>Th z$JaIm&fmIlRtn`6aHFKz6mE^5+iXRw zb%oKY^h%;`CplBS{vlt1u>LT^XotI!^PD*EE^V&?h2am&8&QWeTZ}c=TOAS+xw=HH zO_oAaUIfFZ0mi`E+UWAQmGToHfo?))WUuNr!Cr^v)js9dI1E<$$PBWRWqH6Q6<|3{ zDQW&&D7F}6O`qtMACnGkFup&gUzFm&moi3+M zPOtVO`Q4W{`Vqn>2;yomh<6nN^@QZfTI7`sJIbKWhP`v IcZ2D_0G1+7(*OVf delta 1454 zcmZux%WoS+7~k2K_vu|fVkd6mq;VeJByB2@NDzgz0aX=Jn*&urnj#t3Gcgvsb{N}; zCJg}+gpfd}%ndHdAAnS;ryjT>4oDp60WBx)s7Ee<%6uaMAz*8N{(aB+9<%TuREgoQ&d8sdM77q=GAwyYabX9FI%x#S=*tZ&sz?$CJqv zo{~HppHHUowB$itOJ?v4QmAq~OXp4yp1-D$kmQaOlB2<)hU+{;Wn}O=njB4yTis5t z8>y*(owl2;yRT5z7m9~3p%5LsD|)92Mnu6XL0BUy)=8ci#5~fmK{C`N7R^v=Od%Sz zw@qRbM_3$Nw{=pGc9*)uqaO8zk1u|+(l^+4NR|Xg1`hwuk^>9TMHVPl$Ko9QrViXa2(JPZ zz?wOA=5wHh7&Za$JirFPnIlIUcZQvqGNM#vto7t!UNYI}XU@1D%bw{s+>a>dV-}pvQHo+r``0Zdt zWf}fSP%|x|VK#pdl*NnoZBRol|0S3)$^mQ$6voGhZ71QmIjb;oZQU0ozY^lHJ2Ns;N&K* zDdKVknFV_BnRz9tMR|!iddWGNdP#}JsgrfM7x1|Ob=+dh$xlyDEh-Y2?9U}W`5m`D E0KGCqF8}}l delta 398 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 V%b5s&{J~2ZNFlfHK63ij{{lAPr}O{- delta 7698 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 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-310.pyc index ed2c28c7da23639f385336453a50ba6955445b91..751912d52ca5c52d1a1c32da75ca6d557b702456 100644 GIT binary patch delta 3148 zcma)8TWlOx8J;t@oxSgR?Y;QA-nG}>G+s!nmIevZ#KuvI>zF!8qY-pj_KfYdXD>c8 zPAqH9R<)%nRTJbMQBg`#2l|qSNUdBRK=1;*l_H7&!AMX+UXTzEs8ULKX!!qGZ`_z7 zVe9<+&v(A_&pH2X&X3M+&4=p2pih9myLW!O_?Kflp?>o8&O_h!S9|qdB2a<)&7F4! zTGe5FmhF|D!1(CA5DR#FVh0(j-l7%lZWE>%C7s3UD9o z2e?4VypSK@*T{Qm^s5_2HwO(ea)sN8?buAhKLmQ6yHTcg8W(k6>^OK&0kSO^&>UFF9c>=Wf9%J z|A)G?Kddw;O|mRlDoDaYwzwtiN=Q;})6C%Z}E0p`)!e>^i>NQLMFw!JOn$ zsYXqs*r+s$m)Z$ZEH4@5mAuHl2rp={lOQ2Yyv1VKELm2u$g+U25fsxPuE4NV5CIY) z^1Y3bnTlmk)~i)8T=-ws9gk&Ln2jujc9I~%#A;e`*PGWGr(gkh7VGM8F`QE8rL)I44~{u z6i8-Ip_t{r4CcdELABx_0-gW~i7$udTfc%Q3>oveA@kW#LR;i{;$m@-P);i%ivunp zZp*uH91N(f+MX>qJa9BN(Uf+*SYq2~O`8(7+Cj$x6l}EZ-y+Ka_zl7c!3e{MG|x*^ zyQ(04QwAW)W}3ooR}=J`qKgRZ0wA#tQu6|fup(gH9SroIwho($gIB#g9De*u?6YvR zjT0FAPX6DohyS|}_;mPl3d3mg=fdO4TcCWvZ--aOc|H^wCVTv3WId5!lYp}+6cH2! z6hZ#G$Z)b7R7W$`%jOz2EJs~yV6L++9*SN|gkdtTd?Iw`aAA?}MTZk_fNDJkB0w|} z5k(?GD*I%9C;E9}^1-g_u!Wy=r4$_~zvfQY(x8cpu{PS}a8MH!z~1FwkDVfQ{)5DMYmON5pL&=zci6hU(={;VlF9d&JjysrxtTc~mWayeC8c%D>w4D(viT&(N_Z zz<-BfVUOs=1eZ++#wRR32NUhGT>|ZWJ{^CLSUj2d16k$&O!R;qPjb*b;Ya*P@-_9F z$bXu@lY9gS_mXKKr&AU30e>;ooSer=ta?YPmKu4r?bZXQxMi_}BnyS>o^PS%_Ki!R z{bTP;?_(s0(Po<<@&r!xQeQtw@>_jBjbPz88Y^8c)=E`_t@2C#IS9q|{zU4);(^y! zfF9%T_J5`C1{!=F!~+clx9Z`?2c{q1uN%2tH8(|UAydNFRA?U1EViK5R>!e@=G9rZ zRj^n1TLUqEE}WX8P;TAA1^5K6Lg4~M{5P4Hbq{w-WEdEStRK#YX8?W#dJek?%ElLX zXz)=!o6#oniX)ju%~2~g%V0L^!R7LDy;5U%_Kr*2$KlPvqsprQkMrAuS5)k~Y@VMS zinXe!V$Lzl6NaH>*f|;cn4w!3u5*I>{kv?KW~Ya{?mLYXH!7o`%3_YCM@9Bmd%0r0vuRXu|3;wBTiR zQQY)2B{tXe>`JzWzn4xus-q5bzQ#rB$1Vr$MyA?|!WQ>u{0-yK4C6z?FDWbl@8fR| zPmW^#KZ|A6?yhre@hCX#dO+@kK%0*uqWII%b;-AxSKnmPvXRbYuFxQ z$3Qp=U8^=M$fARqyfKcmSUrwhslhD;Uvt=B*8yALe;&!JsO3MygQF|Y4#4%G0N$w4 zIx95X`(mZGSm?M1gP})VPNfF@wpKC=WwXM9h!6c2Ucj5?da>NTBd`#Eb95w)-PuV# z$c093xHlw=Mfk~FzZwM+bn|lV$XpEhy$|x&?22g>z;2^tGxu9?$Y7gLtypEZ+}uKA zb7(ZlujR6E2?ezmMU7|2a_!Jv=V!-qr|>eQ2^tBI5fTss?Ey~_81BsnG5B<7KA#kk QgqF|}dpcDT$Eun54{r?eJpcdz delta 2792 zcmZuzeP|rV72nyf+x!03Y47xT`aH!}>=dV^IL5M6J4sc=%{3n^NtE@?SX$}6Ji8)l zIHA@ub(7Xj-LV2mC`h3MlF9hlOFt--LJR%36yv&mZ?Cc|(Oc%X zZ+`E+nKy6V%-&Y@{l^lmcswG(FIV{Wl6U|0L?3zX`hD9`B2kG(>%~UNy8cQ3X3$O4 zhZ|+99LUM~NMqC*ZH!rCL}D8M3Ye$rg663wvEmSRn^Fqb@_^=7e-nrzS04QLX!F>8|NC zuzj>2*khDbrOJS~OjgA|$;lz&$LF2q>TIiCXEm?ID?psLYpeDWJL@zl6A#EU(a3qH zU1hH8w3?zVSF&J~opW4|I~UeGAfIG>?>)Ieh$+hIIw^=Z)TzzWkSq5u08Fw7l`NSO zOQEu*QpM8f5Y=f2;?b$WLNv?_s*8n8uL0yancAdnyw2&R8OsK8=? z4uVCVYLL`nKRORdnQb*1c9ZV?Ui*zg&WQKIXZ9Y9JWWVUyb^thJRr=NqY?d<9u`+) z3spblb`x7uAXWQ64Fnb1EHrltz>`);NA3_xuE`sUCsUAD6skZ^^;FO)9hIurWC%kO zgNZMQtBL9fjiunD{s|+}i`9Z?N@ReT_2L*Vo#CMOOSP^R06UP##F@ zqv-fV;L`4%DVL8R7r-bg6u#Dc9Rzn8AVv%lk%gcAEUAfn?z@BYXrfX)Y6t!JdC+_$ zZswNt8c2Lb+#Jtp&x81(cq)H}TokY8&+1F4a!{2-`=4QV72w4q;@O^FG1QaS>&P|H zBw~a3Q|z|H(>=e`ac;gMjupz}SE5>Y4HEVD!l32?{X3EF&6-U#2*P>+C0q_)1o(w` zsP`sW5lQp6g=OgbamQW6vSW2-yR0Jfd2z=a&@iOGiQ(cK`Wm`EEPh=46j>JkC=P*h zq2!Q1i?5bCvyY%s$8nT~-LB}}vhA)KRYC239i@&=?{CS`yM3m&m-vp zR0ynVsFFA8cH;uIPld%!|Bq6=pz#fEzp&V}8;mcD#=y9FcN*9Q+p~Rrnc0+a@W*^# z02ft!Jn+TRHje!&z=30oQ5)je;Mq+NPA3+BN8OTlp>~PXQRbv)^$pF_I@%T-pi7ff zf@;+lIKi>50o)=(HSFyFP?n)pp}7VCB^@b;Uh={%ax_>vT+L+taIt&??}1TpchTLD zUOXv&J~TBqeX`!F*>(362;EFnbYH2nrms6qmvN65z}#0?T27O{3?j!I?e9Q$$>Q?R z5$)SRn__S1rE__-!s~?x+lKcTF9Z0B)ATsS?(+yX0u~Eb5pb6{W|QMkd<3&w83SINGefvl|&Tz37N?M4w@XfQ_RYv;*;U?$;2Iw4!+u6U2-`SQ{@SATRdL&`e!!u zj=lo-6JThIEXf<8j=~@Bgmx597k@09C!RqWw2`(&qj;OawW3mERpZWoHPQCcA&n=F zj(juhhv3^6d>20)nayE^L2*5YFQ{^O@z;VvSpf0VVtn+mhjCvmV;=I3A5JU$NYnLf z`1W#Ns>Jz|p!IdO?y)BI6}$OmU$@(B=xolu=W8LjjSG!MgGb%&@J{7qEO zAiOG~V`F4n93LCdUIAiCd}*vam{L?ZMPdXof(_)DY{(oNS^hcA~G)U8&U0SSlzr{Q* z{xmU45<;IGAW5_k$)p~w?f>cFDRDb7Ig-YZdJc}+V4jU9pX1k%XT`b6DUyQ`MmDk3 z{o+Au_%~E{r(xE%?eXAS(fj`l8jf2F&Q@@stkOZ7{VAs}z-`G*oVSR;aKi8s^X6Mi zOHACJH1%NDZirH4eC{-84atE09EBZ)2X{7jaKG_M!L9?!MkJ!76lqi1l(qe%)PqOq G=zjn!E1t~& diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-310.pyc index be0e37314018a0380cbdfb9fc521984e4eb38412..49e4e922c2cee6cea2598975974a10054a612595 100644 GIT binary patch delta 1138 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 RHlc3Wr_5lVFf;w}e*jeQRoDOk diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc index 2800df941e362e01479f2f01469f0f924aeb8fca..45dcbd706f362a0863a1cad18dd4bddc01822155 100644 GIT binary patch delta 857 zcmZva&ubGw6vyXnHk<5jvPrY~-Izju8VeDt7p)-0Vi7D_1P@Ck#LP5qvzye}O-Ug= zlomv!hcf>_auU4u;?Y0AgOnn&f*1b)Z@mf5Y(WpY3m?Awoi}gZdpifEpCzN0OlpWf z7eCJ1w^AoY1wNcCZfpU<2*;hIYgk68RVU@9t#qh0XTr@`nNaJF>1M60o3nD^cf!fL z1*_l|t)g49N`MF&mC587tjZd~No*V;Y!Hnk4rS}g$@ld<1m;uXd3LXRzvsHmE?&0> zc9%Va{$wO5wqBA}r$Gijq1~qA>@|2qvrRDj1lQOKDv=v3JpWWwN(RD77*9-x250t1!cUMO#XZ@9^f?mNF-$ zfxT58N(!(q%KObBZ0nxoCk_!HKZ#>Qd6$pvSe!49j4@h8&&_>hsBEWrWSZABfz^(T zwPR^t9jbINR7aUH-}{R2brb6yi5~dbFk6m&j@dBJ?!?~|^MTnWegl)OX5aA}-sQZg z&c4O3mouU#@egT2Koyu0NV2k8xn1TmPvk8D zK|?ge?+uNyx?V6mzv=fqZerrmI2-F#P}xVl02=$M&nmhoA;E2PweQ=GS9fi%MU%oc o1jIxFl~4OouifT%X}bBjyWJn%)wcA<*0L71#UEg`pa*|KkrqWHAaUJHm$XT?oyit| zq=>W^4?UDQdE32u5TsuHFDyt-UiISLOFJ(IrI;|EeDmJpJMRtiyY{YTbxl)4;wg=O z>pZs(tug%NaDMG=VA>`|E^@QJ73Az(s#QN96zoE(HGd>1+Qn4sekmy1<)C6$(tpDr z4XSn(BZB%ha&Ca_^Y@Tzy4F5&Eus-)PqxQg{0KF2KVk2O4V)-XT7Hi(q2v{h9iA*= zi7(unUxIGbidgz0eC;)bf40z<;TiYEw{>Vp^yqLwn(}5bPB2f{G!41kH8Oxd`PmHGV#yDTn_b(*lTi#aF z5jKQ|Ex+0Jy{72Zf#F)AONYTb%YW$gYcO6?JzGv*w#il`PL5I7BPpCs3n!}cWuvYb s;A8T2V`9OALRFmpO1IM?lwOC_A^`gRZxH^~n9k?1k-p+9Yf>e13ad-H2LJ#7 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-310.pyc index 4cf795aed1491c95d3f9d2333d6baef3d42e2ce8..0c6d719a7cc736b2e49f335efda811a09e7c8189 100644 GIT binary patch delta 1249 zcmYLI&2Jk;6rZ=dUfb*4^~O%zeAuy*wt9KzRS0u#2;()}NE2kpyX4AA@`OWXW_j@1nX6DP4 zpI2<(vJ8U1fB*iyVb2}gMfl_RrEl(a3e^G-k9e8(xz22Lwli0qi*>U--&v?G#Mo*V zJEdx=vshgOLdmF1D`TiGy+b_P%YH??EHwveb@}+ow^x)&?oK!0wRZbM+TU$5+M!)O zDb=@WeaCInMy(Q0R8i;d@RR|v5B}ag`68t35fx(wX%TmX9oF(tn^4et!Qq zAfW@~AkQz1E_!dLk+dS5v5LFOp7pj#KE}HhI$t>b2dC>E>=FKg$PU0Wc2xE!f6>bf z;0XAo=mYa6T#LRpKPugpM}7^(B(t|oY1^&W@B%S;C```thu$%UX}LO zqU+Xsa5?(LdijDa4bxIsl4s!+q|B}RxZLMVJ_DAG%655%nG$P~l#Xk-UXw*{*~RsD zvHs+{mP9g$#=m%uPg-G6(@Wfe?ydy+}MvXbHUXfYev^G~V`x5D(!u?2Xq+oa<6%>wf;ux#xW6+++KfrK2S~ zuq=b%RVe=1`MLDKuD~A;R=&Ot#3gRVKi@Aliv3cf6x*gh+b=iDF}M7=ex*_AR~uCz z9vRPj3lnJ6t`XOEvtJN5>zPBfv3LyM0*LRRaPkD6CGzL6(o}D?SvMHaA{w+Lo+P(3 zbCRCgC#$J10j`M0>1Jjb-C+YkSHwl*;o+}92qR7y%tWtc5*J*>RYz)+L^YeEGS^U1i&C8QvK)2z zq0UuwqM)mx({U4{RFpd8T)M zT%3?i@^K-uxYaAskf+D9+>-Ho+pNs3AyCfE@!Xm3kX5)D7pa;A%gpb7)sfGI-ETU? zO^p(_l*o><+(yy0ShPkTqI9iS3V*yo?gR40@F&Uc8LU2jN!pm7nkYcF$lkF=*oA|q zKq3doy*zt)yyT`a<|20{Do*Wk_Nnk)Ncgh&v-f4CRA#3@5^Y-1Y?>0MraJ%J;->la+H5rtSRhw>?PVGAZ?YCI7 z9Sj%^d}>L>yaZE5THb(pG~V?-WmNtM)E1V#Al|Vnq-W_;I!XpGjF%(m=!Bh-filT#pxBlGG#iFw+ZaVKlPCRnf z;VtpEQ-Aw~)c<;P24&FNY0?imo$jDR=TA0f%Aib3;`3Y~ z)9;4ucz)CpJXZ%>JjyM;8J|6#M!Ms%4=@wQ6`(S0Nsz@(&+?*`HStgGHPZwK None: - self.cmd_opts.add_option( "--format", action="store", @@ -94,24 +94,30 @@ class CacheCommand(Command): num_http_files = len(self._find_http_files(options)) num_packages = len(self._find_wheels(options, "*")) - http_cache_location = self._cache_dir(options, "http") + http_cache_location = self._cache_dir(options, "http-v2") + old_http_cache_location = self._cache_dir(options, "http") wheels_cache_location = self._cache_dir(options, "wheels") - http_cache_size = filesystem.format_directory_size(http_cache_location) + http_cache_size = filesystem.format_size( + filesystem.directory_size(http_cache_location) + + filesystem.directory_size(old_http_cache_location) + ) wheels_cache_size = filesystem.format_directory_size(wheels_cache_location) message = ( textwrap.dedent( """ - Package index page cache location: {http_cache_location} + Package index page cache location (pip v23.3+): {http_cache_location} + Package index page cache location (older pips): {old_http_cache_location} Package index page cache size: {http_cache_size} Number of HTTP files: {num_http_files} Locally built wheels location: {wheels_cache_location} Locally built wheels size: {wheels_cache_size} Number of locally built wheels: {package_count} - """ + """ # noqa: E501 ) .format( http_cache_location=http_cache_location, + old_http_cache_location=old_http_cache_location, http_cache_size=http_cache_size, num_http_files=num_http_files, wheels_cache_location=wheels_cache_location, @@ -152,14 +158,8 @@ class CacheCommand(Command): logger.info("\n".join(sorted(results))) def format_for_abspath(self, files: List[str]) -> None: - if not files: - return - - results = [] - for filename in files: - results.append(filename) - - logger.info("\n".join(sorted(results))) + if files: + logger.info("\n".join(sorted(files))) def remove_cache_items(self, options: Values, args: List[Any]) -> None: if len(args) > 1: @@ -176,15 +176,17 @@ class CacheCommand(Command): files += self._find_http_files(options) else: # Add the pattern to the log message - no_matching_msg += ' for pattern "{}"'.format(args[0]) + no_matching_msg += f' for pattern "{args[0]}"' if not files: logger.warning(no_matching_msg) + bytes_removed = 0 for filename in files: + bytes_removed += os.stat(filename).st_size os.unlink(filename) logger.verbose("Removed %s", filename) - logger.info("Files removed: %s", len(files)) + logger.info("Files removed: %s (%s)", len(files), format_size(bytes_removed)) def purge_cache(self, options: Values, args: List[Any]) -> None: if args: @@ -196,8 +198,11 @@ class CacheCommand(Command): return os.path.join(options.cache_dir, subdir) def _find_http_files(self, options: Values) -> List[str]: - http_dir = self._cache_dir(options, "http") - return filesystem.find_files(http_dir, "*") + old_http_dir = self._cache_dir(options, "http") + new_http_dir = self._cache_dir(options, "http-v2") + return filesystem.find_files(old_http_dir, "*") + filesystem.find_files( + new_http_dir, "*" + ) def _find_wheels(self, options: Values, pattern: str) -> List[str]: wheel_dir = self._cache_dir(options, "wheels") diff --git a/venv/Lib/site-packages/pip/_internal/commands/check.py b/venv/Lib/site-packages/pip/_internal/commands/check.py index 3864220..f54a16d 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/check.py +++ b/venv/Lib/site-packages/pip/_internal/commands/check.py @@ -4,10 +4,13 @@ from typing import List from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.metadata import get_default_environment from pip._internal.operations.check import ( check_package_set, + check_unsupported, create_package_set_from_installed, ) +from pip._internal.utils.compatibility_tags import get_supported from pip._internal.utils.misc import write_output logger = logging.getLogger(__name__) @@ -16,13 +19,19 @@ logger = logging.getLogger(__name__) class CheckCommand(Command): """Verify installed packages have compatible dependencies.""" + ignore_require_venv = True usage = """ %prog [options]""" def run(self, options: Values, args: List[str]) -> int: - package_set, parsing_probs = create_package_set_from_installed() missing, conflicting = check_package_set(package_set) + unsupported = list( + check_unsupported( + get_default_environment().iter_installed_distributions(), + get_supported(), + ) + ) for project_name in missing: version = package_set[project_name].version @@ -45,8 +54,13 @@ class CheckCommand(Command): dep_name, dep_version, ) - - if missing or conflicting or parsing_probs: + for package in unsupported: + write_output( + "%s %s is not supported on this platform", + package.raw_name, + package.version, + ) + if missing or conflicting or parsing_probs or unsupported: return ERROR else: write_output("No broken requirements found.") diff --git a/venv/Lib/site-packages/pip/_internal/commands/completion.py b/venv/Lib/site-packages/pip/_internal/commands/completion.py index deaa308..9e89e27 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/completion.py +++ b/venv/Lib/site-packages/pip/_internal/commands/completion.py @@ -22,15 +22,19 @@ COMPLETION_SCRIPTS = { complete -o default -F _pip_completion {prog} """, "zsh": """ - function _pip_completion {{ - local words cword - read -Ac words - read -cn cword - reply=( $( COMP_WORDS="$words[*]" \\ - COMP_CWORD=$(( cword-1 )) \\ - PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) + #compdef -P pip[0-9.]# + __pip() {{ + compadd $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$((CURRENT-1)) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null ) }} - compctl -K _pip_completion {prog} + if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + __pip "$@" + else + # eval/source/. command, register function for later + compdef __pip -P 'pip[0-9.]#' + fi """, "fish": """ function __fish_complete_pip diff --git a/venv/Lib/site-packages/pip/_internal/commands/configuration.py b/venv/Lib/site-packages/pip/_internal/commands/configuration.py index e383732..1a1dc6b 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/configuration.py +++ b/venv/Lib/site-packages/pip/_internal/commands/configuration.py @@ -228,25 +228,29 @@ class ConfigurationCommand(Command): fname = self.configuration.get_file_to_edit() if fname is None: raise PipError("Could not determine appropriate file.") + elif '"' in fname: + # This shouldn't happen, unless we see a username like that. + # If that happens, we'd appreciate a pull request fixing this. + raise PipError( + f'Can not open an editor for a file name containing "\n{fname}' + ) try: - subprocess.check_call([editor, fname]) + subprocess.check_call(f'{editor} "{fname}"', shell=True) except FileNotFoundError as e: if not e.filename: e.filename = editor raise except subprocess.CalledProcessError as e: - raise PipError( - "Editor Subprocess exited with exit code {}".format(e.returncode) - ) + raise PipError(f"Editor Subprocess exited with exit code {e.returncode}") def _get_n_args(self, args: List[str], example: str, n: int) -> Any: """Helper to make sure the command got the right number of arguments""" if len(args) != n: msg = ( - "Got unexpected number of arguments, expected {}. " - '(example: "{} config {}")' - ).format(n, get_prog(), example) + f"Got unexpected number of arguments, expected {n}. " + f'(example: "{get_prog()} config {example}")' + ) raise PipError(msg) if n == 1: diff --git a/venv/Lib/site-packages/pip/_internal/commands/debug.py b/venv/Lib/site-packages/pip/_internal/commands/debug.py index 6fad1fe..567ca96 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/debug.py +++ b/venv/Lib/site-packages/pip/_internal/commands/debug.py @@ -1,4 +1,3 @@ -import importlib.resources import locale import logging import os @@ -17,6 +16,7 @@ from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.status_codes import SUCCESS from pip._internal.configuration import Configuration from pip._internal.metadata import get_environment +from pip._internal.utils.compat import open_text_resource from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import get_pip_version @@ -35,7 +35,7 @@ def show_sys_implementation() -> None: def create_vendor_txt_map() -> Dict[str, str]: - with importlib.resources.open_text("pip._vendor", "vendor.txt") as f: + with open_text_resource("pip._vendor", "vendor.txt") as f: # Purge non version specifying lines. # Also, remove any space prefix or suffixes (including comments). lines = [ @@ -46,22 +46,29 @@ def create_vendor_txt_map() -> Dict[str, str]: return dict(line.split("==", 1) for line in lines) -def get_module_from_module_name(module_name: str) -> ModuleType: +def get_module_from_module_name(module_name: str) -> Optional[ModuleType]: # Module name can be uppercase in vendor.txt for some reason... - module_name = module_name.lower() + module_name = module_name.lower().replace("-", "_") # PATCH: setuptools is actually only pkg_resources. if module_name == "setuptools": module_name = "pkg_resources" - __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) - return getattr(pip._vendor, module_name) + try: + __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) + return getattr(pip._vendor, module_name) + except ImportError: + # We allow 'truststore' to fail to import due + # to being unavailable on Python 3.9 and earlier. + if module_name == "truststore" and sys.version_info < (3, 10): + return None + raise def get_vendor_version_from_module(module_name: str) -> Optional[str]: module = get_module_from_module_name(module_name) version = getattr(module, "__version__", None) - if not version: + if module and not version: # Try to find version in debundled module info. assert module.__file__ is not None env = get_environment([os.path.dirname(module.__file__)]) @@ -88,7 +95,7 @@ def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None: elif parse_version(actual_version) != parse_version(expected_version): extra_message = ( " (CONFLICT: vendor.txt suggests version should" - " be {})".format(expected_version) + f" be {expected_version})" ) logger.info("%s==%s%s", module_name, actual_version, extra_message) @@ -105,7 +112,7 @@ def show_tags(options: Values) -> None: tag_limit = 10 target_python = make_target_python(options) - tags = target_python.get_tags() + tags = target_python.get_sorted_tags() # Display the target options that were explicitly provided. formatted_target = target_python.format_given() @@ -113,7 +120,7 @@ def show_tags(options: Values) -> None: if formatted_target: suffix = f" (target: {formatted_target})" - msg = "Compatible tags: {}{}".format(len(tags), suffix) + msg = f"Compatible tags: {len(tags)}{suffix}" logger.info(msg) if options.verbose < 1 and len(tags) > tag_limit: @@ -127,17 +134,12 @@ def show_tags(options: Values) -> None: logger.info(str(tag)) if tags_limited: - msg = ( - "...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" - ).format(tag_limit=tag_limit) + msg = f"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" logger.info(msg) def ca_bundle_info(config: Configuration) -> str: - levels = set() - for key, _ in config.items(): - levels.add(key.split(".")[0]) - + levels = {key.split(".", 1)[0] for key, _ in config.items()} if not levels: return "Not specified" diff --git a/venv/Lib/site-packages/pip/_internal/commands/download.py b/venv/Lib/site-packages/pip/_internal/commands/download.py index 26a5080..917bbb9 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/download.py +++ b/venv/Lib/site-packages/pip/_internal/commands/download.py @@ -8,6 +8,7 @@ from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.req.req_install import check_legacy_setup_py_options from pip._internal.utils.misc import ensure_dir, normalize_path, write_output from pip._internal.utils.temp_dir import TempDirectory @@ -75,7 +76,6 @@ class DownloadCommand(RequirementCommand): @with_cleanup def run(self, options: Values, args: List[str]) -> int: - options.ignore_installed = True # editable doesn't really make sense for `pip download`, but the bowels # of the RequirementSet code require that property. @@ -105,6 +105,7 @@ class DownloadCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) preparer = self.make_requirement_preparer( temp_build_dir=directory, @@ -136,6 +137,9 @@ class DownloadCommand(RequirementCommand): assert req.name is not None preparer.save_linked_requirement(req) downloaded.append(req.name) + + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + if downloaded: write_output("Successfully downloaded %s", " ".join(downloaded)) diff --git a/venv/Lib/site-packages/pip/_internal/commands/freeze.py b/venv/Lib/site-packages/pip/_internal/commands/freeze.py index 5fa6d39..885fdfe 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/freeze.py +++ b/venv/Lib/site-packages/pip/_internal/commands/freeze.py @@ -1,6 +1,6 @@ import sys from optparse import Values -from typing import List +from typing import AbstractSet, List from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command @@ -8,7 +8,18 @@ from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.freeze import freeze from pip._internal.utils.compat import stdlib_pkgs -DEV_PKGS = {"pip", "setuptools", "distribute", "wheel"} + +def _should_suppress_build_backends() -> bool: + return sys.version_info < (3, 12) + + +def _dev_pkgs() -> AbstractSet[str]: + pkgs = {"pip"} + + if _should_suppress_build_backends(): + pkgs |= {"setuptools", "distribute", "wheel"} + + return pkgs class FreezeCommand(Command): @@ -18,6 +29,7 @@ class FreezeCommand(Command): packages are listed in a case-insensitive sorted order. """ + ignore_require_venv = True usage = """ %prog [options]""" log_streams = ("ext://sys.stderr", "ext://sys.stderr") @@ -61,7 +73,7 @@ class FreezeCommand(Command): action="store_true", help=( "Do not skip these packages in the output:" - " {}".format(", ".join(DEV_PKGS)) + " {}".format(", ".join(_dev_pkgs())) ), ) self.cmd_opts.add_option( @@ -77,7 +89,7 @@ class FreezeCommand(Command): def run(self, options: Values, args: List[str]) -> int: skip = set(stdlib_pkgs) if not options.freeze_all: - skip.update(DEV_PKGS) + skip.update(_dev_pkgs()) if options.excludes: skip.update(options.excludes) diff --git a/venv/Lib/site-packages/pip/_internal/commands/index.py b/venv/Lib/site-packages/pip/_internal/commands/index.py index b4bf0ac..2e2661b 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/index.py +++ b/venv/Lib/site-packages/pip/_internal/commands/index.py @@ -1,8 +1,8 @@ import logging from optparse import Values -from typing import Any, Iterable, List, Optional, Union +from typing import Any, Iterable, List, Optional -from pip._vendor.packaging.version import LegacyVersion, Version +from pip._vendor.packaging.version import Version from pip._internal.cli import cmdoptions from pip._internal.cli.req_command import IndexGroupCommand @@ -24,6 +24,7 @@ class IndexCommand(IndexGroupCommand): Inspect information available from package indexes. """ + ignore_require_venv = True usage = """ %prog versions """ @@ -114,7 +115,7 @@ class IndexCommand(IndexGroupCommand): ignore_requires_python=options.ignore_requires_python, ) - versions: Iterable[Union[LegacyVersion, Version]] = ( + versions: Iterable[Version] = ( candidate.version for candidate in finder.find_all_candidates(query) ) @@ -127,12 +128,12 @@ class IndexCommand(IndexGroupCommand): if not versions: raise DistributionNotFound( - "No matching distribution found for {}".format(query) + f"No matching distribution found for {query}" ) formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)] latest = formatted_versions[0] - write_output("{} ({})".format(query, latest)) + write_output(f"{query} ({latest})") write_output("Available versions: {}".format(", ".join(formatted_versions))) print_dist_installation_info(query, latest) diff --git a/venv/Lib/site-packages/pip/_internal/commands/inspect.py b/venv/Lib/site-packages/pip/_internal/commands/inspect.py index a4e3599..e810c13 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/inspect.py +++ b/venv/Lib/site-packages/pip/_internal/commands/inspect.py @@ -7,7 +7,7 @@ from pip._vendor.rich import print_json from pip import __version__ from pip._internal.cli import cmdoptions -from pip._internal.cli.req_command import Command +from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import SUCCESS from pip._internal.metadata import BaseDistribution, get_environment from pip._internal.utils.compat import stdlib_pkgs @@ -46,11 +46,6 @@ class InspectCommand(Command): self.parser.insert_option_group(0, self.cmd_opts) def run(self, options: Values, args: List[str]) -> int: - logger.warning( - "pip inspect is currently an experimental command. " - "The output format may change in a future release without prior warning." - ) - cmdoptions.check_list_path_option(options) dists = get_environment(options.path).iter_installed_distributions( local_only=options.local, @@ -58,7 +53,7 @@ class InspectCommand(Command): skip=set(stdlib_pkgs), ) output = { - "version": "0", + "version": "1", "pip_version": __version__, "installed": [self._dist_to_dict(dist) for dist in dists], "environment": default_environment(), diff --git a/venv/Lib/site-packages/pip/_internal/commands/install.py b/venv/Lib/site-packages/pip/_internal/commands/install.py index 2990764..232a34a 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/install.py +++ b/venv/Lib/site-packages/pip/_internal/commands/install.py @@ -5,37 +5,46 @@ import os import shutil import site from optparse import SUPPRESS_HELP, Values -from typing import Iterable, List, Optional +from typing import List, Optional from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.rich import print_json +# Eagerly import self_outdated_check to avoid crashes. Otherwise, +# this module would be imported *after* pip was replaced, resulting +# in crashes if the new self_outdated_check module was incompatible +# with the rest of pip that's already imported, or allowing a +# wheel to execute arbitrary code on install by replacing +# self_outdated_check. +import pip._internal.self_outdated_check # noqa: F401 from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import ( RequirementCommand, - warn_if_run_as_root, with_cleanup, ) from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.exceptions import CommandError, InstallationError from pip._internal.locations import get_scheme from pip._internal.metadata import get_environment -from pip._internal.models.format_control import FormatControl from pip._internal.models.installation_report import InstallationReport from pip._internal.operations.build.build_tracker import get_build_tracker from pip._internal.operations.check import ConflictDetails, check_install_conflicts from pip._internal.req import install_given_reqs -from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_install import ( + InstallRequirement, + check_legacy_setup_py_options, +) from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.distutils_args import parse_distutils_args from pip._internal.utils.filesystem import test_writable_dir from pip._internal.utils.logging import getLogger from pip._internal.utils.misc import ( + check_externally_managed, ensure_dir, get_pip_version, protect_pip_from_modification_on_windows, + warn_if_run_as_root, write_output, ) from pip._internal.utils.temp_dir import TempDirectory @@ -43,24 +52,11 @@ from pip._internal.utils.virtualenv import ( running_under_virtualenv, virtualenv_no_global, ) -from pip._internal.wheel_builder import ( - BinaryAllowedPredicate, - build, - should_build_for_install_command, -) +from pip._internal.wheel_builder import build, should_build_for_install_command logger = getLogger(__name__) -def get_check_binary_allowed(format_control: FormatControl) -> BinaryAllowedPredicate: - def check_binary_allowed(req: InstallRequirement) -> bool: - canonical_name = canonicalize_name(req.name or "") - allowed_formats = format_control.get_allowed_formats(canonical_name) - return "binary" in allowed_formats - - return check_binary_allowed - - class InstallCommand(RequirementCommand): """ Install packages from: @@ -145,7 +141,12 @@ class InstallCommand(RequirementCommand): default=None, help=( "Installation prefix where lib, bin and other top-level " - "folders are placed" + "folders are placed. Note that the resulting installation may " + "contain scripts and other resources which reference the " + "Python interpreter of pip, and not that of ``--prefix``. " + "See also the ``--python`` option if the intention is to " + "install packages into another (possibly pip-free) " + "environment." ), ) @@ -204,9 +205,9 @@ class InstallCommand(RequirementCommand): self.cmd_opts.add_option(cmdoptions.use_pep517()) self.cmd_opts.add_option(cmdoptions.no_use_pep517()) self.cmd_opts.add_option(cmdoptions.check_build_deps()) + self.cmd_opts.add_option(cmdoptions.override_externally_managed()) self.cmd_opts.add_option(cmdoptions.config_settings()) - self.cmd_opts.add_option(cmdoptions.install_options()) self.cmd_opts.add_option(cmdoptions.global_options()) self.cmd_opts.add_option( @@ -263,7 +264,9 @@ class InstallCommand(RequirementCommand): "the provided requirements. " "Can be used in combination with --dry-run and --ignore-installed " "to 'resolve' the requirements. " - "When - is used as file name it writes to stdout." + "When - is used as file name it writes to stdout. " + "When writing to stdout, please combine with the --quiet option " + "to avoid mixing pip logging output with JSON output." ), ) @@ -272,15 +275,29 @@ class InstallCommand(RequirementCommand): if options.use_user_site and options.target_dir is not None: raise CommandError("Can not combine '--user' and '--target'") - cmdoptions.check_install_build_global(options) + # Check whether the environment we're installing into is externally + # managed, as specified in PEP 668. Specifying --root, --target, or + # --prefix disables the check, since there's no reliable way to locate + # the EXTERNALLY-MANAGED file for those cases. An exception is also + # made specifically for "--dry-run --report" for convenience. + installing_into_current_environment = ( + not (options.dry_run and options.json_report_file) + and options.root_path is None + and options.target_dir is None + and options.prefix_path is None + ) + if ( + installing_into_current_environment + and not options.override_externally_managed + ): + check_externally_managed() + upgrade_strategy = "to-satisfy-only" if options.upgrade: upgrade_strategy = options.upgrade_strategy cmdoptions.check_dist_restriction(options, check_target=True) - install_options = options.install_options or [] - logger.verbose("Using %s", get_pip_version()) options.use_user_site = decide_user_install( options.use_user_site, @@ -321,8 +338,6 @@ class InstallCommand(RequirementCommand): target_python=target_python, ignore_requires_python=options.ignore_requires_python, ) - wheel_cache = WheelCache(options.cache_dir, options.format_control) - build_tracker = self.enter_context(get_build_tracker()) directory = TempDirectory( @@ -333,6 +348,9 @@ class InstallCommand(RequirementCommand): try: reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) + + wheel_cache = WheelCache(options.cache_dir) # Only when installing is it permitted to use PEP 660. # In other circumstances (pip wheel, pip download) we generate @@ -340,8 +358,6 @@ class InstallCommand(RequirementCommand): for req in reqs: req.permit_editable_wheels = True - reject_location_related_install_options(reqs, options.install_options) - preparer = self.make_requirement_preparer( temp_build_dir=directory, options=options, @@ -362,6 +378,7 @@ class InstallCommand(RequirementCommand): force_reinstall=options.force_reinstall, upgrade_strategy=upgrade_strategy, use_pep517=options.use_pep517, + py_version_info=options.python_version, ) self.trace_basic_info(finder) @@ -371,12 +388,6 @@ class InstallCommand(RequirementCommand): ) if options.json_report_file: - logger.warning( - "--report is currently an experimental option. " - "The output format may change in a future release " - "without prior warning." - ) - report = InstallationReport(requirement_set.requirements_to_install) if options.json_report_file == "-": print_json(data=report.to_dict()) @@ -406,12 +417,10 @@ class InstallCommand(RequirementCommand): modifying_pip = pip_req.satisfied_by is None protect_pip_from_modification_on_windows(modifying_pip=modifying_pip) - check_binary_allowed = get_check_binary_allowed(finder.format_control) - reqs_to_build = [ r for r in requirement_set.requirements.values() - if should_build_for_install_command(r, check_binary_allowed) + if should_build_for_install_command(r) ] _, build_failures = build( @@ -419,29 +428,17 @@ class InstallCommand(RequirementCommand): wheel_cache=wheel_cache, verify=True, build_options=[], - global_options=[], + global_options=global_options, ) - # If we're using PEP 517, we cannot do a legacy setup.py install - # so we fail here. - pep517_build_failure_names: List[str] = [ - r.name for r in build_failures if r.use_pep517 # type: ignore - ] - if pep517_build_failure_names: + if build_failures: raise InstallationError( - "Could not build wheels for {}, which is required to " - "install pyproject.toml-based projects".format( - ", ".join(pep517_build_failure_names) + "Failed to build installable wheels for some " + "pyproject.toml based projects ({})".format( + ", ".join(r.name for r in build_failures) # type: ignore ) ) - # For now, we just warn about failures building legacy - # requirements, as we'll fall through to a setup.py install for - # those. - for r in build_failures: - if not r.use_pep517: - r.legacy_install_reason = 8368 - to_install = resolver.get_installation_order(requirement_set) # Check for conflicts in the package set we're installing. @@ -460,7 +457,6 @@ class InstallCommand(RequirementCommand): installed = install_given_reqs( to_install, - install_options, global_options, root=options.root_path, home=target_temp_dir_path, @@ -479,17 +475,21 @@ class InstallCommand(RequirementCommand): ) env = get_environment(lib_locations) + # Display a summary of installed packages, with extra care to + # display a package name as it was requested by the user. installed.sort(key=operator.attrgetter("name")) - items = [] - for result in installed: - item = result.name - try: - installed_dist = env.get_distribution(item) - if installed_dist is not None: - item = f"{item}-{installed_dist.version}" - except Exception: - pass - items.append(item) + summary = [] + installed_versions = {} + for distribution in env.iter_all_distributions(): + installed_versions[distribution.canonical_name] = distribution.version + for package in installed: + display_name = package.name + version = installed_versions.get(canonicalize_name(display_name), None) + if version: + text = f"{display_name}-{version}" + else: + text = display_name + summary.append(text) if conflicts is not None: self._warn_about_conflicts( @@ -497,7 +497,7 @@ class InstallCommand(RequirementCommand): resolver_variant=self.determine_resolver_variant(options), ) - installed_desc = " ".join(items) + installed_desc = " ".join(summary) if installed_desc: write_output( "Successfully installed %s", @@ -511,7 +511,7 @@ class InstallCommand(RequirementCommand): show_traceback, options.use_user_site, ) - logger.error(message, exc_info=show_traceback) # noqa + logger.error(message, exc_info=show_traceback) return ERROR @@ -605,7 +605,7 @@ class InstallCommand(RequirementCommand): "source of the following dependency conflicts." ) else: - assert resolver_variant == "2020-resolver" + assert resolver_variant == "resolvelib" parts.append( "pip's dependency resolver does not currently take into account " "all the packages that are installed. This behaviour is the " @@ -617,12 +617,8 @@ class InstallCommand(RequirementCommand): version = package_set[project_name][0] for dependency in missing[project_name]: message = ( - "{name} {version} requires {requirement}, " + f"{project_name} {version} requires {dependency[1]}, " "which is not installed." - ).format( - name=project_name, - version=version, - requirement=dependency[1], ) parts.append(message) @@ -638,7 +634,7 @@ class InstallCommand(RequirementCommand): requirement=req, dep_name=dep_name, dep_version=dep_version, - you=("you" if resolver_variant == "2020-resolver" else "you'll"), + you=("you" if resolver_variant == "resolvelib" else "you'll"), ) parts.append(message) @@ -731,45 +727,6 @@ def decide_user_install( return True -def reject_location_related_install_options( - requirements: List[InstallRequirement], options: Optional[List[str]] -) -> None: - """If any location-changing --install-option arguments were passed for - requirements or on the command-line, then show a deprecation warning. - """ - - def format_options(option_names: Iterable[str]) -> List[str]: - return ["--{}".format(name.replace("_", "-")) for name in option_names] - - offenders = [] - - for requirement in requirements: - install_options = requirement.install_options - location_options = parse_distutils_args(install_options) - if location_options: - offenders.append( - "{!r} from {}".format( - format_options(location_options.keys()), requirement - ) - ) - - if options: - location_options = parse_distutils_args(options) - if location_options: - offenders.append( - "{!r} from command line".format(format_options(location_options.keys())) - ) - - if not offenders: - return - - raise CommandError( - "Location-changing options found in --install-option: {}." - " This is unsupported, use pip-level options like --user," - " --prefix, --root, and --target instead.".format("; ".join(offenders)) - ) - - def create_os_error_message( error: OSError, show_traceback: bool, using_user_site: bool ) -> str: diff --git a/venv/Lib/site-packages/pip/_internal/commands/list.py b/venv/Lib/site-packages/pip/_internal/commands/list.py index a9b08a0..8494370 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/list.py +++ b/venv/Lib/site-packages/pip/_internal/commands/list.py @@ -4,21 +4,20 @@ from optparse import Values from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version from pip._internal.cli import cmdoptions -from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.index_command import IndexGroupCommand from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError -from pip._internal.index.collector import LinkCollector -from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution, get_environment from pip._internal.models.selection_prefs import SelectionPreferences -from pip._internal.network.session import PipSession from pip._internal.utils.compat import stdlib_pkgs from pip._internal.utils.misc import tabulate, write_output if TYPE_CHECKING: - from pip._internal.metadata.base import DistributionVersion + from pip._internal.index.package_finder import PackageFinder + from pip._internal.network.session import PipSession class _DistWithLatestInfo(BaseDistribution): """Give the distribution object a couple of extra fields. @@ -27,7 +26,7 @@ if TYPE_CHECKING: makes the rest of the code much cleaner. """ - latest_version: DistributionVersion + latest_version: Version latest_filetype: str _ProcessedDists = Sequence[_DistWithLatestInfo] @@ -103,7 +102,10 @@ class ListCommand(IndexGroupCommand): dest="list_format", default="columns", choices=("columns", "freeze", "json"), - help="Select the output format among: columns (default), freeze, or json", + help=( + "Select the output format among: columns (default), freeze, or json. " + "The 'freeze' format cannot be used with the --outdated option." + ), ) self.cmd_opts.add_option( @@ -132,12 +134,20 @@ class ListCommand(IndexGroupCommand): self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, self.cmd_opts) + def handle_pip_version_check(self, options: Values) -> None: + if options.outdated or options.uptodate: + super().handle_pip_version_check(options) + def _build_package_finder( - self, options: Values, session: PipSession - ) -> PackageFinder: + self, options: Values, session: "PipSession" + ) -> "PackageFinder": """ Create a package finder appropriate to this list command. """ + # Lazy import the heavy index modules as most list invocations won't need 'em. + from pip._internal.index.collector import LinkCollector + from pip._internal.index.package_finder import PackageFinder + link_collector = LinkCollector.create(session, options=options) # Pass allow_yanked=False to ignore yanked versions. @@ -155,13 +165,18 @@ class ListCommand(IndexGroupCommand): if options.outdated and options.uptodate: raise CommandError("Options --outdated and --uptodate cannot be combined.") + if options.outdated and options.list_format == "freeze": + raise CommandError( + "List format 'freeze' cannot be used with the --outdated option." + ) + cmdoptions.check_list_path_option(options) skip = set(stdlib_pkgs) if options.excludes: skip.update(canonicalize_name(n) for n in options.excludes) - packages: "_ProcessedDists" = [ + packages: _ProcessedDists = [ cast("_DistWithLatestInfo", d) for d in get_environment(options.path).iter_installed_distributions( local_only=options.local, @@ -289,7 +304,7 @@ class ListCommand(IndexGroupCommand): # Create and add a separator. if len(data) > 0: - pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes))) + pkg_strings.insert(1, " ".join("-" * x for x in sizes)) for val in pkg_strings: write_output(val) @@ -321,7 +336,7 @@ def format_for_columns( for proj in pkgs: # if we're working on the 'outdated' list, separate out the # latest_version and type - row = [proj.raw_name, str(proj.version)] + row = [proj.raw_name, proj.raw_version] if running_outdated: row.append(str(proj.latest_version)) diff --git a/venv/Lib/site-packages/pip/_internal/commands/search.py b/venv/Lib/site-packages/pip/_internal/commands/search.py index 03ed925..74b8d65 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/search.py +++ b/venv/Lib/site-packages/pip/_internal/commands/search.py @@ -5,7 +5,7 @@ import textwrap import xmlrpc.client from collections import OrderedDict from optparse import Values -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING, Dict, List, Optional, TypedDict from pip._vendor.packaging.version import parse as parse_version @@ -20,7 +20,6 @@ from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import write_output if TYPE_CHECKING: - from typing import TypedDict class TransformedHit(TypedDict): name: str @@ -76,9 +75,8 @@ class SearchCommand(Command, SessionCommandMixin): try: hits = pypi.search({"name": query, "summary": query}, "or") except xmlrpc.client.Fault as fault: - message = "XMLRPC request failed [code: {code}]\n{string}".format( - code=fault.faultCode, - string=fault.faultString, + message = ( + f"XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString}" ) raise CommandError(message) assert isinstance(hits, list) @@ -91,7 +89,7 @@ def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]: packages with the list of versions stored inline. This converts the list from pypi into one we can use. """ - packages: Dict[str, "TransformedHit"] = OrderedDict() + packages: Dict[str, TransformedHit] = OrderedDict() for hit in hits: name = hit["name"] summary = hit["summary"] diff --git a/venv/Lib/site-packages/pip/_internal/commands/show.py b/venv/Lib/site-packages/pip/_internal/commands/show.py index 212167c..b47500c 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/show.py +++ b/venv/Lib/site-packages/pip/_internal/commands/show.py @@ -2,6 +2,7 @@ import logging from optparse import Values from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional +from pip._vendor.packaging.requirements import InvalidRequirement from pip._vendor.packaging.utils import canonicalize_name from pip._internal.cli.base_command import Command @@ -53,6 +54,7 @@ class _PackageInfo(NamedTuple): name: str version: str location: str + editable_project_location: Optional[str] requires: List[str] required_by: List[str] installer: str @@ -64,6 +66,7 @@ class _PackageInfo(NamedTuple): author: str author_email: str license: str + license_expression: str entry_points: List[str] files: Optional[List[str]] @@ -99,8 +102,19 @@ def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None except KeyError: continue - requires = sorted((req.name for req in dist.iter_dependencies()), key=str.lower) - required_by = sorted(_get_requiring_packages(dist), key=str.lower) + try: + requires = sorted( + # Avoid duplicates in requirements (e.g. due to environment markers). + {req.name for req in dist.iter_dependencies()}, + key=str.lower, + ) + except InvalidRequirement: + requires = sorted(dist.iter_raw_dependencies(), key=str.lower) + + try: + required_by = sorted(_get_requiring_packages(dist), key=str.lower) + except InvalidRequirement: + required_by = ["#N/A"] try: entry_points_text = dist.read_text("entry_points.txt") @@ -116,21 +130,39 @@ def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None metadata = dist.metadata + project_urls = metadata.get_all("Project-URL", []) + homepage = metadata.get("Home-page", "") + if not homepage: + # It's common that there is a "homepage" Project-URL, but Home-page + # remains unset (especially as PEP 621 doesn't surface the field). + # + # This logic was taken from PyPI's codebase. + for url in project_urls: + url_label, url = url.split(",", maxsplit=1) + normalized_label = ( + url_label.casefold().replace("-", "").replace("_", "").strip() + ) + if normalized_label == "homepage": + homepage = url.strip() + break + yield _PackageInfo( name=dist.raw_name, - version=str(dist.version), + version=dist.raw_version, location=dist.location or "", + editable_project_location=dist.editable_project_location, requires=requires, required_by=required_by, installer=dist.installer, metadata_version=dist.metadata_version or "", classifiers=metadata.get_all("Classifier", []), summary=metadata.get("Summary", ""), - homepage=metadata.get("Home-page", ""), - project_urls=metadata.get_all("Project-URL", []), + homepage=homepage, + project_urls=project_urls, author=metadata.get("Author", ""), author_email=metadata.get("Author-email", ""), license=metadata.get("License", ""), + license_expression=metadata.get("License-Expression", ""), entry_points=entry_points, files=files, ) @@ -150,14 +182,23 @@ def print_results( if i > 0: write_output("---") + metadata_version_tuple = tuple(map(int, dist.metadata_version.split("."))) + write_output("Name: %s", dist.name) write_output("Version: %s", dist.version) write_output("Summary: %s", dist.summary) write_output("Home-page: %s", dist.homepage) write_output("Author: %s", dist.author) write_output("Author-email: %s", dist.author_email) - write_output("License: %s", dist.license) + if metadata_version_tuple >= (2, 4) and dist.license_expression: + write_output("License-Expression: %s", dist.license_expression) + else: + write_output("License: %s", dist.license) write_output("Location: %s", dist.location) + if dist.editable_project_location is not None: + write_output( + "Editable project location: %s", dist.editable_project_location + ) write_output("Requires: %s", ", ".join(dist.requires)) write_output("Required-by: %s", ", ".join(dist.required_by)) diff --git a/venv/Lib/site-packages/pip/_internal/commands/uninstall.py b/venv/Lib/site-packages/pip/_internal/commands/uninstall.py index dea8077..bc0edea 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/uninstall.py +++ b/venv/Lib/site-packages/pip/_internal/commands/uninstall.py @@ -6,7 +6,7 @@ from pip._vendor.packaging.utils import canonicalize_name from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command -from pip._internal.cli.req_command import SessionCommandMixin, warn_if_run_as_root +from pip._internal.cli.index_command import SessionCommandMixin from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import InstallationError from pip._internal.req import parse_requirements @@ -14,7 +14,11 @@ from pip._internal.req.constructors import ( install_req_from_line, install_req_from_parsed_requirement, ) -from pip._internal.utils.misc import protect_pip_from_modification_on_windows +from pip._internal.utils.misc import ( + check_externally_managed, + protect_pip_from_modification_on_windows, + warn_if_run_as_root, +) logger = logging.getLogger(__name__) @@ -55,6 +59,7 @@ class UninstallCommand(Command, SessionCommandMixin): help="Don't ask for confirmation of uninstall deletions.", ) self.cmd_opts.add_option(cmdoptions.root_user_action()) + self.cmd_opts.add_option(cmdoptions.override_externally_managed()) self.parser.insert_option_group(0, self.cmd_opts) def run(self, options: Values, args: List[str]) -> int: @@ -90,6 +95,9 @@ class UninstallCommand(Command, SessionCommandMixin): f'"pip help {self.name}")' ) + if not options.override_externally_managed: + check_externally_managed() + protect_pip_from_modification_on_windows( modifying_pip="pip" in reqs_to_uninstall ) diff --git a/venv/Lib/site-packages/pip/_internal/commands/wheel.py b/venv/Lib/site-packages/pip/_internal/commands/wheel.py index 9dd6c82..278719f 100644 --- a/venv/Lib/site-packages/pip/_internal/commands/wheel.py +++ b/venv/Lib/site-packages/pip/_internal/commands/wheel.py @@ -10,7 +10,10 @@ from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError from pip._internal.operations.build.build_tracker import get_build_tracker -from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_install import ( + InstallRequirement, + check_legacy_setup_py_options, +) from pip._internal.utils.misc import ensure_dir, normalize_path from pip._internal.utils.temp_dir import TempDirectory from pip._internal.wheel_builder import build, should_build_for_wheel_command @@ -39,7 +42,6 @@ class WheelCommand(RequirementCommand): %prog [options] ...""" def add_options(self) -> None: - self.cmd_opts.add_option( "-w", "--wheel-dir", @@ -100,12 +102,9 @@ class WheelCommand(RequirementCommand): @with_cleanup def run(self, options: Values, args: List[str]) -> int: - cmdoptions.check_install_build_global(options) - session = self.get_default_session(options) finder = self._build_package_finder(options, session) - wheel_cache = WheelCache(options.cache_dir, options.format_control) options.wheel_dir = normalize_path(options.wheel_dir) ensure_dir(options.wheel_dir) @@ -119,6 +118,9 @@ class WheelCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) + + wheel_cache = WheelCache(options.cache_dir) preparer = self.make_requirement_preparer( temp_build_dir=directory, @@ -151,6 +153,8 @@ class WheelCommand(RequirementCommand): elif should_build_for_wheel_command(req): reqs_to_build.append(req) + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + # build wheels build_successes, build_failures = build( reqs_to_build, diff --git a/venv/Lib/site-packages/pip/_internal/configuration.py b/venv/Lib/site-packages/pip/_internal/configuration.py index 8fd46c9..ffeda1d 100644 --- a/venv/Lib/site-packages/pip/_internal/configuration.py +++ b/venv/Lib/site-packages/pip/_internal/configuration.py @@ -59,8 +59,8 @@ def _disassemble_key(name: str) -> List[str]: if "." not in name: error_message = ( "Key does not contain dot separated section and key. " - "Perhaps you wanted to use 'global.{}' instead?" - ).format(name) + f"Perhaps you wanted to use 'global.{name}' instead?" + ) raise ConfigurationError(error_message) return name.split(".", 1) @@ -210,8 +210,15 @@ class Configuration: # Ensure directory exists. ensure_dir(os.path.dirname(fname)) - with open(fname, "w") as f: - parser.write(f) + # Ensure directory's permission(need to be writeable) + try: + with open(fname, "w") as f: + parser.write(f) + except OSError as error: + raise ConfigurationError( + f"An error occurred while writing to the configuration file " + f"{fname}: {error}" + ) # # Private routines @@ -320,33 +327,35 @@ class Configuration: def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]: """Yields variant and configuration files associated with it. - This should be treated like items of a dictionary. + This should be treated like items of a dictionary. The order + here doesn't affect what gets overridden. That is controlled + by OVERRIDE_ORDER. However this does control the order they are + displayed to the user. It's probably most ergonomic to display + things in the same order as OVERRIDE_ORDER """ # SMELL: Move the conditions out of this function - # environment variables have the lowest priority - config_file = os.environ.get("PIP_CONFIG_FILE", None) - if config_file is not None: - yield kinds.ENV, [config_file] - else: - yield kinds.ENV, [] - + env_config_file = os.environ.get("PIP_CONFIG_FILE", None) config_files = get_configuration_files() - # at the base we have any global configuration yield kinds.GLOBAL, config_files[kinds.GLOBAL] - # per-user configuration next + # per-user config is not loaded when env_config_file exists should_load_user_config = not self.isolated and not ( - config_file and os.path.exists(config_file) + env_config_file and os.path.exists(env_config_file) ) if should_load_user_config: # The legacy config file is overridden by the new config file yield kinds.USER, config_files[kinds.USER] - # finally virtualenv configuration first trumping others + # virtualenv config yield kinds.SITE, config_files[kinds.SITE] + if env_config_file is not None: + yield kinds.ENV, [env_config_file] + else: + yield kinds.ENV, [] + def get_values_in_config(self, variant: Kind) -> Dict[str, Any]: """Get values present in a config file""" return self._config[variant] diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc index b48edfb4966916abac9527b2a28d206f6269b143..73e7d7bcac3dc397aae262f3637df2551aa8288e 100644 GIT binary patch delta 18 YcmeBT>tf@|=jG*M0D^Ci7jiKJ03|pCMF0Q* delta 18 XcmeBT>tf@|=jG*M00I&5gAmq6rY)$U9TP6I1otqI5Z%EFa(P~062vJ0U<&p?j%?VIcv{2Su(pDX4gbP zNG=YE0#QWU(St-yM@5OQI8h*qZK>$4x-0k)?=5y@K}MQ4Gw;3MdvAVk=I{FJJ@vR& zs}LCfeSE+2zq3_8G`IyPNhH<8!kyA|m^wY&*QZ<1#D6DC`1vb^@k?WIfY`74*^uU%bS$lV+3X%I)g z-gsng}A1t}4;#2O9JcV@;V^bPW4RDmqH|9jy?sq9SGd z6cnN#1^4>uM_eH=W3+-UfmBf%^frr#M&0WNMujt=+c8V_r*)_90xiHTPn7N%H+y6C z>?)`ZXQ%j$L6biCFt;6l)lY|+_2wv5pb|(HBw~~elR+iFT&YzVl`F3H#9|z&S#-k7 z16l%YV%1MXG-Rb9==hFh&k8@1+rgHXTiHYVx0w^o+Pc2hO182ApB}uV zrUsWXjcqXryS!15-X413AMt$~dW z*udQKJKenD58vgwiPx1$H;q-;;K`VMxT}vGLY1z@(s0C2qlI_kSet{mt+m@-?I%fB zY29v*<*%bRQfW#cCJ0#~33BKXPWSERe2Vf?gK~>e#@IJzv9FA?FU+3$TmazHmLacS z1aDT20BG){o9pnL4Yt8p*+0$^%Cmo+X=-QBof8X4RbHCAFn=9@MU=663TBGdx@W^! W_O&{X{YbD*mo(rrRw;)$V|@omNHlH$ delta 644 zcmYjOzi-qq6t*4b*Ikn9=|WqH(+QYJB@Q+i_#sLGAw)r9OC=&->?_wgm%|A&NK|5C zIQ$Q=c0_FKEX=arzr8hgYj;HoA3$C z581xBH=A>zmd9IXbD&n2|1YVYEq`CSHYMEU-VuF+Q(rj7)fXM!5nbLjpT+6a;{gv_ zK6r~LN<&jGYGVD`i3tloy~hF3SLt5l7~6z2v=VZv9Q}b#Z5Ve`ckRcQm1n|Z+zfWh z`a!Xfq7d_1@ViQtD#5C2SQY(;p8n>H@KB#R+j_^nab*n{a8P{%3H_^&VdD(II>74j zkM0G0PM^59aHL~z{EC7Ax@jyn$(x8xs#>wUE=2vjZA diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-310.pyc index 29ac82bd87174f11d10a35db88b34ed092cc32b6..2f00568fd635deeaa775b2361d8485fbecbc3af9 100644 GIT binary patch delta 614 zcmZvZO>5LZ7{}*rlgVxpt6debc&K1qiVNaRL9{e1h;?a|5!HX~WJgG$x2jBTR?ZFp$8#GLg?b4$O-;olVjt% zxW6hCU_0!HkB?9qRhfKd@d@sdn2gq@%PfaUZPTaEjh$q03ezirqQr|U_ZL;2=DC4U zR@F9}E(v`2Z;5-$pY?4IYpCrXiO{*1;v!#nZ^Y~CR#PN62@jMF$)6!vC+VMrj(bGz zq1@!>T`BMI$i0)-UNyS3MQLokZwarFNMvKG>X4i!p|>__S`@iGOXt5hts^Gup%6^9 z(Hg~t*XOYmN(k{wNbwWh57CLgx0&NX(0KKJnfZ&ocCNdrE_3OgsH?l}v~y)v4ky{7 oHWt5hI5%|)X`LQJ(X9VLH2T)OfMsrO(>GNF7qU=CbS3e zVqftxNTF7vVmNrR5nkJUxdyR4lMja@#r`CC7J8LCFI82*sfryEhXn`M`a@`Eaub&9 zhB|@3_SN21a rWxWMxkMs^m+t;0}+2t(ePHGl}T&vCTT}k)Dq6=<;VMHQ=2-@-&OzT7j diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc index bd3ee4dc32efd55040ead9b182b7b26e47d6f64f..a8b57c11eddf90f3e39b08eb17357048d8da88f9 100644 GIT binary patch delta 1794 zcmZ`(%WoS+7~h$Fc)jcA+D>XWNu9JwaUUTd9xY1CBNR6jg+Mu!<={G=vAfCo(b=^i z6;cGPI3YwCByOlZRtRzE9U;VlKY-Ip2t-d@5L`GwY5Bf&A1)7D^V{z|-+bSE^UJ~) zwM;*qwiNjNe&f4NqjEVjMLxKEaC)b!yL#7f4WclGseYnsx@JskezI%1R!r-@-A%cv zm^S=$H{)hvI^k!#IX6cXPQ?-MH~oCqaUI~5D+OM>O59RiVM%6PQkcc9i>f=p$Z4f! z|BRWe)%0jC{o3p6CmJg!Ppq6;U8_gtYRE-%!{?Ft@*wp3y{3Qpn{_!)mUe0+O0PFt zTg?uC!Rs+DS{P*fX9DvKtl&!kuDFCLE@i}3xyC5hxlvZyl&MU+q+KL#0%RueIx{Y5 zZjvRK$&%c{L>Xmv+hi%0293?8S%zhIfJ}i)`c9Y}%Y!5{CUIB+Bv~*ovJy}^Ho*-x z$@ARd1~=NYtdx~Fw83_EY;X7C>U+Jd#hMzaU=(S{Ma7};8*h5yx&AP0v_-Rnj@L+}1>Er4*A!8d>*|@A z+{V!JStAtC5-u7Zo5Z{{fRt(xc{^MBmxVOd!>2?ROd_+x!v@2XIlzkIJt(2JjM^>_ zo2(f&M`qr}5U;~Dr~?XMkqd_;$ra>J>Z~qOAd#welVm^Af6Ntt6J>-7!fyGizJFm3 z$jEN>du`uqgh-h6A0&r~3Um_*guQaptW592Fr~4Q292=a zXr1G&Eio^znoEc8?;iUeK;MH14<1tN0a^X}Epv(3@lJcu#+FB|Iw{C^tdc!uFRxlN zq$$6$7&#*6?MEtO9_V%y;VFPB`svz$8j8cX*G#H4w)?loMH()aCi? z?%B8`kAYr1iI4=in@b%9C*|kax#EMN;gK{DF@!3`MqGAmluxYh~SV#JP z@W+vT0^$BP+UUq}mtR5Es|f$tY5`=Q$V&cLK^t98ytE<%uvRO{Gx@_ikvS0k0To=SDGxZ+#GP$r z-I*o{$(;pa%J-d_8Eix}G4KY94X+2UJ3Q%&cV}Bz@;7H6vE^sZLvLU`q9ly|OZ`rV q3vn8F@hAc&`d=rA%;j#M4Sjx`fJOW$n#vSO(G(f|HJ~h7RR0Fl_<}e9 delta 1442 zcmZ`(O>Y}T7@nE^-u156YrCl(I}K6e)S(S2lp;jwr$m9a6sebXkuXkX;<#C_!`KE? z6#}#eZYUalKr3^slAU-QiDe&76~ z5%hiEMeDEFsCykzm)X~}xJ2;<)bxIX>hCnQ%zkUgczYpX znRa3Q-Z|fYx4pR1?yxtyDP`hid`Miu)wLg_H$yR|C?*ug8YN6$B2=ULbv-ty!Axp0 zi&}CJYA@NUq#oO91sI)rG$(x>8R;^wf@HK$1IgsJF?kwF#@`lIppj&b1+>UKT4H$? zGLLynq=G6)l`?6W?vgGAIwn_TV#VroH?2rEqPE;^Ra_+Z#7M7=XBuZ8W_E`STeLeE zHgTp8ShDmT;-R>sUBne}U$5Y@_(?x5%Eklii^%*n%*);LB0veCEQmFOYhu=_dLa-B z3gWyqg?Ddo>n|MoK-T~afV#NqRO=Jc%*wKXQJ1qGONWEju-{r-W{WF)kJxbL4{Q}u zv3ntQ8em%)m{uel+X&rx?5Rq1AYF0BJAE8dWF{Y_DdU;7APvWi{dWHQW|=b1M_ea{Vg0 zj4opysVCWd-q3C$9*Ot-89XDd`LlSJxaCjT`=oo*<-YjEKgC{y+^+(tU4dwP55TO1 zroo?Tl(|ngFyQ|y)wqmWkz)Xgng)4f67taA_&i844#oX^y}Dx`&XEpF*(a;~=vSf< z#`uKzA{>8CX)z~L@Ph!BgeSe60OF*$9Zr>=O{LoYO#B(1#M9z%;hPUmK@{O{LI50V z)8cP~y_Nh0n9c)imC-l1tnR@XSUL-^qtvA2z8165>$oVcL&$s->&~aGr!fjsbLQBOM1O(TLPm;yO*XpM7LzK3Yxy@5$=||iU-xeF# z6h9UxuqF1F_F-H6UaVn9Sf#y}-~*aD@*GkO-VMnp_ T7{JSHqY}=M9Dee5NlAMQa5f{H diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc index 41d5efeb798d841a0990c83a780d12d68c4991b5..9584e34a991fd405117f6d7451fdf29d1c2d6397 100644 GIT binary patch delta 731 zcmZuvzi-n(6ux)9^N++fsi=UIh@pal1@tcn6;de$A%#k<1l&>*-X$39IJ%@lg#n>< zWr)1NU(gw`)0LUY5(`W)g2cqYy%ZP_mfq+0?t4GJclP`6Fpi5TsxkZg`21mTPEO<2 z^ZPbJhLEuw6y#iSpqOV)E|i%0P9}3#xiep6UhXSD4^)uXR1KI0vt;vSR?kBf0$XS3 zqPNe`)9#+5BJ?*|5`3Yd39q89dmC%pt2fqGZ{6&ySN?5pG)aqLH=Dj#p1y0(B~V2h z-3O1m1ARRmqBhf?3tJsqtC<31iX$jT3*=gAx5@e(9TfXw50q!md>c!2_k{}3LmvZO z!8=YUxqVyv^iiS4P0%SX=LtBu}H zn&I}uSbf@Tr+C70V{Sq4r;B$UYMot6#}kwGc4(*Nf79Q5f&pCgsG(0l0~2nJ*;gf> zQ2Fm^L^dpxht6qOC_g%D(gYMQiYu2)NOVL%+7dBqU{2D(DT3x7%F2Ez&coUAt!P77 zeiN5f<&R7;(q^)29Gg}-R<4<&0+)amszk3SGP6MO(ei&i(q!oOA!ppO;4=YS&O_{! zU3t7oTqlVucd|Q5hXX@*GaFPslV?DbujCTQ@~dpsXXB2pqCAurR%pFh>;KKH{B~a8 WPNrArV~t5wgM~cg^B~+1=AB;`q?sfD delta 540 zcmY+CJ8u**5P&^nd)IgDZ9+JniI8Xl5#nl!BpsqbX^;R}pwmX<3oChVquq_@Xh;dg z$rYlcqC=vjqNS!f#1Ek07w{0{Gq(ILf1l;`XfzZ&#%DhqJXMQ)^&iPlOSqTsD-un3i*G((e6;yP^l*+bi%Kf9RtmkXt zrMeNmsGUixSU`gHu-B|anQBH+ycTgPVjK~-SbIlbhK=x8Z^IzG)z|JfI None: super().__init__() self.req = req + @abc.abstractproperty + def build_tracker_id(self) -> Optional[str]: + """A string that uniquely identifies this requirement to the build tracker. + + If None, then this dist has no work to do in the build tracker, and + ``.prepare_distribution_metadata()`` will not be called.""" + raise NotImplementedError() + @abc.abstractmethod def get_metadata_distribution(self) -> BaseDistribution: raise NotImplementedError() @@ -32,7 +46,7 @@ class AbstractDistribution(metaclass=abc.ABCMeta): @abc.abstractmethod def prepare_distribution_metadata( self, - finder: PackageFinder, + finder: "PackageFinder", build_isolation: bool, check_build_deps: bool, ) -> None: diff --git a/venv/Lib/site-packages/pip/_internal/distributions/installed.py b/venv/Lib/site-packages/pip/_internal/distributions/installed.py index edb38aa..ab8d53b 100644 --- a/venv/Lib/site-packages/pip/_internal/distributions/installed.py +++ b/venv/Lib/site-packages/pip/_internal/distributions/installed.py @@ -1,3 +1,5 @@ +from typing import Optional + from pip._internal.distributions.base import AbstractDistribution from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution @@ -10,6 +12,10 @@ class InstalledDistribution(AbstractDistribution): been computed. """ + @property + def build_tracker_id(self) -> Optional[str]: + return None + def get_metadata_distribution(self) -> BaseDistribution: assert self.req.satisfied_by is not None, "not actually installed" return self.req.satisfied_by diff --git a/venv/Lib/site-packages/pip/_internal/distributions/sdist.py b/venv/Lib/site-packages/pip/_internal/distributions/sdist.py index 4c25647..28ea5ce 100644 --- a/venv/Lib/site-packages/pip/_internal/distributions/sdist.py +++ b/venv/Lib/site-packages/pip/_internal/distributions/sdist.py @@ -1,13 +1,15 @@ import logging -from typing import Iterable, Set, Tuple +from typing import TYPE_CHECKING, Iterable, Optional, Set, Tuple from pip._internal.build_env import BuildEnvironment from pip._internal.distributions.base import AbstractDistribution from pip._internal.exceptions import InstallationError -from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution from pip._internal.utils.subprocess import runner_with_spinner_message +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + logger = logging.getLogger(__name__) @@ -18,12 +20,18 @@ class SourceDistribution(AbstractDistribution): generated, either using PEP 517 or using the legacy `setup.py egg_info`. """ + @property + def build_tracker_id(self) -> Optional[str]: + """Identify this requirement uniquely by its link.""" + assert self.req.link + return self.req.link.url_without_fragment + def get_metadata_distribution(self) -> BaseDistribution: return self.req.get_dist() def prepare_distribution_metadata( self, - finder: PackageFinder, + finder: "PackageFinder", build_isolation: bool, check_build_deps: bool, ) -> None: @@ -60,7 +68,7 @@ class SourceDistribution(AbstractDistribution): self._raise_missing_reqs(missing) self.req.prepare_metadata() - def _prepare_build_backend(self, finder: PackageFinder) -> None: + def _prepare_build_backend(self, finder: "PackageFinder") -> None: # Isolate in a BuildEnvironment and install the build-time # requirements. pyproject_requires = self.req.pyproject_requires @@ -104,14 +112,14 @@ class SourceDistribution(AbstractDistribution): with backend.subprocess_runner(runner): return backend.get_requires_for_build_editable() - def _install_build_reqs(self, finder: PackageFinder) -> None: + def _install_build_reqs(self, finder: "PackageFinder") -> None: # Install any extra build dependencies that the backend requests. # This must be done in a second pass, as the pyproject.toml # dependencies must be installed before we can call the backend. if ( self.req.editable and self.req.permit_editable_wheels - and self.req.supports_pyproject_editable() + and self.req.supports_pyproject_editable ): build_reqs = self._get_build_requires_editable() else: diff --git a/venv/Lib/site-packages/pip/_internal/distributions/wheel.py b/venv/Lib/site-packages/pip/_internal/distributions/wheel.py index 03aac77..bfadd39 100644 --- a/venv/Lib/site-packages/pip/_internal/distributions/wheel.py +++ b/venv/Lib/site-packages/pip/_internal/distributions/wheel.py @@ -1,13 +1,17 @@ +from typing import TYPE_CHECKING, Optional + from pip._vendor.packaging.utils import canonicalize_name from pip._internal.distributions.base import AbstractDistribution -from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import ( BaseDistribution, FilesystemWheel, get_wheel_distribution, ) +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + class WheelDistribution(AbstractDistribution): """Represents a wheel distribution. @@ -15,6 +19,10 @@ class WheelDistribution(AbstractDistribution): This does not need any preparation as wheels can be directly unpacked. """ + @property + def build_tracker_id(self) -> Optional[str]: + return None + def get_metadata_distribution(self) -> BaseDistribution: """Loads the metadata from the wheel file into memory and returns a Distribution that uses it, not relying on the wheel file or @@ -27,7 +35,7 @@ class WheelDistribution(AbstractDistribution): def prepare_distribution_metadata( self, - finder: PackageFinder, + finder: "PackageFinder", build_isolation: bool, check_build_deps: bool, ) -> None: diff --git a/venv/Lib/site-packages/pip/_internal/exceptions.py b/venv/Lib/site-packages/pip/_internal/exceptions.py index 97b9612..45a876a 100644 --- a/venv/Lib/site-packages/pip/_internal/exceptions.py +++ b/venv/Lib/site-packages/pip/_internal/exceptions.py @@ -6,22 +6,31 @@ subpackage and, thus, should not depend on them. """ import configparser +import contextlib +import locale +import logging +import pathlib import re +import sys from itertools import chain, groupby, repeat -from typing import TYPE_CHECKING, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Dict, Iterator, List, Literal, Optional, Union -from pip._vendor.requests.models import Request, Response +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.version import InvalidVersion from pip._vendor.rich.console import Console, ConsoleOptions, RenderResult from pip._vendor.rich.markup import escape from pip._vendor.rich.text import Text if TYPE_CHECKING: from hashlib import _Hash - from typing import Literal + + from pip._vendor.requests.models import Request, Response from pip._internal.metadata import BaseDistribution from pip._internal.req.req_install import InstallRequirement +logger = logging.getLogger(__name__) + # # Scaffolding @@ -177,10 +186,6 @@ class InstallationError(PipError): """General exception during installation""" -class UninstallationError(PipError): - """General exception during uninstallation""" - - class MissingPyProjectBuildRequires(DiagnosticPipError): """Raised when pyproject.toml has `build-system`, but no `build-system.requires`.""" @@ -240,10 +245,7 @@ class NoneMetadataError(PipError): def __str__(self) -> str: # Use `dist` in the error message because its stringification # includes more information, like the version and location. - return "None {} metadata found for distribution: {}".format( - self.metadata_name, - self.dist, - ) + return f"None {self.metadata_name} metadata found for distribution: {self.dist}" class UserInstallationInvalid(InstallationError): @@ -288,7 +290,10 @@ class NetworkConnectionError(PipError): """HTTP connection error""" def __init__( - self, error_msg: str, response: Response = None, request: Request = None + self, + error_msg: str, + response: Optional["Response"] = None, + request: Optional["Request"] = None, ) -> None: """ Initialize NetworkConnectionError with `request` and `response` @@ -332,8 +337,8 @@ class MetadataInconsistent(InstallationError): """Built metadata contains inconsistent information. This is raised when the metadata contains values (e.g. name and version) - that do not match the information previously obtained from sdist filename - or user-supplied ``#egg=`` value. + that do not match the information previously obtained from sdist filename, + user-supplied ``#egg=`` value, or an install requirement name. """ def __init__( @@ -345,25 +350,21 @@ class MetadataInconsistent(InstallationError): self.m_val = m_val def __str__(self) -> str: - template = ( - "Requested {} has inconsistent {}: " - "filename has {!r}, but metadata has {!r}" + return ( + f"Requested {self.ireq} has inconsistent {self.field}: " + f"expected {self.f_val!r}, but metadata has {self.m_val!r}" ) - return template.format(self.ireq, self.field, self.f_val, self.m_val) -class LegacyInstallFailure(DiagnosticPipError): - """Error occurred while executing `setup.py install`""" +class MetadataInvalid(InstallationError): + """Metadata is invalid.""" - reference = "legacy-install-failure" + def __init__(self, ireq: "InstallRequirement", error: str) -> None: + self.ireq = ireq + self.error = error - def __init__(self, package_details: str) -> None: - super().__init__( - message="Encountered error while trying to install package.", - context=package_details, - hint_stmt="See above for output from the failure.", - note_stmt="This is an issue with the package mentioned above, not pip.", - ) + def __str__(self) -> str: + return f"Requested {self.ireq} has invalid metadata: {self.error}" class InstallationSubprocessError(DiagnosticPipError, InstallationError): @@ -430,7 +431,7 @@ class HashErrors(InstallationError): """Multiple HashError instances rolled into one for reporting""" def __init__(self) -> None: - self.errors: List["HashError"] = [] + self.errors: List[HashError] = [] def append(self, error: "HashError") -> None: self.errors.append(error) @@ -549,7 +550,7 @@ class HashMissing(HashError): # so the output can be directly copied into the requirements file. package = ( self.req.original_link - if self.req.original_link + if self.req.is_direct # In case someone feeds something downright stupid # to InstallRequirement's constructor. else getattr(self.req, "req", None) @@ -599,7 +600,7 @@ class HashMismatch(HashError): self.gots = gots def body(self) -> str: - return " {}:\n{}".format(self._requirement_name(), self._hash_comparison()) + return f" {self._requirement_name()}:\n{self._hash_comparison()}" def _hash_comparison(self) -> str: """ @@ -621,11 +622,9 @@ class HashMismatch(HashError): lines: List[str] = [] for hash_name, expecteds in self.allowed.items(): prefix = hash_then_or(hash_name) - lines.extend( - (" Expected {} {}".format(next(prefix), e)) for e in expecteds - ) + lines.extend((f" Expected {next(prefix)} {e}") for e in expecteds) lines.append( - " Got {}\n".format(self.gots[hash_name].hexdigest()) + f" Got {self.gots[hash_name].hexdigest()}\n" ) return "\n".join(lines) @@ -656,3 +655,155 @@ class ConfigurationFileCouldNotBeLoaded(ConfigurationError): assert self.error is not None message_part = f".\n{self.error}\n" return f"Configuration file {self.reason}{message_part}" + + +_DEFAULT_EXTERNALLY_MANAGED_ERROR = f"""\ +The Python environment under {sys.prefix} is managed externally, and may not be +manipulated by the user. Please use specific tooling from the distributor of +the Python installation to interact with this environment instead. +""" + + +class ExternallyManagedEnvironment(DiagnosticPipError): + """The current environment is externally managed. + + This is raised when the current environment is externally managed, as + defined by `PEP 668`_. The ``EXTERNALLY-MANAGED`` configuration is checked + and displayed when the error is bubbled up to the user. + + :param error: The error message read from ``EXTERNALLY-MANAGED``. + """ + + reference = "externally-managed-environment" + + def __init__(self, error: Optional[str]) -> None: + if error is None: + context = Text(_DEFAULT_EXTERNALLY_MANAGED_ERROR) + else: + context = Text(error) + super().__init__( + message="This environment is externally managed", + context=context, + note_stmt=( + "If you believe this is a mistake, please contact your " + "Python installation or OS distribution provider. " + "You can override this, at the risk of breaking your Python " + "installation or OS, by passing --break-system-packages." + ), + hint_stmt=Text("See PEP 668 for the detailed specification."), + ) + + @staticmethod + def _iter_externally_managed_error_keys() -> Iterator[str]: + # LC_MESSAGES is in POSIX, but not the C standard. The most common + # platform that does not implement this category is Windows, where + # using other categories for console message localization is equally + # unreliable, so we fall back to the locale-less vendor message. This + # can always be re-evaluated when a vendor proposes a new alternative. + try: + category = locale.LC_MESSAGES + except AttributeError: + lang: Optional[str] = None + else: + lang, _ = locale.getlocale(category) + if lang is not None: + yield f"Error-{lang}" + for sep in ("-", "_"): + before, found, _ = lang.partition(sep) + if not found: + continue + yield f"Error-{before}" + yield "Error" + + @classmethod + def from_config( + cls, + config: Union[pathlib.Path, str], + ) -> "ExternallyManagedEnvironment": + parser = configparser.ConfigParser(interpolation=None) + try: + parser.read(config, encoding="utf-8") + section = parser["externally-managed"] + for key in cls._iter_externally_managed_error_keys(): + with contextlib.suppress(KeyError): + return cls(section[key]) + except KeyError: + pass + except (OSError, UnicodeDecodeError, configparser.ParsingError): + from pip._internal.utils._log import VERBOSE + + exc_info = logger.isEnabledFor(VERBOSE) + logger.warning("Failed to read %s", config, exc_info=exc_info) + return cls(None) + + +class UninstallMissingRecord(DiagnosticPipError): + reference = "uninstall-no-record-file" + + def __init__(self, *, distribution: "BaseDistribution") -> None: + installer = distribution.installer + if not installer or installer == "pip": + dep = f"{distribution.raw_name}=={distribution.version}" + hint = Text.assemble( + "You might be able to recover from this via: ", + (f"pip install --force-reinstall --no-deps {dep}", "green"), + ) + else: + hint = Text( + f"The package was installed by {installer}. " + "You should check if it can uninstall the package." + ) + + super().__init__( + message=Text(f"Cannot uninstall {distribution}"), + context=( + "The package's contents are unknown: " + f"no RECORD file was found for {distribution.raw_name}." + ), + hint_stmt=hint, + ) + + +class LegacyDistutilsInstall(DiagnosticPipError): + reference = "uninstall-distutils-installed-package" + + def __init__(self, *, distribution: "BaseDistribution") -> None: + super().__init__( + message=Text(f"Cannot uninstall {distribution}"), + context=( + "It is a distutils installed project and thus we cannot accurately " + "determine which files belong to it which would lead to only a partial " + "uninstall." + ), + hint_stmt=None, + ) + + +class InvalidInstalledPackage(DiagnosticPipError): + reference = "invalid-installed-package" + + def __init__( + self, + *, + dist: "BaseDistribution", + invalid_exc: Union[InvalidRequirement, InvalidVersion], + ) -> None: + installed_location = dist.installed_location + + if isinstance(invalid_exc, InvalidRequirement): + invalid_type = "requirement" + else: + invalid_type = "version" + + super().__init__( + message=Text( + f"Cannot process installed package {dist} " + + (f"in {installed_location!r} " if installed_location else "") + + f"because it has an invalid {invalid_type}:\n{invalid_exc.args[0]}" + ), + context=( + "Starting with pip 24.1, packages with invalid " + f"{invalid_type}s can not be processed." + ), + hint_stmt="To proceed this package must be uninstalled.", + ) diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-310.pyc index 655edd880ece89afbcfd3e6b8b79a545a92a7c08..eabdf3cdd83fd88fd8d2d23ba951478b02d6b157 100644 GIT binary patch delta 18 YcmX@hc$SeXpO=@50SLZ5p2&3=04@#%aR2}S delta 18 YcmX@hc$SeXpO=@50SH9ICvqJI048(;!vFvP diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-310.pyc index a675027eedfaf9262357f4af03329b186dcde971..e487652362af1317fc97e9c71a282618b88dc1ce 100644 GIT binary patch delta 4326 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 R{6*s3u?D?7&p#M&{0E19`X>MY delta 6848 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 diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-310.pyc index 4d29a85e34d2ff8416ff62efa8f6ded40d88c2f7..c5ca8a32d89be52b1d706a989b944342ea89f8c3 100644 GIT binary patch delta 9705 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 Ckn*hn delta 8880 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 XxD`1Rsfw&|l_E!6CHz+#i8lTpKI;zN diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-310.pyc index e709fd597acb263e547e1fc54801e4151ced55f2..1907ba9bc66edcab3852e070bd681e237f1b58eb 100644 GIT binary patch literal 8857 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 A_5c6? literal 7098 zcmc&&OLH5?5#C+wE*2mNK150+_3+w~Bf}*^ah#WFS*Al-u__GhvSn2Yp=$|Z2GmLm zEIhN2MHE!ALmzU8PC2GhA#+HTenIj>a@uQ7IqMWZ^Ytvi1p!b}9#vV?4Cc`@(>>Gu zO;3lDlX(r_{Hed~{9#ek{!W#_Zwi%FBzZ;GG^Q~<&??ElUeQ(Es2J)$Q_0}p2+W36 zu^M*8Ze%OjhEs8LqR#}mM!u3)Wiyy)6e*+Wss* zaiCY`xXts6T4f&p1^l1n7BB4RNo(Ce%c)+=f~qb4RAX7@e6BHP&!{Z196!zSe4%c# z30C;rteiprBrBr7$d~pqm9wZ%v1!z&Rs9_5Gi(<1Syg`y^%HCk^*L2{**s=E$xpFU ze332i1-6Kk=MK;E(~BDNrA3W6sTbH1JB<~eXZi

C8W9UpGo-?5tITpt>FK*trpL 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 diff --git a/venv/Lib/site-packages/pip/_internal/index/collector.py b/venv/Lib/site-packages/pip/_internal/index/collector.py index 6e5dac5..5f8fdee 100644 --- a/venv/Lib/site-packages/pip/_internal/index/collector.py +++ b/venv/Lib/site-packages/pip/_internal/index/collector.py @@ -9,14 +9,12 @@ import itertools import json import logging import os -import re import urllib.parse import urllib.request -import xml.etree.ElementTree +from dataclasses import dataclass from html.parser import HTMLParser from optparse import Values from typing import ( - TYPE_CHECKING, Callable, Dict, Iterable, @@ -24,6 +22,7 @@ from typing import ( MutableMapping, NamedTuple, Optional, + Protocol, Sequence, Tuple, Union, @@ -39,19 +38,13 @@ from pip._internal.models.search_scope import SearchScope from pip._internal.network.session import PipSession from pip._internal.network.utils import raise_for_status from pip._internal.utils.filetypes import is_archive_file -from pip._internal.utils.misc import pairwise, redact_auth_from_url +from pip._internal.utils.misc import redact_auth_from_url from pip._internal.vcs import vcs from .sources import CandidatesFromPage, LinkSource, build_source -if TYPE_CHECKING: - from typing import Protocol -else: - Protocol = object - logger = logging.getLogger(__name__) -HTMLElement = xml.etree.ElementTree.Element ResponseHeaders = MutableMapping[str, str] @@ -191,94 +184,6 @@ def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: return None -def _clean_url_path_part(part: str) -> str: - """ - Clean a "part" of a URL path (i.e. after splitting on "@" characters). - """ - # We unquote prior to quoting to make sure nothing is double quoted. - return urllib.parse.quote(urllib.parse.unquote(part)) - - -def _clean_file_url_path(part: str) -> str: - """ - Clean the first part of a URL path that corresponds to a local - filesystem path (i.e. the first part after splitting on "@" characters). - """ - # We unquote prior to quoting to make sure nothing is double quoted. - # Also, on Windows the path part might contain a drive letter which - # should not be quoted. On Linux where drive letters do not - # exist, the colon should be quoted. We rely on urllib.request - # to do the right thing here. - return urllib.request.pathname2url(urllib.request.url2pathname(part)) - - -# percent-encoded: / -_reserved_chars_re = re.compile("(@|%2F)", re.IGNORECASE) - - -def _clean_url_path(path: str, is_local_path: bool) -> str: - """ - Clean the path portion of a URL. - """ - if is_local_path: - clean_func = _clean_file_url_path - else: - clean_func = _clean_url_path_part - - # Split on the reserved characters prior to cleaning so that - # revision strings in VCS URLs are properly preserved. - parts = _reserved_chars_re.split(path) - - cleaned_parts = [] - for to_clean, reserved in pairwise(itertools.chain(parts, [""])): - cleaned_parts.append(clean_func(to_clean)) - # Normalize %xx escapes (e.g. %2f -> %2F) - cleaned_parts.append(reserved.upper()) - - return "".join(cleaned_parts) - - -def _clean_link(url: str) -> str: - """ - Make sure a link is fully quoted. - For example, if ' ' occurs in the URL, it will be replaced with "%20", - and without double-quoting other characters. - """ - # Split the URL into parts according to the general structure - # `scheme://netloc/path;parameters?query#fragment`. - result = urllib.parse.urlparse(url) - # If the netloc is empty, then the URL refers to a local filesystem path. - is_local_path = not result.netloc - path = _clean_url_path(result.path, is_local_path=is_local_path) - return urllib.parse.urlunparse(result._replace(path=path)) - - -def _create_link_from_element( - element_attribs: Dict[str, Optional[str]], - page_url: str, - base_url: str, -) -> Optional[Link]: - """ - Convert an anchor element's attributes in a simple repository page to a Link. - """ - href = element_attribs.get("href") - if not href: - return None - - url = _clean_link(urllib.parse.urljoin(base_url, href)) - pyrequire = element_attribs.get("data-requires-python") - yanked_reason = element_attribs.get("data-yanked") - - link = Link( - url, - comes_from=page_url, - requires_python=pyrequire, - yanked_reason=yanked_reason, - ) - - return link - - class CacheablePageContent: def __init__(self, page: "IndexContent") -> None: assert page.cache_link_parsing @@ -292,8 +197,7 @@ class CacheablePageContent: class ParseLinks(Protocol): - def __call__(self, page: "IndexContent") -> Iterable[Link]: - ... + def __call__(self, page: "IndexContent") -> Iterable[Link]: ... def with_cached_index_content(fn: ParseLinks) -> ParseLinks: @@ -326,25 +230,11 @@ def parse_links(page: "IndexContent") -> Iterable[Link]: if content_type_l.startswith("application/vnd.pypi.simple.v1+json"): data = json.loads(page.content) for file in data.get("files", []): - file_url = file.get("url") - if file_url is None: + link = Link.from_json(file, page.url) + if link is None: continue - - # The Link.yanked_reason expects an empty string instead of a boolean. - yanked_reason = file.get("yanked") - if yanked_reason and not isinstance(yanked_reason, str): - yanked_reason = "" - # The Link.yanked_reason expects None instead of False - elif not yanked_reason: - yanked_reason = None - - yield Link( - _clean_link(urllib.parse.urljoin(page.url, file_url)), - comes_from=page.url, - requires_python=file.get("requires-python"), - yanked_reason=yanked_reason, - hashes=file.get("hashes", {}), - ) + yield link + return parser = HTMLLinkParser(page.url) encoding = page.encoding or "utf-8" @@ -353,39 +243,28 @@ def parse_links(page: "IndexContent") -> Iterable[Link]: url = page.url base_url = parser.base_url or url for anchor in parser.anchors: - link = _create_link_from_element( - anchor, - page_url=url, - base_url=base_url, - ) + link = Link.from_element(anchor, page_url=url, base_url=base_url) if link is None: continue yield link +@dataclass(frozen=True) class IndexContent: - """Represents one response (or page), along with its URL""" + """Represents one response (or page), along with its URL. - def __init__( - self, - content: bytes, - content_type: str, - encoding: Optional[str], - url: str, - cache_link_parsing: bool = True, - ) -> None: - """ - :param encoding: the encoding to decode the given content. - :param url: the URL from which the HTML was downloaded. - :param cache_link_parsing: whether links parsed from this page's url - should be cached. PyPI index urls should - have this set to False, for example. - """ - self.content = content - self.content_type = content_type - self.encoding = encoding - self.url = url - self.cache_link_parsing = cache_link_parsing + :param encoding: the encoding to decode the given content. + :param url: the URL from which the HTML was downloaded. + :param cache_link_parsing: whether links parsed from this page's url + should be cached. PyPI index urls should + have this set to False, for example. + """ + + content: bytes + content_type: str + encoding: Optional[str] + url: str + cache_link_parsing: bool = True def __str__(self) -> str: return redact_auth_from_url(self.url) @@ -442,14 +321,7 @@ def _make_index_content( ) -def _get_index_content( - link: Link, session: Optional[PipSession] = None -) -> Optional["IndexContent"]: - if session is None: - raise TypeError( - "_get_html_page() missing 1 required keyword argument: 'session'" - ) - +def _get_index_content(link: Link, *, session: PipSession) -> Optional["IndexContent"]: url = link.url.split("#", 1)[0] # Check for VCS schemes that do not support lookup as web pages. @@ -470,7 +342,7 @@ def _get_index_content( if not url.endswith("/"): url += "/" # TODO: In the future, it would be nice if pip supported PEP 691 - # style respones in the file:// URLs, however there's no + # style responses in the file:// URLs, however there's no # standard file extension for application/vnd.pypi.simple.v1+json # so we'll need to come up with something on our own. url = urllib.parse.urljoin(url, "index.html") @@ -516,7 +388,6 @@ class CollectedSources(NamedTuple): class LinkCollector: - """ Responsible for collecting Link objects from all configured locations, making network requests as needed. @@ -558,6 +429,7 @@ class LinkCollector: search_scope = SearchScope.create( find_links=find_links, index_urls=index_urls, + no_index=options.no_index, ) link_collector = LinkCollector( session=session, @@ -588,6 +460,7 @@ class LinkCollector: page_validator=self.session.is_secure_origin, expand_dir=False, cache_link_parsing=False, + project_name=project_name, ) for loc in self.search_scope.get_index_urls_locations(project_name) ).values() @@ -598,6 +471,7 @@ class LinkCollector: page_validator=self.session.is_secure_origin, expand_dir=True, cache_link_parsing=True, + project_name=project_name, ) for loc in self.find_links ).values() diff --git a/venv/Lib/site-packages/pip/_internal/index/package_finder.py b/venv/Lib/site-packages/pip/_internal/index/package_finder.py index 9bf247f..85628ee 100644 --- a/venv/Lib/site-packages/pip/_internal/index/package_finder.py +++ b/venv/Lib/site-packages/pip/_internal/index/package_finder.py @@ -1,19 +1,17 @@ """Routines related to PyPI, indexes""" -# The following comment should be removed at some point in the future. -# mypy: strict-optional=False - import enum import functools import itertools import logging import re -from typing import FrozenSet, Iterable, List, Optional, Set, Tuple, Union +from dataclasses import dataclass +from typing import TYPE_CHECKING, FrozenSet, Iterable, List, Optional, Set, Tuple, Union from pip._vendor.packaging import specifiers from pip._vendor.packaging.tags import Tag from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.packaging.version import _BaseVersion +from pip._vendor.packaging.version import InvalidVersion, _BaseVersion from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import ( @@ -39,6 +37,9 @@ from pip._internal.utils.misc import build_netloc from pip._internal.utils.packaging import check_requires_python from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS +if TYPE_CHECKING: + from pip._vendor.typing_extensions import TypeGuard + __all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"] @@ -106,7 +107,6 @@ class LinkType(enum.Enum): class LinkEvaluator: - """ Responsible for evaluating links for a particular project. """ @@ -198,7 +198,7 @@ class LinkEvaluator: reason = f"wrong project name (not {self.project_name})" return (LinkType.different_project, reason) - supported_tags = self._target_python.get_tags() + supported_tags = self._target_python.get_unsorted_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. @@ -251,7 +251,7 @@ class LinkEvaluator: def filter_unallowed_hashes( candidates: List[InstallationCandidate], - hashes: Hashes, + hashes: Optional[Hashes], project_name: str, ) -> List[InstallationCandidate]: """ @@ -323,67 +323,44 @@ def filter_unallowed_hashes( return filtered +@dataclass class CandidatePreferences: - """ Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. """ - def __init__( - self, - prefer_binary: bool = False, - allow_all_prereleases: bool = False, - ) -> None: - """ - :param allow_all_prereleases: Whether to allow all pre-releases. - """ - self.allow_all_prereleases = allow_all_prereleases - self.prefer_binary = prefer_binary + prefer_binary: bool = False + allow_all_prereleases: bool = False +@dataclass(frozen=True) class BestCandidateResult: """A collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. + + :param all_candidates: A sequence of all available candidates found. + :param applicable_candidates: The applicable candidates. + :param best_candidate: The most preferred candidate found, or None + if no applicable candidates were found. """ - def __init__( - self, - candidates: List[InstallationCandidate], - applicable_candidates: List[InstallationCandidate], - best_candidate: Optional[InstallationCandidate], - ) -> None: - """ - :param candidates: A sequence of all available candidates found. - :param applicable_candidates: The applicable candidates. - :param best_candidate: The most preferred candidate found, or None - if no applicable candidates were found. - """ - assert set(applicable_candidates) <= set(candidates) + all_candidates: List[InstallationCandidate] + applicable_candidates: List[InstallationCandidate] + best_candidate: Optional[InstallationCandidate] - if best_candidate is None: - assert not applicable_candidates + def __post_init__(self) -> None: + assert set(self.applicable_candidates) <= set(self.all_candidates) + + if self.best_candidate is None: + assert not self.applicable_candidates else: - assert best_candidate in applicable_candidates - - self._applicable_candidates = applicable_candidates - self._candidates = candidates - - self.best_candidate = best_candidate - - def iter_all(self) -> Iterable[InstallationCandidate]: - """Iterate through all candidates.""" - return iter(self._candidates) - - def iter_applicable(self) -> Iterable[InstallationCandidate]: - """Iterate through the applicable candidates.""" - return iter(self._applicable_candidates) + assert self.best_candidate in self.applicable_candidates class CandidateEvaluator: - """ Responsible for filtering and sorting candidates for installation based on what tags are valid. @@ -414,7 +391,7 @@ class CandidateEvaluator: if specifier is None: specifier = specifiers.SpecifierSet() - supported_tags = target_python.get_tags() + supported_tags = target_python.get_sorted_tags() return cls( project_name=project_name, @@ -461,24 +438,23 @@ class CandidateEvaluator: # Using None infers from the specifier instead. allow_prereleases = self._allow_all_prereleases or None specifier = self._specifier - versions = { - str(v) - for v in specifier.filter( - # We turn the version object into a str here because otherwise - # when we're debundled but setuptools isn't, Python will see - # packaging.version.Version and - # pkg_resources._vendor.packaging.version.Version as different - # types. This way we'll use a str as a common data interchange - # format. If we stop using the pkg_resources provided specifier - # and start using our own, we can drop the cast to str(). - (str(c.version) for c in candidates), + + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + candidates_and_versions = [(c, str(c.version)) for c in candidates] + versions = set( + specifier.filter( + (v for _, v in candidates_and_versions), prereleases=allow_prereleases, ) - } - - # Again, converting version to str to deal with debundling. - applicable_candidates = [c for c in candidates if str(c.version) in versions] + ) + applicable_candidates = [c for c, v in candidates_and_versions if v in versions] filtered_applicable_candidates = filter_unallowed_hashes( candidates=applicable_candidates, hashes=self._hashes, @@ -533,13 +509,14 @@ class CandidateEvaluator: ) except ValueError: raise UnsupportedWheel( - "{} is not a supported wheel for this platform. It " - "can't be sorted.".format(wheel.filename) + f"{wheel.filename} is not a supported wheel for this platform. It " + "can't be sorted." ) if self._prefer_binary: binary_preference = 1 if wheel.build_tag is not None: match = re.match(r"^(\d+)(.*)$", wheel.build_tag) + assert match is not None, "guaranteed by filename validation" build_tag_groups = match.groups() build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) else: # sdist @@ -684,11 +661,29 @@ class PackageFinder: def index_urls(self) -> List[str]: return self.search_scope.index_urls + @property + def proxy(self) -> Optional[str]: + return self._link_collector.session.pip_proxy + @property def trusted_hosts(self) -> Iterable[str]: for host_port in self._link_collector.session.pip_trusted_origins: yield build_netloc(*host_port) + @property + def custom_cert(self) -> Optional[str]: + # session.verify is either a boolean (use default bundle/no SSL + # verification) or a string path to a custom CA bundle to use. We only + # care about the latter. + verify = self._link_collector.session.verify + return verify if isinstance(verify, str) else None + + @property + def client_cert(self) -> Optional[str]: + cert = self._link_collector.session.cert + assert not isinstance(cert, tuple), "pip only supports PEM client certs" + return cert + @property def allow_all_prereleases(self) -> bool: return self._candidate_prefs.allow_all_prereleases @@ -741,6 +736,11 @@ class PackageFinder: return no_eggs + eggs def _log_skipped_link(self, link: Link, result: LinkType, detail: str) -> None: + # This is a hot method so don't waste time hashing links unless we're + # actually going to log 'em. + if not logger.isEnabledFor(logging.DEBUG): + return + entry = (link, result, detail) if entry not in self._logged_links: # Put the link at the end so the reason is more visible and because @@ -760,11 +760,14 @@ class PackageFinder: self._log_skipped_link(link, result, detail) return None - return InstallationCandidate( - name=link_evaluator.project_name, - link=link, - version=detail, - ) + try: + return InstallationCandidate( + name=link_evaluator.project_name, + link=link, + version=detail, + ) + except InvalidVersion: + return None def evaluate_links( self, link_evaluator: LinkEvaluator, links: Iterable[Link] @@ -935,50 +938,51 @@ class PackageFinder: "Could not find a version that satisfies the requirement %s " "(from versions: %s)", req, - _format_versions(best_candidate_result.iter_all()), + _format_versions(best_candidate_result.all_candidates), ) - raise DistributionNotFound( - "No matching distribution found for {}".format(req) - ) + raise DistributionNotFound(f"No matching distribution found for {req}") - best_installed = False - if installed_version and ( - best_candidate is None or best_candidate.version <= installed_version - ): - best_installed = True + def _should_install_candidate( + candidate: Optional[InstallationCandidate], + ) -> "TypeGuard[InstallationCandidate]": + if installed_version is None: + return True + if best_candidate is None: + return False + return best_candidate.version > installed_version if not upgrade and installed_version is not None: - if best_installed: - logger.debug( - "Existing installed version (%s) is most up-to-date and " - "satisfies requirement", - installed_version, - ) - else: + if _should_install_candidate(best_candidate): logger.debug( "Existing installed version (%s) satisfies requirement " "(most up-to-date version is %s)", installed_version, best_candidate.version, ) + else: + logger.debug( + "Existing installed version (%s) is most up-to-date and " + "satisfies requirement", + installed_version, + ) return None - if best_installed: - # We have an existing version, and its the best version + if _should_install_candidate(best_candidate): logger.debug( - "Installed version (%s) is most up-to-date (past versions: %s)", - installed_version, - _format_versions(best_candidate_result.iter_applicable()), + "Using version %s (newest of versions: %s)", + best_candidate.version, + _format_versions(best_candidate_result.applicable_candidates), ) - raise BestVersionAlreadyInstalled + return best_candidate + # We have an existing version, and its the best version logger.debug( - "Using version %s (newest of versions: %s)", - best_candidate.version, - _format_versions(best_candidate_result.iter_applicable()), + "Installed version (%s) is most up-to-date (past versions: %s)", + installed_version, + _format_versions(best_candidate_result.applicable_candidates), ) - return best_candidate + raise BestVersionAlreadyInstalled def _find_name_version_sep(fragment: str, canonical_name: str) -> int: diff --git a/venv/Lib/site-packages/pip/_internal/index/sources.py b/venv/Lib/site-packages/pip/_internal/index/sources.py index eec3f12..3dafb30 100644 --- a/venv/Lib/site-packages/pip/_internal/index/sources.py +++ b/venv/Lib/site-packages/pip/_internal/index/sources.py @@ -1,8 +1,16 @@ import logging import mimetypes import os -import pathlib -from typing import Callable, Iterable, Optional, Tuple +from collections import defaultdict +from typing import Callable, Dict, Iterable, List, Optional, Tuple + +from pip._vendor.packaging.utils import ( + InvalidSdistFilename, + InvalidWheelFilename, + canonicalize_name, + parse_sdist_filename, + parse_wheel_filename, +) from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.link import Link @@ -36,6 +44,53 @@ def _is_html_file(file_url: str) -> bool: return mimetypes.guess_type(file_url, strict=False)[0] == "text/html" +class _FlatDirectoryToUrls: + """Scans directory and caches results""" + + def __init__(self, path: str) -> None: + self._path = path + self._page_candidates: List[str] = [] + self._project_name_to_urls: Dict[str, List[str]] = defaultdict(list) + self._scanned_directory = False + + def _scan_directory(self) -> None: + """Scans directory once and populates both page_candidates + and project_name_to_urls at the same time + """ + for entry in os.scandir(self._path): + url = path_to_url(entry.path) + if _is_html_file(url): + self._page_candidates.append(url) + continue + + # File must have a valid wheel or sdist name, + # otherwise not worth considering as a package + try: + project_filename = parse_wheel_filename(entry.name)[0] + except InvalidWheelFilename: + try: + project_filename = parse_sdist_filename(entry.name)[0] + except InvalidSdistFilename: + continue + + self._project_name_to_urls[project_filename].append(url) + self._scanned_directory = True + + @property + def page_candidates(self) -> List[str]: + if not self._scanned_directory: + self._scan_directory() + + return self._page_candidates + + @property + def project_name_to_urls(self) -> Dict[str, List[str]]: + if not self._scanned_directory: + self._scan_directory() + + return self._project_name_to_urls + + class _FlatDirectorySource(LinkSource): """Link source specified by ``--find-links=``. @@ -45,30 +100,34 @@ class _FlatDirectorySource(LinkSource): * ``file_candidates``: Archives in the directory. """ + _paths_to_urls: Dict[str, _FlatDirectoryToUrls] = {} + def __init__( self, candidates_from_page: CandidatesFromPage, path: str, + project_name: str, ) -> None: self._candidates_from_page = candidates_from_page - self._path = pathlib.Path(os.path.realpath(path)) + self._project_name = canonicalize_name(project_name) + + # Get existing instance of _FlatDirectoryToUrls if it exists + if path in self._paths_to_urls: + self._path_to_urls = self._paths_to_urls[path] + else: + self._path_to_urls = _FlatDirectoryToUrls(path=path) + self._paths_to_urls[path] = self._path_to_urls @property def link(self) -> Optional[Link]: return None def page_candidates(self) -> FoundCandidates: - for path in self._path.iterdir(): - url = path_to_url(str(path)) - if not _is_html_file(url): - continue + for url in self._path_to_urls.page_candidates: yield from self._candidates_from_page(Link(url)) def file_links(self) -> FoundLinks: - for path in self._path.iterdir(): - url = path_to_url(str(path)) - if _is_html_file(url): - continue + for url in self._path_to_urls.project_name_to_urls[self._project_name]: yield Link(url) @@ -170,8 +229,8 @@ def build_source( page_validator: PageValidator, expand_dir: bool, cache_link_parsing: bool, + project_name: str, ) -> Tuple[Optional[str], Optional[LinkSource]]: - path: Optional[str] = None url: Optional[str] = None if os.path.exists(location): # Is a local path. @@ -204,6 +263,7 @@ def build_source( source = _FlatDirectorySource( candidates_from_page=candidates_from_page, path=path, + project_name=project_name, ) else: source = _IndexDirectorySource( diff --git a/venv/Lib/site-packages/pip/_internal/locations/__init__.py b/venv/Lib/site-packages/pip/_internal/locations/__init__.py index 3f6f0a5..32382be 100644 --- a/venv/Lib/site-packages/pip/_internal/locations/__init__.py +++ b/venv/Lib/site-packages/pip/_internal/locations/__init__.py @@ -4,7 +4,7 @@ import os import pathlib import sys import sysconfig -from typing import Any, Dict, Generator, List, Optional, Tuple +from typing import Any, Dict, Generator, Optional, Tuple from pip._internal.models.scheme import SCHEME_KEYS, Scheme from pip._internal.utils.compat import WINDOWS @@ -27,7 +27,6 @@ __all__ = [ "get_bin_user", "get_major_minor_version", "get_platlib", - "get_prefixed_libs", "get_purelib", "get_scheme", "get_src_prefix", @@ -60,6 +59,12 @@ def _should_use_sysconfig() -> bool: _USE_SYSCONFIG = _should_use_sysconfig() +if not _USE_SYSCONFIG: + # Import distutils lazily to avoid deprecation warnings, + # but import it soon enough that it is in memory and available during + # a pip reinstall. + from . import _distutils + # Be noisy about incompatibilities if this platforms "should" be using # sysconfig, but is explicitly opting out and using distutils instead. if _USE_SYSCONFIG_DEFAULT and not _USE_SYSCONFIG: @@ -241,8 +246,6 @@ def get_scheme( if _USE_SYSCONFIG: return new - from . import _distutils - old = _distutils.get_scheme( dist_name, user=user, @@ -333,17 +336,6 @@ def get_scheme( if skip_linux_system_special_case: continue - # On Python 3.7 and earlier, sysconfig does not include sys.abiflags in - # the "pythonX.Y" part of the path, but distutils does. - skip_sysconfig_abiflag_bug = ( - sys.version_info < (3, 8) - and not WINDOWS - and k in ("headers", "platlib", "purelib") - and tuple(_fix_abiflags(old_v.parts)) == new_v.parts - ) - if skip_sysconfig_abiflag_bug: - continue - # MSYS2 MINGW's sysconfig patch does not include the "site-packages" # part of the path. This is incorrect and will be fixed in MSYS. skip_msys2_mingw_bug = ( @@ -407,8 +399,6 @@ def get_bin_prefix() -> str: if _USE_SYSCONFIG: return new - from . import _distutils - old = _distutils.get_bin_prefix() if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"): _log_context() @@ -442,8 +432,6 @@ def get_purelib() -> str: if _USE_SYSCONFIG: return new - from . import _distutils - old = _distutils.get_purelib() if _looks_like_deb_system_dist_packages(old): return old @@ -466,65 +454,3 @@ def get_platlib() -> str: if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"): _log_context() return old - - -def _deduplicated(v1: str, v2: str) -> List[str]: - """Deduplicate values from a list.""" - if v1 == v2: - return [v1] - return [v1, v2] - - -def _looks_like_apple_library(path: str) -> bool: - """Apple patches sysconfig to *always* look under */Library/Python*.""" - if sys.platform[:6] != "darwin": - return False - return path == f"/Library/Python/{get_major_minor_version()}/site-packages" - - -def get_prefixed_libs(prefix: str) -> List[str]: - """Return the lib locations under ``prefix``.""" - new_pure, new_plat = _sysconfig.get_prefixed_libs(prefix) - if _USE_SYSCONFIG: - return _deduplicated(new_pure, new_plat) - - from . import _distutils - - old_pure, old_plat = _distutils.get_prefixed_libs(prefix) - old_lib_paths = _deduplicated(old_pure, old_plat) - - # Apple's Python (shipped with Xcode and Command Line Tools) hard-code - # platlib and purelib to '/Library/Python/X.Y/site-packages'. This will - # cause serious build isolation bugs when Apple starts shipping 3.10 because - # pip will install build backends to the wrong location. This tells users - # who is at fault so Apple may notice it and fix the issue in time. - if all(_looks_like_apple_library(p) for p in old_lib_paths): - deprecated( - reason=( - "Python distributed by Apple's Command Line Tools incorrectly " - "patches sysconfig to always point to '/Library/Python'. This " - "will cause build isolation to operate incorrectly on Python " - "3.10 or later. Please help report this to Apple so they can " - "fix this. https://developer.apple.com/bug-reporting/" - ), - replacement=None, - gone_in=None, - ) - return old_lib_paths - - warned = [ - _warn_if_mismatch( - pathlib.Path(old_pure), - pathlib.Path(new_pure), - key="prefixed-purelib", - ), - _warn_if_mismatch( - pathlib.Path(old_plat), - pathlib.Path(new_plat), - key="prefixed-platlib", - ), - ] - if any(warned): - _log_context(prefix=prefix) - - return old_lib_paths diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-310.pyc index b28192734f6dd6b0ffb90ea7c297d2fa8ec346b5..3edcecaa0daf9e2433f99a76dcd11c7db74588dc 100644 GIT binary patch delta 3781 zcmZ`*U2qfE72dnMl6F_pTJpdABir(?02>2_B;WuJf5{X~8fa1kR1v-_TeAMRy9NX6 zC{*qwgfSuPOQ(g2-S&lcGM(0)=|dkned|MK=uAte)l7eAC(MwCPV>-AC!Lm_b0sVr zQfch;?K;W1U2p7O3_e5(^t-xy$HYA+a7KV#w4>eI+SY>^1s~e(E0=3^_eO^;uVJ zkk%PPNs$I?WHk^}S9ElBAH5+In zXl|uVh62|6l43~Uh)kPl3m~J0klscKZCxV8s!E8qEy^Vl+g^jJNIUJ|$c|@_P8#OO z*fU5M?dHhNXOJEm;m9u9Yj};mP!T;-jXv;(B&Cp$lxZLB2OpnXr#fIr>F4Pnr$ZoH z2eJx{(oNjd3-lQr;-}EfbPL$oz0S@s?gIaj+cMp14AD_TD}oOK-DYTf++H1V1C8#W zV~cKx$sToBCGZDI57M3BKvj8z?k+I6rf=v;ojymOUv$OB;ee0=`U2ez?z~u??V;l^ z+e^RvBAy5QmFZr(50>^-1@_YknC-95UZMwJHbKb=A$sT$*70Q2RhA}lm&)?N)Ra|L zj~F?FC9FJizApV<(wOd?l_R_AK(g$eHmrCdldv+WbJfWlGjO6IVouE%S%U>Yl+`0? zSpB6uEV}!U?{og`&W1;THANr+FB^d2E-7nqnli09E0r-<=RHS>w<3-@{mwn5jU078 zQ9dT^&ac(>4cKSuD2c5OYHyMzuF?-GWp#WS{GTtdy&31WHxsBCi&iYQ`Z@@8cKW`* z!PY0fFfmtE|8;T0@`rU@#h)Y1FA=y{lU%+5;MUb^8V_3!8gQxZ6I;kZ>B6` zxR98dO-vi+WR#Q@BS+1PDQhMwvOVY`DX^MX=rnr~$Pb+E#;b7zp2$hF#wB(V@wMY| z$&X;kl!1tEHw$+~wgpATfJ7x0LH-1i{YYy2a6A3CntB^P1i(~)=w5{cMCHHith1}> z#}rk|I_7aIpG&5u;};T)^`MnwNKPRvWsF=@W?w^I&Cm-5GgJ8-dlTn!A;GM5JMwh+ z~;~IR82`XsdR9?oBX$F~M^2R5G4Tnc0LjHS?<{ zW)&h69UhiF`fC=Z=Ie&HiaY&q%5cNsa({>)`=lDi3Ef5^v1q;CO?gF zwTyY|Hy~hQ{uCvwunSH$)URW8sqjdMEjr7g9?_DVd!d%1$C3{UXaBmOSgvKa<$0Ib zN=aNH3uo1msd=8XdppZl5HTBA@YGA=<`xpZyg}T9s%a&de*kx|y zMrAF3!>aQMK$UcWdS+d~1*tMC!B}4s7W}rK-Qx0hs;=JQ^2Iw=1HihivlWC3cWn_K zSK+SJSQ5bCeQ>IYs#N<1zMSw}_pN3)O;d?bbyfx(c&Y;C+kk1aLg60A{DA4;$bGA& zBoyvjt*~F6UB~_ak*q7`A5{H$V1)n(*a7x20Bz}ZczXnvNd8mq=cgbQydW$D?I8On zIO>!5dn?Z9;glf8EHXX&=%^gZrswYhu1OSH_7=; zR!?;U7Y!}R6`g1sbo{3)cOL4FmoHr7ONC4949v^!!X?Z3Nk`+$9WZ-@<;k$eF&`3K zi;87w&SYg*CO?(PumxCpgw3731q5zoS%Wvi)NFhvpEcleUU7yxuMYE;vKs{Mie)b~ zl8L#D6^Cw6xx4(vt~JH^)!%jY5)ySj4|ng+q2&UQXoUHZZv|4;<6k*(D1PG9i37(c z55IDR4I$z|#8XIEGx&0nUj>HsIA^+cd?|?V1QI+?*;j30@l-CEXYIH?isW@9UL^cF zpF{3dBnOe4MG|oyc8!hVryy@W>;iDn26hn_p6Uy0(Ph)l@$OY8+_ULrY+RK#v4|W$ zG9Kt5Jm%kl$cjj6fA{CIA`@tS8`o6Dxz$r@2)M+@vLq6pM<(K9wdk@KVBp57sb@7JJdp6H|E%~UvM8HQK z80^h5QN%Xl#tz-+O!bZ(D)Y9FfriSem4nBeVyS{(*dz?g9HAOgDzpc`MRAUW=IxHxt7qfGM>%Txs0(F;v|?DY7MT%lYa+%$N32Vi`_&~HNV~{ ZX`(KX7cOm-S%1{y)m|OKkuE delta 5375 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 diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc index 325aaf53717dd0526a430def8bc37a71b15d3ffd..fbc027c56101d30bde747c7839309d3c237a1b45 100644 GIT binary patch delta 1709 zcmah~OKclO7@nDZde^&t#ExGHwcDg=K&o2xfIw+W5mf3cLOevf2)T)8?QXPdFS8rk zRBNSbB5^<*U?e2eAjKyn-~=4FaN~eDao~WKBex#7AOYeL_-9*MwL+>#`_1=1=KE)7 ze%pI9y+S@!iH=NMSzD83owoqWbs;Fe=&T=NS-(J5wJ_e;TM z*(nE8&QwrwDnZqOQm{DZPX{%pmT|+c2Mwo@ano-GEvE%MPc45Yn000`a+Tf3+XecG#E9v>~`EvpEOXvNb9t* ztvLrC5PYN*DAn9r-=&cp1z50;wyn4875iUnL*l5-&;f_y_)^#5WUjoKG;jm?-SxSw!sw-$JyID7Vmu z@)o{{6TqD%VkcVP8Tubt6xg_7sB{&KpH=-r5j6?~qLd3{83CF-q;ASF)Tfplvpc^ zhgNpT1Y;CWZ6S6W%72!Su`-0surDEA0WQI8jFq^$HodDQ3a!#l8j#8Pf#4C#mdoa$9i_8-Mi-au+o)=tW z|81xJv~afXK?hiB4BWUI^{%*q8}Yzu;FJ6<>&GkiUMbawBNl`!@s(7HHljPnV+oBT zV!7&GgY%10J@i-NK4d~|ae|Jz>J7W$#>3@oQ7#KHx9?qhpMPt&@ELxoFvCfq`mAFK zoo*DmJ+JTem?{djAB1e%rqBu3nd^J2A3^*V0$^Zv9;9Y3p9N!4T7H?G6H6Z<0tG?j z6OnmAz_M7ZoL*i&y}WoR)w*3e>UF!R(d~LcIASqy-Yqtd*{9-|d8_NO`#fVKmTLZJ zFz|*0mYv;cP;spLZPp7YllV^Ys3D6YiU{*hwdS#O>V6U&aBnp1djqCHJXPb3PzdT` zMNWYDEoUaLmpZDr+_cFrmnwR1Brb?q{I$|t-WGm&btQ748{aN9HV+Gj1WgX!(a68k z8YhL&83E@7hf5wnPkqJRI3EGWC&7 delta 1990 zcmah~-H+5%6uW(go7uUY*^+jq-gZ|O zyBXpV-bf(V#27T$dC~`Cj7Fc-zd;jYVtw%sFg$3CMg=^#gRBq}X42pJosWCYx##xI ze6{1&yfM)AEP_v^_Fb=Ezh+Dg-^K`0WTFeIjVa#1n`DGAdKvXIGP0$$G6oH!GpLW> zK$K9)l}$O3im4GnpoAoqPOLz)+&eRj0b`39Y<`b^E1+Qopyj}@g4XKb=tU;Hs|k2 zvb7u*HxQ&4%W;}9ui5pkL7Q~)l435y9=N1@Pn&PW+3&b>Mm=`Imtkz=r^v zdGT5~Xk8BrhtR9qx)H*1T8fMs+8~i08T--eS7|xQY?i1t!mEgV9O;|oZ~~H4#6u^p zkP*fxtZpE70~+`uBI`;&16%qM{59Yb$lSUT*3UII(~&|ev`TAXlaJ)u?2W`anc!5U z(|QAq@CegJ1Fh$UmH!|g!7J4UXUvO*W|2(*Wpx1+0aboAUBwdrAiXe*WeVrVb_#nQz$`fZAZ)v?wG!BD zsSPkCeA5Do0C6_(T_>c>S+(PIdnxeS;c~0M$|4{sG_E1knt-HkNw6k>nGr2oZPp87 zOk;jn-K)(CX99ElO?6+1$e7>~R&SA;a@xQ-oaJAuleo%bbsiu1?6&%zG~6xL>=N)0 zK%5Rb%<;njw$l#VErs3dXHSdBX8>A+9S~d>JpF*KpA?b*=?>I5+p|L}NOhKN&kp&F z-oOX>6Z((Kcc&Dq{Q>jDRAMPu3AM5cXWeab!$0|;W(ciUkXBB3KOA~Ut*^eunw z{(6R}m$;bSb-nEdC0!U1#Y- zF#JjYvY4IZx%~9-c~Dx?;%T-BV1the^Eq(?V>!8XMgDD}F?>WAB)HRH9Sq#@yL(V9J}%&- z0C51x-v9UH)&1UpuDJG7;#h*q05T$40d5uCvfHYpVioxKJA-p1VI)h4LNMX9SZ)%D g+$1vj8!Ug36#0{=(pn-?%1=VnaVoWX0v zXuctnp_Zpaz=a`}raCSSCXa&l1Ky##-(g zZlD?Bn~(EdXJ#+r2il`4Jb8go#bia{5YZ^UbHjAD#@j4X^rev^L)UllwB)L+a7BvhDK7pB!D7e zKoJ@Kq7WcYlgY2h7DyL`PL>gslg&vi$;nK*3K9qh5fLCItZsgOZho5TnZ7zO-5 e;=v#y46FjEPh#>eaX!Y7$tT5wSpE3eg;)UXU`@yX delta 504 zcmX|-&r2IY6vyYy&NgDQ>n5A1A+}h5po1vIQ!njB%|UdP`m07n)SZYLFwU+;VM7n` z>Otlvo_Z>H3_bM^D7|@5ls$VD1@F=~Y3;y#<~!dvKi+$HBj4UxdzRHoaO66!wtk*k zuc3N6^ay>b3pU^8MZs?oY-d0eM4?Rcq|E#tzxSAx27Q<#yuWb_zmiaDOj)Bad=Wb1 zWYwvq!gOSWnJ5{h>a&H00BMaUJbv{OB|+pwst Nj!%hcJ7KeK_6G-nY&-w} diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-310.pyc index d248e857f7f2e63521c374b7888717ccb066c3b9..842a4e23408fcde27b41121d355c28b562461d35 100644 GIT binary patch delta 201 zcmX>rbXubXJHjpO=@50SH9JucY&GP2`hd{4-HIFPAk-AXQM3Ayp`a-G(8BBULbsDTOnI ztA!;>IE6b^Fog$*L85FayeWJ@Q4y#b{uBWqPqd0Rm1%+4LWU^uRD?-_HVokmc|0r( zsS=fWj0_-{%9JG;CBBKVj-8Xkzn~;DKQA$7axI6$ Dict[str, str]: @@ -56,8 +56,7 @@ def distutils_scheme( try: d.parse_config_files() except UnicodeDecodeError: - # Typeshed does not include find_config_files() for some reason. - paths = d.find_config_files() # type: ignore + paths = d.find_config_files() logger.warning( "Ignore distutils configs in %s due to encoding errors.", ", ".join(os.path.basename(p) for p in paths), @@ -65,7 +64,7 @@ def distutils_scheme( obj: Optional[DistutilsCommand] = None obj = d.get_command_obj("install", create=True) assert obj is not None - i = cast(distutils_install_command, obj) + i: distutils_install_command = obj # NOTE: setting user or home has the side-effect of creating the home dir # or user base for installations during finalize_options() # ideally, we'd prefer a scheme class that has no side-effects. @@ -79,7 +78,7 @@ def distutils_scheme( i.root = root or i.root i.finalize_options() - scheme = {} + scheme: Dict[str, str] = {} for key in SCHEME_KEYS: scheme[key] = getattr(i, "install_" + key) @@ -89,7 +88,7 @@ def distutils_scheme( # finalize_options(); we only want to override here if the user # has explicitly requested it hence going back to the config if "install_lib" in d.get_option_dict("install"): - scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + scheme.update({"purelib": i.install_lib, "platlib": i.install_lib}) if running_under_virtualenv(): if home: @@ -171,10 +170,3 @@ def get_purelib() -> str: def get_platlib() -> str: return get_python_lib(plat_specific=True) - - -def get_prefixed_libs(prefix: str) -> Tuple[str, str]: - return ( - get_python_lib(plat_specific=False, prefix=prefix), - get_python_lib(plat_specific=True, prefix=prefix), - ) diff --git a/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py b/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py index 0bbc928..ca860ea 100644 --- a/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py +++ b/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py @@ -192,9 +192,10 @@ def get_scheme( data=paths["data"], ) if root is not None: + converted_keys = {} for key in SCHEME_KEYS: - value = change_root(root, getattr(scheme, key)) - setattr(scheme, key, value) + converted_keys[key] = change_root(root, getattr(scheme, key)) + scheme = Scheme(**converted_keys) return scheme @@ -211,8 +212,3 @@ def get_purelib() -> str: def get_platlib() -> str: return sysconfig.get_paths()["platlib"] - - -def get_prefixed_libs(prefix: str) -> typing.Tuple[str, str]: - paths = sysconfig.get_paths(vars={"base": prefix, "platbase": prefix}) - return (paths["purelib"], paths["platlib"]) diff --git a/venv/Lib/site-packages/pip/_internal/locations/base.py b/venv/Lib/site-packages/pip/_internal/locations/base.py index 3f7de00..3f9f896 100644 --- a/venv/Lib/site-packages/pip/_internal/locations/base.py +++ b/venv/Lib/site-packages/pip/_internal/locations/base.py @@ -13,7 +13,7 @@ from pip._internal.utils.virtualenv import running_under_virtualenv USER_CACHE_DIR = appdirs.user_cache_dir("pip") # FIXME doesn't account for venv linked to global site-packages -site_packages: typing.Optional[str] = sysconfig.get_path("purelib") +site_packages: str = sysconfig.get_path("purelib") def get_major_minor_version() -> str: diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__init__.py b/venv/Lib/site-packages/pip/_internal/metadata/__init__.py index 8cd0fda..1ea1e7f 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/__init__.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/__init__.py @@ -9,7 +9,7 @@ from pip._internal.utils.misc import strtobool from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel if TYPE_CHECKING: - from typing import Protocol + from typing import Literal, Protocol else: Protocol = object @@ -30,7 +30,7 @@ def _should_use_importlib_metadata() -> bool: """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend. By default, pip uses ``importlib.metadata`` on Python 3.11+, and - ``pkg_resourcess`` otherwise. This can be overridden by a couple of ways: + ``pkg_resources`` otherwise. This can be overridden by a couple of ways: * If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it dictates whether ``importlib.metadata`` is used, regardless of Python @@ -50,6 +50,7 @@ def _should_use_importlib_metadata() -> bool: class Backend(Protocol): + NAME: 'Literal["importlib", "pkg_resources"]' Distribution: Type[BaseDistribution] Environment: Type[BaseEnvironment] @@ -70,7 +71,7 @@ def get_default_environment() -> BaseEnvironment: This returns an Environment instance from the chosen backend. The default Environment instance should be built from ``sys.path`` and may use caching - to share instance state accorss calls. + to share instance state across calls. """ return select_backend().Environment.default() @@ -103,3 +104,25 @@ def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistributio :param canonical_name: Normalized project name of the given wheel. """ return select_backend().Distribution.from_wheel(wheel, canonical_name) + + +def get_metadata_distribution( + metadata_contents: bytes, + filename: str, + canonical_name: str, +) -> BaseDistribution: + """Get the dist representation of the specified METADATA file contents. + + This returns a Distribution instance from the chosen backend sourced from the data + in `metadata_contents`. + + :param metadata_contents: Contents of a METADATA file within a dist, or one served + via PEP 658. + :param filename: Filename for the dist this metadata represents. + :param canonical_name: Normalized project name of the given dist. + """ + return select_backend().Distribution.from_metadata_file_contents( + metadata_contents, + filename, + canonical_name, + ) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc index 57ff5c96c1d68dc979da45c8ff71ab609709abcb..8ed56a1cfa3596b35621d7687ca78bea79e5cf4a 100644 GIT binary patch delta 1656 zcmZux&2Jk;6rUMy*6a009J@{I#Hptd39%A#K(va28=AJENNu4K<$w`#HlDGw?t0gn zUAHPkGE#D_1YL1}6CiHDgVEp~)x7J@-gdR!ZBrL(qL#;M*6|p2s9U_+E`GZ)kz;V0CFiYRZu&w~>GHmitJHWMBkTW1> z*%a)XV>uq@IxiJb5h;tt^6V5?=HFtcc?neMrpBh(45-eq0-s{Vp;l+JY!0+#R^pV+ zgZ9{BursU-ma`1Miz+nS#GjfZieI+_E-dHh7p!CaAbd!^J^DEIBf(4IntmTIhd=4_ z?KL<(M>Wh)jl72#<}pU9h--YJh+rO5b6w4~Dq<6WuSfAqR^v8z*++{*7auIxovtSW z$KG97r3>BLt-9d8*AoryFMJqjZ*Se$4m0sf*Q3dL-Ev(ouman2{d!$YKmZ~knY=2o zG|pa@Vg=Z1K)$>#6B#&#vshHZFXOHLOQ5RYC_Uz~qKjqFM@THfPw0|K5b-Lo3K?kS z{DeE@DG$00AYaC!lN2@;38`-YjST`)_=!=#M)-yC_?qy1pEfMV@z+cWqY_iw#40R{ z;*2+~o)esKs7|W9LS>?DAYUS;;v#$WN1}xa{bde;i}{0bK5r2c816vPzh z-T_h&nYfq=50lIIeE381*HwkH0>&t#aF{K4Bk;sMz*>I>EBr21PQO0_(#6Kn@2MT! ze~K}PS@cns<_sYS;< z-?f81fVEU)tJD*;@41}%T-@PI;mRs`@wj7K^yc zXs`4j?A@O1@Q%Dd*-XYH!SbWp6LAsb%7Q4sFG@6fE)=8Z_+lPpQ4T-PwEALF+H`NX z4V4YBh3stA%~8S;y?VoH?D0XT$v%o=;9SUd5VDa6bvLnlFW|oNd!lhh z4Hy~Kj>mcq--LQX{J&54E4c4>+GduIWZ@#y0=HtTKxs}MWOoBF5{nq(n z5%Nm7b{*HDq^Gd5>vRa{@2NWp2AgUtkOT8bbt|_BOhEpK zK%O~=8Mn&l!8A~?jw$l0$SXkcNIj%(4eJ8dHk7ch4i3|q#u_zJBk73>Wtha18JJ>? zWrVD@3Kgg#bOEMW32Lm7q8ikpf#@vIUDBKp59w=4hbL5{RER&yhvB=-P@xOro_4%@ z86Om&pRo*9+vxEk21Z;8#8vJSmSJj*uq@D)%(XOES_Cq9jhg5?e(;p_Kj-n<9I&s!!W*L&Z9LmTr&AG zhC~O}_6K2qOe_82RIrGQo9MBEA+Ph|uw{1W_5a;wn@3&mncv@wo0P91YfLAVuo1ia zPoki6TYR5bqU$1;|Ei@rP4OdNv9F$M6}mNNJvi;t_{MO}dQ2aUS`bf0SHIX}EX0{? z%KmHTL}XdQ;G?Hcu#L2C&haWjNv=KU1^p-rV?HCfv*J~$(@nJK$pH)ciH_?GLtJA+ z9?F%ZYe;e-A9#Tu?6J`t<&=_4+~-_AmT$-)uN@o3=|~f!)s0{fvKtf`@uGO{lq&_Q UDuz<9?5dfyX~C?Uj#gojVZ=ljlge2#xq-ml;c zJMuU9>aFSr&Ma1w-{Amn=nID$Du6ZQps)@;%4dbQRpAMEY`rSJww}Ys&auM=atqxC zXXI1#2Q=jqyWXtnDmI6@j?^*_(?~>|4)4*BP}Y$j>_^)R(F`is*;e4e46uv;SC+c5 zo@$gOd2dIKoovGt1wh$cuqbEkg?iD9ZRy-C`O7(rORQ*kGXiVLHTQJ4p+n_Ps2GNE ztO`2NPI(*&X8uO`hRMUjI15SOvI{2X=#3r3g00HLZPw;(I>vB5n4j>;P-MgVJWJbh z=5AJ&AOaphkoB}^Kd8vh?*2_<&Mq5h88EMy^Cv4>?BT@I>n0gFh-nXK882%%1pz(K)IEUHmUc?S)6R|I#RfpbuQeD= zU;PSzT!r6pRqq~Id`2!5_JRd{5l~A7@Vb0km;;~Xr@}}7%zB64TW_2*hqq*cUV_{5 z8vSnE)ueJdhlA`$D0}}Tr$S+xbr?yrgwJUAugn^*EZSL`r-H_Zv`r{~D1X?eD-&o0 z6!+QP36M5mVeKQmRWs97reg0rVkC&M+zO3b${>EjdEaed@ zIvUPXmPJKgG>qxVO=DGlv9;UWZ0P@3WClz!uNyJe eKd&`uq40W-kwKR>fF^{mWeWPB1~9x8hUgFT=YQb< diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-310.pyc index 8683d08217be636af1005fa70d4c0c66aa5c5630..4c1d5f5e7fbda6d9a83d9f6d7a12a2e7a374e744 100644 GIT binary patch delta 8032 zcma)BeNb>DgW$?~;)i|@yW5Q_kT5C{;G015Ps(3ce>OUq+tfJMtLp7)RpMqaB@ zoi??t$P?8`Q@c{)=0tIGYIl8{^pBq795=C=<2H7h*2#0-I%$)}aX#DA{vkI`@13{1 zEC`M*o6F2^?!9wo=FYwM4d41U`OTXoCz_q@wZXst{rB%peRtw|PKEM4a=rPv%-O23 zDq^EH>Iz?fI~>cQx#5o4ZDZSrjTN&_=9=l6R7!1Q+nMubH|x1Y#(MYJsE_7dwb49Q zc*Q=pgXXg$)=3MHj~1r20iATwVp?+5G1doC8)zv=m9l)0+6nzKS`Phksbv@RD`@3G z04lF2W4obSMXRA#Ert%H7@>md=%l zO2=)|BwllzCR;_dvu8^^=;s@eG$3h2(v%{bp=CNRXyJL*g89$pKiU1+Y7LTs5%7BTojtLX?uCZoJA{~OvflR{0i>`luK)uC)q4ccxy{{!-$>(#8>1aUXrC`5#I+JT)aB=F$Z@%iq#%Vnbi zmO}irNh0ME$zm09rJHH9L@QH#Ewoi4RT4qNx6n3;RHu-38rv!%H3fChZ4#+TA)T~K zBDE=GJMET89qnQDu-$o+4%$n1!1iy1UPEH@`{+(UHYIo*z_W|)2BZ;q{H#fu-5;X^ z0Br`Sd8TEi6|5YjdjQ$O+Gg6*(7kj>PPtVY(ZL*S8^$BxAEx`{NT(c0p8S4#K%!j| z#hpAz4@qRZM7jYvOpjcRp{w=KNqUs^qTSNA9iZ4jN9nPv&apm;SnhP3o&eK!N~Bm$ zev+O7WEUV=*19EnA3Y7|?p5d~=>359uSCb_7(D~<0Kg4wP>Mf5&jPXs5PxDT&(Q!N zd()6{ssS=YC#-#gyAuSHDP@2T(;x)PDe+oP6{!>78LcGs!jXHe4MUn=G3~*y&i6n& z?dr5d(sdZh9s|VTQrf%$noT8Q_+o zHRu4H$$!`;@FVBJsOl%$HvkZsx#clqnyE=`YIIW7)FVSD2lft}98ghptJkY0{+*l- z=_>p`uQRF|Q8hF>7iP0yg*rMks&;jDs}l?A6pJtp@hCC{nriiFEgX(stW{}9H`M3^ z+NT=RnxR56kcwlde1cg@A(*P1>Cx~!1~m0z$e51K8!C-njD({aMWw(oF&_%cHkz&l zjd?9>>0e+*nz_Am8rNpkd$z1sJ(;%T*qUojE;*qixyQZgFl>p6+pVIlXnNI#uk6*D5vY{WoCV#rb;^>H=_`+x_$tVd=+zk~0E1LXUV>_>6{Nm@FA zu30XfCuvFm%};qu7#MT~h|9OwJgA8`a|;{R<}{rbrx^>I&eQmdH;WH*!F%HszE6>M z>ArT$mP2TPOropI@JchJl1Ic_c@KAHa_wT^0^>TIuIUL!gEDcgnb|#%&0rG(fyc#_ z{QFyv!W@u5kKt6uk*rk>xB~&*0Fi6LTd)f(Jy7sAsavmh;3q)MQ>bbrzORUq-PO=G z?ejd$D-e}aA&=kA{RrHLGn@IL zh;G2eU^I~2gO|m&(gPs)NNKOqxUOI})*C6ASL5%NKS8!UfX2ykW(Qj64(am1Z!4DB zayac^#Gh7{lYfkVy|Rup;POlli%=aMI4ObXij|S-BJys$qR5rn9{e)_7<_hO1U^Zjsql zD>iJ5Z%6Mj-QdAtEy&h%)&iXw^K(Wt8n(_0gGyOkX>cmd(;%GiI@6tq%_d>#XM!7r z4p}QY8s8uh;qZ45zv%WimZcpv+K`d-H7F$){dzrCf@|87!P$fJOg9+aFY=m>c4FZT z3Cb}67V@$6q&$p<3~eIJ4&%mL6*roGu<;BsSFR`FM3)bb3bFaYKFL`EoTe8p1UIA` z@~ZVjGeeO8Bp(PL1{)Lo&BKTO5LrJ31mdDpR*b+OAz4?8544~LxWU2m+7#2r(ex+8 zo6WV!VZo>PQybRY+*UCNRxQCOL`&@3>4nlw3@=np3msULAs=8*7by&RFdI(r6 zxBRL~vVM9E#Sz3rQ(J%6N4uk$2W#K~`6UvVi-sUqJS=Xu?f+PpD3FTyn8Y7J13v?o zs9yZ0vP?wU%i>*I%ZOd!H^lY!styc)rY9+~dN-bi(aWGgcR|CG;Ux~TSSs>5OT~?j zGV=TJ7djeAOAW3JIoI^P?4)jpBSGUy;p}{|44F;)6f^FT5N~uAkrbUxK6HGU4& z;+?sN6EVDr&&F?deVI%zbLZg*enN2{5(CLR66E$ft;mU=gr-BEV?llqo9
)0h_J$J5&_ayJ&mrfjzqC@7W1^5fb?^>||D77Rqowa4A;6$3D#+)X#^ zW&rZeTKi-cNq52ooj&_3c(7P4frZ07TRjIY+E)_~K z(0L(5A$`l^)&DlRNiOf=#%3+c4bU5Yejp1g=pL9B5%Zh(f0|`C?8Ic2_o5- zP#>9FCBwfA@H=95*K;u$>>a!hfV9N!gbLcw`Bza1F+H;Q;7|$5spY!}YWOLx-U|)o zQHM=Y@_*<3o!`q->yW0)VvEb-VYzO|1YJ-7USNS8@QL#<&iw+Alg9A8vGw6 zwg3WmN!?v?<}NwAsGK=_m-Ipo-i3PbafbH;@q1RU>k|^dmc&3LWOS@jl&wNREF4zj*-?G{dxOlmaRP zd)D~~d|xG8*?OXqrlxEI)6VWID=&sHpyz|M@~8`*r@Zivq)6)cKzw>%XABL-6d;ZM zJ!o9ErOfTQM8I4k%~h5ZUIA@8ub_z8KMx=JOA1i?GtNu)NIr~jq>cn)2P8vsHzS3f zLV;_^&U>Nn04diJXn4jRKe+$zl*72*MZ3B~9RW95xoCNU@<0=nCAA@hof8WN)A>Q0#B{8S}4q)!FJ4jB$0t{U^hc%5iFq1+@KbmhC7YHo^fNrDmBm>xgE)8 zk^Bh~Oz=Dp$+Jk%X?ZS^n@GNhFz@SLQLR(90G6wBXCeqw!-uXG{PP1&S2 zA2tpsz}zBUglDLi@G)w~Drv=%ehGE1Qel0}%W!XM)RgNb*o^T*=b8$dK! z;K;#MYJ6CO;2THsv*{Qr8y2UI?}pFc8^zfENU;q@573P!;I#Bq(|cgw$kF3Ndj?JnrPX=p_xOn=4xFm;tunD#JbAj9OvIl&b=lD* zGb52MoJyp0)!xWNdR_F4J=TKkw~6KU|BCBasatXiH2GZ^6gj&}+xa`lhI0IeNY<0O zkuKG?ECnYnuhx2UPfIxwJJWAvd175)WCufkfKy5vrQ>2g|11dTcrTPkE1;s|Z$Z=V zwi4O*kzLA|*m@huzW_0nP@*FF5kjcTtdNJ5{QRT=DvqAcA{WJ>2S#Fb$n`o9f5GZ# z29G#28id!MZz9j%Bax9R16$jW`~#BjAd#U1PhH+PX(=zq?qf)tNd5!K@*!ADmAY{H zVNr8-H+dcI)WOWd$SLEYyjZc7S7S|w^lExwF*JwoYtP~~e+E=6`s8z2>+;YDlnpCG zwzZA{;5OX}dDA@>n#0#c{u8vL$+l^Q-STwM!q4OBxS)Z5$thI$VT=djiE~F?3DbXc zt|jTT645MmNp13I;BhS!2^oRF7e!BCs_{RO<)=ubMB}{@(x@+qI|2W(wN~;olvvi1 zSV3~iW%qgy_`Z-_fX9|k3hn$oxq$n|Pvqd_rVAni(`I>{_}X|!7hVg9Ceo~5V>|H{ zmjcp`R&Ehm^1M*BzS#TF;y<@!mQ6z?YaOLr;9uey{t`GAi;u8bcy(WWl2F&KwR{k> z@oynn-iVmo&vkd=SHS(1<(()ag$|CGe-FP6zu=t_(_U-xi}MaD|27hiqwa8YY6`w{ ztXloMh~pAXm$5L1FenxeOuVG<0+Ai86P>|-6Tc1?#o%pI=hevQ49w_Iqt>7#-YL^F zI?tKR$**BI1ETa{m;=5%#$|a;7N$TWHPv2~`i_VAH yE&_b|C=ieQQzZU5()zEDWchr=2Y;N*Qhbmxvz+iZQ0R#&R^y)Zo$|R0J^v4qA9eEp delta 7256 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 F{|Cwje+d8p diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc index 9efffbc982836e1b18632a92761fe2c712ca8652..bd24f26f426a2e452895c7a7aa94012d46e30bfb 100644 GIT binary patch delta 5139 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 delta 4164 zcmZu!Z)_Y#72nzWw|73D&*$^mcmDtHoQoajU)8FvN$bQ;n%0Q|NgCy7SGL2)DL`sFsejDC6W)cgz_gPLP8Lve&7p{KmvgxR%#^>LJCNL)Xy}$_ts}S z7vE`rJM-qvdv9jm{ATvy+52+|ySX{0z^}dIPm9NgZzQ_e_>Hlva~(`E6eD7FRN6v4Gp6GTbAHJ+?doe>IPmhc-gg zd*M8cROIC!17GaufnqN_js_4@G^VjQ6FqV!_#oU&J??dcTG?CyyX;2rJ7Z}Sz|(Zy zteUQ_W1|xU2(uVl%~0PH+$|X;w=_{#66j0bkLS+fbg!{B<)U&~Ijx9ss1}&m1Ft)( z*b6UGZS)quP;&H2-708(ssez&oIkop;k#^)ycy|#Hi;%C01AOEa~|VQSzP4qrp5j8 zzmaTs!`5A`U5;vd&rxUr5d~Xb(~8M0L$}N-cf@n(Vn0H|oTRqf^pz(;jbcr*)qX$L zyV~JN>bR4MM17FD=@_Q?T)lgct#kXxX zsX!(QPaqed_A)eW`^6O{0@at`aZbs2)8KlTM+}u~3qd1dXxD?+STV}OMwG{l*hWhj zH#N01@i^!<^GH@%P-#b_KJ4jjQry=lZFxe9`x~W6lD0x`+~FWuFQ!P;2BLN&LrQ6q zw1cF>=p;$T$np+w(h6bbjIQg!VkgwH8-a8iJs`<#=tMxL*XRRD7wB~J9tyVK7ywBx zNct}JUmO72gT@d@UL7=c8zX!OO_BOAs0WR_F?u~z93hE6+FeEg)bmCFxM<9aZ)YDb zXdoAj$zQ~K-uSe>)pa1#&8_Z*bkwPD_M-R#2PmkXIEn`!LS$4~IrFO`WOKrtGnA0q~TtdzkM6z>etjUW3(XE=b1=HdpE&tv&w4Oj$ z3kXRB_N9p;m39?Dz8q$pkaI4#aohoESMc25(fWt|p* zM$v}0d~)_QzPN})dC4E(ljgjXS%oRLEDp@OF;`dQgZ9%$s_1rGOuikQdtq-zM8;^G z&9o|Y6W36qCcm69dS1X#LShCbI5sb;*Mxo9G`J9_n6ny@^IDIBsgt&Q)LyC@vqIRyKLT1X zir}^=D77PHyXx|)+Za<+@RFfpu73~uIk;i)I^#bv24`nR{wMcN3XO<9gnj_nIxowc zUAc8Sk)kl!u1VXm2O7N)-l=M!Lo6z&>)AE}=&-BrpZf$kS*{`D$+CnM$x1QN{ zjBMLpryW+1Q@w+I4M8L}FFLwesaZdfZ}!ftqmCCwekeI*yiL`ASjHpx2t3Xpz#0=x zF5oqG3omZ!#lUU$CY5dl*Vt{illmDO@}fW}tGw!P*NelnK;i zapA5A4P~@!4wjY>h;go9sR>~fA*ZYZ;vN=V2wy`8B3wnF6u@;6oe1AR_%?tSsc^?B zEpjh%!Y_!M*oMOrcmxaF6yg@bR$fqvPFoz}mz_+EbSu|G4_D zF*@gJ@HOQ8S&>(VUmw_T_dY7q${ug%CjU3wss2Tg9V7c$@4e$ACs-aAsm@8nB(!Qr z8#~_5XVs4t`7r;TX7UmeKSh=I<=W`(9FYlieyZO`qwVS==r=mK{^b4H&%Y1Q2u_-~ zjgUpSgFxv;cVy%-@goGv8p_HaW0eB<8J4!DkxH}@--m|Z!LxCBPP1cbAPGs(&EWPN z%*6#N6b^XJyizi)iH&UYb1&}8=%5l_#IhF`Vd2C{^kvG2yMDfV4T@f8&8$tp_aZPt zwPa23D`j3oUT_3*wP-;|%3l=*S*!e{(A$L9c!Bo>FDpMPq;vk2ER9mUbHNuw$>9PA zDEIBotwiCwYYtq)sZCS&EmTAnrz?`bz&MDVhVN-p728;{_#p-wbOqAra~MB~hgn>W Z14+kOn%+s)ug0RuKq8zRQr6Rv{{yP!x1|68 diff --git a/venv/Lib/site-packages/pip/_internal/metadata/_json.py b/venv/Lib/site-packages/pip/_internal/metadata/_json.py index 336b52f..f3aeab3 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/_json.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/_json.py @@ -2,7 +2,7 @@ from email.header import Header, decode_header, make_header from email.message import Message -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Union, cast METADATA_FIELDS = [ # Name, Multiple-Use @@ -23,6 +23,8 @@ METADATA_FIELDS = [ ("Maintainer", False), ("Maintainer-email", False), ("License", False), + ("License-Expression", False), + ("License-File", True), ("Classifier", True), ("Requires-Dist", True), ("Requires-Python", False), @@ -64,10 +66,10 @@ def msg_to_json(msg: Message) -> Dict[str, Any]: key = json_name(field) if multi: value: Union[str, List[str]] = [ - sanitise_header(v) for v in msg.get_all(field) + sanitise_header(v) for v in msg.get_all(field) # type: ignore ] else: - value = sanitise_header(msg.get(field)) + value = sanitise_header(msg.get(field)) # type: ignore if key == "keywords": # Accept both comma-separated and space-separated # forms, for better compatibility with old data. @@ -77,7 +79,7 @@ def msg_to_json(msg: Message) -> Dict[str, Any]: value = value.split() result[key] = value - payload = msg.get_payload() + payload = cast(str, msg.get_payload()) if payload: result["description"] = payload diff --git a/venv/Lib/site-packages/pip/_internal/metadata/base.py b/venv/Lib/site-packages/pip/_internal/metadata/base.py index 151fd6d..9eabcdb 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/base.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/base.py @@ -8,7 +8,6 @@ import re import zipfile from typing import ( IO, - TYPE_CHECKING, Any, Collection, Container, @@ -18,14 +17,15 @@ from typing import ( List, NamedTuple, Optional, + Protocol, Tuple, Union, ) from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet -from pip._vendor.packaging.utils import NormalizedName -from pip._vendor.packaging.version import LegacyVersion, Version +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version from pip._internal.exceptions import NoneMetadataError from pip._internal.locations import site_packages, user_site @@ -37,18 +37,10 @@ from pip._internal.models.direct_url import ( from pip._internal.utils.compat import stdlib_pkgs # TODO: Move definition here. from pip._internal.utils.egg_link import egg_link_path_from_sys_path from pip._internal.utils.misc import is_local, normalize_path -from pip._internal.utils.packaging import safe_extra from pip._internal.utils.urls import url_to_path from ._json import msg_to_json -if TYPE_CHECKING: - from typing import Protocol -else: - Protocol = object - -DistributionVersion = Union[LegacyVersion, Version] - InfoPath = Union[str, pathlib.PurePath] logger = logging.getLogger(__name__) @@ -113,6 +105,24 @@ class BaseDistribution(Protocol): """ raise NotImplementedError() + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> "BaseDistribution": + """Load the distribution from the contents of a METADATA file. + + This is used to implement PEP 658 by generating a "shallow" dist object that can + be used for resolution without downloading or building the actual dist yet. + + :param metadata_contents: The contents of a METADATA file. + :param filename: File name for the dist with this metadata. + :param project_name: Name of the project this dist represents. + """ + raise NotImplementedError() + @classmethod def from_wheel(cls, wheel: "Wheel", name: str) -> "BaseDistribution": """Load the distribution from a given wheel. @@ -128,10 +138,10 @@ class BaseDistribution(Protocol): raise NotImplementedError() def __repr__(self) -> str: - return f"{self.raw_name} {self.version} ({self.location})" + return f"{self.raw_name} {self.raw_version} ({self.location})" def __str__(self) -> str: - return f"{self.raw_name} {self.version}" + return f"{self.raw_name} {self.raw_version}" @property def location(self) -> Optional[str]: @@ -262,7 +272,11 @@ class BaseDistribution(Protocol): raise NotImplementedError() @property - def version(self) -> DistributionVersion: + def version(self) -> Version: + raise NotImplementedError() + + @property + def raw_version(self) -> str: raise NotImplementedError() @property @@ -368,15 +382,7 @@ class BaseDistribution(Protocol): def _metadata_impl(self) -> email.message.Message: raise NotImplementedError() - @functools.lru_cache(maxsize=1) - def _metadata_cached(self) -> email.message.Message: - # When we drop python 3.7 support, move this to the metadata property and use - # functools.cached_property instead of lru_cache. - metadata = self._metadata_impl() - self._add_egg_info_requires(metadata) - return metadata - - @property + @functools.cached_property def metadata(self) -> email.message.Message: """Metadata of distribution parsed from e.g. METADATA or PKG-INFO. @@ -385,7 +391,9 @@ class BaseDistribution(Protocol): :raises NoneMetadataError: If the metadata file is available, but does not contain valid metadata. """ - return self._metadata_cached() + metadata = self._metadata_impl() + self._add_egg_info_requires(metadata) + return metadata @property def metadata_dict(self) -> Dict[str, Any]: @@ -437,11 +445,19 @@ class BaseDistribution(Protocol): """ raise NotImplementedError() - def iter_provided_extras(self) -> Iterable[str]: + def iter_raw_dependencies(self) -> Iterable[str]: + """Raw Requires-Dist metadata.""" + return self.metadata.get_all("Requires-Dist", []) + + def iter_provided_extras(self) -> Iterable[NormalizedName]: """Extras provided by this distribution. For modern .dist-info distributions, this is the collection of "Provides-Extra:" entries in distribution metadata. + + The return value of this function is expected to be normalised names, + per PEP 685, with the returned value being handled appropriately by + `iter_dependencies`. """ raise NotImplementedError() @@ -519,10 +535,11 @@ class BaseDistribution(Protocol): """Get extras from the egg-info directory.""" known_extras = {""} for entry in self._iter_requires_txt_entries(): - if entry.extra in known_extras: + extra = canonicalize_name(entry.extra) + if extra in known_extras: continue - known_extras.add(entry.extra) - yield entry.extra + known_extras.add(extra) + yield extra def _iter_egg_info_dependencies(self) -> Iterable[str]: """Get distribution dependencies from the egg-info directory. @@ -538,10 +555,11 @@ class BaseDistribution(Protocol): all currently available PEP 517 backends, although not standardized. """ for entry in self._iter_requires_txt_entries(): - if entry.extra and entry.marker: - marker = f'({entry.marker}) and extra == "{safe_extra(entry.extra)}"' - elif entry.extra: - marker = f'extra == "{safe_extra(entry.extra)}"' + extra = canonicalize_name(entry.extra) + if extra and entry.marker: + marker = f'({entry.marker}) and extra == "{extra}"' + elif extra: + marker = f'extra == "{extra}"' elif entry.marker: marker = entry.marker else: diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py index 5e7af9f..a779138 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py @@ -1,4 +1,6 @@ from ._dists import Distribution from ._envs import Environment -__all__ = ["Distribution", "Environment"] +__all__ = ["NAME", "Distribution", "Environment"] + +NAME = "importlib" diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc index 05665c93fea7fb26ab69ca248c9f3f456d95dd22..d98babacee6ce2ad8524c93839c22efd44af5e0d 100644 GIT binary patch delta 109 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 delta 4084 zcmZt}TWlj&b?(e~JaHVyah#W9CzE%aY_haeYU!riq)oT2wye6_?LvpG%p`Z5jG3{$ zcP81y>)^CW=~iN?R`&y;0^0DBw&EeNAn}FZqX;4KhX4&9{O|#MAjBX0vz&9CY#zjk zkMBKm?m73o&pcZE!9t?a))tfC)7A5b6(e^yktOQg>G1?{HB+M!mEEYPn|BMj29aQ^ zxJj?W>=0|!O?jPWrofbjjF}PpsN3&l&8(L*bKZbC;0>CC zo?#l|neGmG!{)G9x40wTs5vUuF?Y-xH^;pRa{~4Ytu*dVdU-SNO_@_fdRd}vG_fnu zgsqgOOJ{Zza|UqjGzqw*orV1wO5Tw29sfY}F6DK;N*4J8GRGg1Jc;m8c_iJr==cG1 zmevBNQod$0AAa}+c_eY4gfZVL+68+fU>3h4pUudj{(|M(uUo-t*tTK^1qx>iWy`a9 zT*;7aKA~(!A|SBy!EcqMoEZeEc_mbR+byyI*f7N0m)I!(Ph^FhePC))LNa_Q`rP;= z(vnbj%Eb!sWo#7b#{h&ab1Qb)-l($k&+|{ByD#FCJYjwKqp(jQiC$cD-74NI%51R! zf(dwXgiUOYI?KUw#jBoQ>U5ftGc zsv@}OW%dLT331}W@gl2ug_=_>Ip z%s*~jkn^4Vz4&a8cE}V~VPt7Duzfbpe-|HFn8Rn!BIraAK`@UXir^xGLm`i^&2sPn zcm5PV-!?s*(FA50FvmVR?B?O?FY!BVR~o9_TGT{9t2@L@*zHucH9OWP6=f09h)o{D zcF@!=VmppuJ84>AQ%BBs(e7Q<>=blq;MYTY1x=U0bOWZZK{Eo?L;LMsINDcKX_n^T zSO#|e`xhCYgMi8I)5L(rphJMk0nLCtC@wopM*w30W~ek=8Uf~`bPO<~f~Kj^IGq5@ z7(GMt_BisU7m&dOFi`0fo!*U@lN2*)CX63V&``yc6KNEtoU$KSu4~hRTUoX+f0@A- z+CM{v_^tM*CPgT`2?iGA>>92P-Gzb5#sPeh|EYcLnuyP+h^|l-3Etv()d~w-XDQS@ zJFut~SnMhs2xTi^FToL^m%GX)8jcT1ybE%O6RU)FU5B-%@tSyM)4%FGp^Yn^Ik>t97-c2QBwv zby8CH$c_RQk}uVIj8)4wtg_*h*Dcqf#?4jRcF!33)-Y!I2Z<=6uo=#n&+H0-un~K~ zqNY>50GY}Xh{i-}YI9f+w5Fm>74W&pb)oGmxILmWY{Qtye{qQ_?EMS?S&oqu$v#rI zlX8OS+X>j|+cN)Y=bKLm<16g*$V%iKTK7I_Ci8LLq7>cY&!n$UiBs~CQdV^`Ux5mXFl8b+{c8(4G=v=Z$2*+^Fd5wo$F zvH!Wc>i7oyduz+9M$z)24gw{37>k%wUNH_La`y3&OL@5#o5l2)!5&g;nYC9|#PT7T zVdw%z06-B&JBM<`7d1E3{i^FUur4xD>(3&QB5V(xE3my#^Vf<+XXAuv!))PL3oHny zA7tVk;Nr&t#3Cw56P>6eNox6{xjcL1ybkIM2K=w-?uHEK@cSY%!JF5md(xg%)dK=n zmv_h(36wh70b4WSR+TwG#j*%KhX5r*UlJuiXmvb_!o;#wu9Tf+%N6bW8$j->08+9} zYW$yFdH%Jowgz$u(D~r-Lt#qT20h2O3+v5kK}Zav2fNcE$^}N>Mj5D8T&|^$+2PGa_dmdrcOWGvjz}vrvT#20lB*d|?O90fnPvKLcjMn7YjW)^}MK*VI@Ge=d`o z6_-QY0V=%v3w}FuqoE)_{NhaX4&3wYD8v|K@(#Hs5$T3ZA&*6@v2LIM z(}}SwB4)#rN%^Zz%srK=G~$pw!eHNg7DV2ciiB!3x~tdaMQI0Y#Gc_l%o>dd zh>EunV<-^)^n3pI+FDpq+D8oj6_bwHT92=$G?4`aZt0MiK6<0jX4@f5P&kJy8YEjzaV37~~t zf+AP=<{qx8`B(v=XTB+#5;xe_C9s4i71F7t4Y&SeaN zC_`8+SqFju!5V^f1UC_EAh?A9-PW|}S8#RcWU&%{Ky~oG{yYHwm%&V3EI%8z*`DRNv!3nykVN7tFdQCCZ-Cz)-h=^dkkNdJ z5c7`~Y*x{K;+j|m7%0X+Ff#l{#+Zh&5ccz*7~T9|hNcNS#rZ>HL~BFRFY(Et0j)VT z@z;iix`gS4QBwF^yfvix*3bay;@=z^(Rz?yAKx2F*Ti(hFj2&doEa@(sKaC_T$)Av wp|5keJ;ijPKIc{FnrojYK;aJq(4pEi|0YSiH3^BIl(Qrrg!0NT5muQqlI1gSu%^AZR1yP{2iViGd=>DVP2SK@W52rN{PIq(I>`eQ#)e!1bYA z?2m6|-psuB=DpwS$KU?-VlgTdas+-~{_Ts7d2G8lLFczmU&>M6vMo+H^S7gNKNz-$ zDS@Wumx2*{Bp9_vRa^Iu1Y`DCP`1meo$)I{)vhYp@W+FiT~o5@*Mp<>QIIX3^(TU3 z_Oal&eLR@7Cxa<_O7-Xb6T!4SO^K`R%(y3asXfbw+&P|iuYRMg^8zn!>Gu3{gb(x5 z7U88$W;a~2e2P;(@*V}%ygOGTJkKd;kMbj1`X;qcgZ>yVgMQg9Z))~Jx=24=(B;t6 z4u8>29PT8Jw4Qci_qvlT$!f<lsSciix>najmEIGRxUrjglMWO~UDV z<|mok!-M}j^bYCiJ+hqpF%gTmhf&%Y>gl_bk{;`6ZT15~32MJe8v5FaXT6Y5@$}E; z_BwDx+Q)CywvCeBYjj&Ct<`EBC(0{*zst!|)!vC>7yV!9< z_noe|#XWzdl;&i|e>%4Li&jQk;82U{J+40v`NeL-WvvYP#XO9jCP_ znU}~626J@~J!Sm92XbU^R&J*gL+V2%i2&A&adozlr|Fr}U#i!j(XhnJxY-*BuOM7c z>mv&(J{qq{e-V-jHs;Vpm$ zJLK*|9%WTL(V?HF<6}=ip>lr?CBXd)bJz8_OD3j^4SvF0oSS)VWESVgOpEBVTJC11~r*|b`oJdJen zeN>zPNPrJ|fKD6<&$(K-73#qUehl;e)ha~>Kw#D7l1?# z3AgJzEjNIJmS!gkT{ujPU%cXq0%(X62nWW_q<<~ftM5Z+oCjbm2W5#*?!H(`3zbhG zY@b)oJocb&jAj?eHr@;S@XizpbF^857o_;>r5jqgI_Hpx1~Zkawq-kM%#J-Wks zY?oe!*gX%N32hDAFq&J}fUULV%qFs`rWmyX@0L`VuxP zb?@*%@t(P_>Z6*V=A%@gXVx2i+~nQr)zWc zVtS=^>@lR|1iaX!zaT#&Z3_1%+p>COhwhSR2;4j@0e?B!WRNM^OX+sL+((j(j|03* zdgwOo(Pi>;a*GKFk8&F(JaFlv!V_z!wliRH)oU(;nrLv=)PiulVjI3K}sIq6LwKXBI&{Q?$fN4DaMT S9f$uM8`X-roEWEL+5ZA>MM{+b delta 2284 zcmZuz&2JM&6yKR$+v|<(*onQd9XkmmKnyKk6{tX(mOx8@3R*xF+5*OS)`^o{JIroc zsGJ6rNc6%14W&}6Rv`7l0op2u_SQ?)KcK2qX)jcjdTP~EB_z~JeQ(_0C}3%Rc{B57 z-kab1*xVU=us_j^#|;I3nZBQ=`U|%b1=4eC+xQ}NbT?{6UBfcmF00FpSurU6tFE9s`Jl$>i$kK1eYx@jvd=OHKKnwBZ$u+!&et*n$IPR`9+d60D$b^6_c zRd9<|(H*b` zF4r4%zg*rfUX7Fn@un&TSp9`S&|p+yco)Qt$i{=k1?p>ls705^5?N4NYD<|3zo+ox zY8b_u&Qxrfn;-#?~aNhaG#WQoS0`x*vp)psQ_0);v|DdU_#Hye7U){?>OCPL*_i z9Irf$@Fv1B@pbBjJ(Aq;8WU3CBq#(rgsaJYn?LV*lkk<%o&)qazCd~#gz6rc*b1VOAA4%b`%pYg?}hsKJ-u&nD<0j3fDUrZeVziay54BcH`poL zn|FL(!sQ7BEEX=~gPn=Lgm45wdV@Z23!!7Y6Xg-uKvz99r7Mt=v7|vw)l8W&Gi%23 zF+L(5WClxEg@;fv58x||w3N>jMn6}X3hhn1sbaf=(h7;knGrG~3g&Rv_L3Texn1#^ z4e_>V9_4X3%ZCs;zQ`VsDcdfz0AQlb>^W|?E9oX^diW+vu}mm2{^i&Ou%U>b%#VSu z>An|tU>=u95H8O_lk!&iwqbRh8Ohlv;)lMYJMqkY8mQh?PX-Xqt5wHacOZx`yH)|V zKNYWJ&+fuQdfNW6w1V=IG+0WN7WwSq9F5u_^isAu!_n_M>Y zCG2=f0D3J9EhkA5M5p4{+-7n@MDoSL5NzF0Y6LzIbXjjHca?j}VFh|8^@*6w7Zx!I z(YS}~`q*{D}5j_i~iyDX5m7ybk>Y^J<^ zX&#&AeZrBaHvect_Mfjn@DczKdQF2Yh>1t}eT0gE{@kI1uv}8xwS`B6h+FZi)As){ zoP#AUb1S*})mpXn5VkxWK(zWx`FBzA9Kv~o5W)mPNqpaLUYtP@U(Z#9SpwrSHDMTyEJ^GC0mQA%2><{9 diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py index e087980..ec1e815 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py @@ -1,5 +1,17 @@ import importlib.metadata -from typing import Any, Optional, Protocol, cast +import os +from typing import Any, Optional, Protocol, Tuple, cast + +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + + +class BadMetadata(ValueError): + def __init__(self, dist: importlib.metadata.Distribution, *, reason: str) -> None: + self.dist = dist + self.reason = reason + + def __str__(self) -> str: + return f"Bad metadata in {self.dist} ({self.reason})" class BasePath(Protocol): @@ -34,10 +46,40 @@ def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]: return getattr(d, "_path", None) -def get_dist_name(dist: importlib.metadata.Distribution) -> str: - """Get the distribution's project name. +def parse_name_and_version_from_info_directory( + dist: importlib.metadata.Distribution, +) -> Tuple[Optional[str], Optional[str]]: + """Get a name and version from the metadata directory name. + + This is much faster than reading distribution metadata. + """ + info_location = get_info_location(dist) + if info_location is None: + return None, None + + stem, suffix = os.path.splitext(info_location.name) + if suffix == ".dist-info": + name, sep, version = stem.partition("-") + if sep: + return name, version + + if suffix == ".egg-info": + name = stem.split("-", 1)[0] + return name, None + + return None, None + + +def get_dist_canonical_name(dist: importlib.metadata.Distribution) -> NormalizedName: + """Get the distribution's normalized name. The ``name`` attribute is only available in Python 3.10 or later. We are targeting exactly that, but Mypy does not know this. """ - return cast(Any, dist).name + if name := parse_name_and_version_from_info_directory(dist)[0]: + return canonicalize_name(name) + + name = cast(Any, dist).name + if not isinstance(name, str): + raise BadMetadata(dist, reason="invalid metadata entry 'name'") + return canonicalize_name(name) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py index fbf9a93..d220b61 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py @@ -1,8 +1,8 @@ import email.message import importlib.metadata -import os import pathlib import zipfile +from os import PathLike from typing import ( Collection, Dict, @@ -11,26 +11,32 @@ from typing import ( Mapping, Optional, Sequence, + Union, cast, ) from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import InvalidWheel, UnsupportedWheel from pip._internal.metadata.base import ( BaseDistribution, BaseEntryPoint, - DistributionVersion, InfoPath, Wheel, ) from pip._internal.utils.misc import normalize_path -from pip._internal.utils.packaging import safe_extra +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file -from ._compat import BasePath, get_dist_name +from ._compat import ( + BasePath, + get_dist_canonical_name, + parse_name_and_version_from_info_directory, +) class WheelDistribution(importlib.metadata.Distribution): @@ -91,6 +97,11 @@ class WheelDistribution(importlib.metadata.Distribution): raise UnsupportedWheel(error) return text + def locate_file(self, path: Union[str, "PathLike[str]"]) -> pathlib.Path: + # This method doesn't make sense for our in-memory wheel, but the API + # requires us to define it. + raise NotImplementedError + class Distribution(BaseDistribution): def __init__( @@ -109,6 +120,23 @@ class Distribution(BaseDistribution): dist = importlib.metadata.Distribution.at(info_location) return cls(dist, info_location, info_location.parent) + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> BaseDistribution: + # Generate temp dir to contain the metadata file, and write the file contents. + temp_dir = pathlib.Path( + TempDirectory(kind="metadata", globally_managed=True).path + ) + metadata_path = temp_dir / "METADATA" + metadata_path.write_bytes(metadata_contents) + # Construct dist pointing to the newly created directory. + dist = importlib.metadata.Distribution.at(metadata_path.parent) + return cls(dist, metadata_path.parent, None) + @classmethod def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: try: @@ -116,8 +144,6 @@ class Distribution(BaseDistribution): dist = WheelDistribution.from_zipfile(zf, name, wheel.location) except zipfile.BadZipFile as e: raise InvalidWheel(wheel.location, name) from e - except UnsupportedWheel as e: - raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") return cls(dist, dist.info_location, pathlib.PurePosixPath(wheel.location)) @property @@ -138,27 +164,20 @@ class Distribution(BaseDistribution): return None return normalize_path(str(self._installed_location)) - def _get_dist_name_from_location(self) -> Optional[str]: - """Try to get the name from the metadata directory name. - - This is much faster than reading metadata. - """ - if self._info_location is None: - return None - stem, suffix = os.path.splitext(self._info_location.name) - if suffix not in (".dist-info", ".egg-info"): - return None - return stem.split("-", 1)[0] - @property def canonical_name(self) -> NormalizedName: - name = self._get_dist_name_from_location() or get_dist_name(self._dist) - return canonicalize_name(name) + return get_dist_canonical_name(self._dist) @property - def version(self) -> DistributionVersion: + def version(self) -> Version: + if version := parse_name_and_version_from_info_directory(self._dist)[1]: + return parse_version(version) return parse_version(self._dist.version) + @property + def raw_version(self) -> str: + return self._dist.version + def is_file(self, path: InfoPath) -> bool: return self._dist.read_text(str(path)) is not None @@ -178,7 +197,7 @@ class Distribution(BaseDistribution): return content def iter_entry_points(self) -> Iterable[BaseEntryPoint]: - # importlib.metadata's EntryPoint structure sasitfies BaseEntryPoint. + # importlib.metadata's EntryPoint structure satisfies BaseEntryPoint. return self._dist.entry_points def _metadata_impl(self) -> email.message.Message: @@ -189,15 +208,18 @@ class Distribution(BaseDistribution): # until upstream can improve the protocol. (python/cpython#94952) return cast(email.message.Message, self._dist.metadata) - def iter_provided_extras(self) -> Iterable[str]: - return ( - safe_extra(extra) for extra in self.metadata.get_all("Provides-Extra", []) - ) + def iter_provided_extras(self) -> Iterable[NormalizedName]: + return [ + canonicalize_name(extra) + for extra in self.metadata.get_all("Provides-Extra", []) + ] def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: - contexts: Sequence[Dict[str, str]] = [{"extra": safe_extra(e)} for e in extras] + contexts: Sequence[Dict[str, str]] = [{"extra": e} for e in extras] for req_string in self.metadata.get_all("Requires-Dist", []): - req = Requirement(req_string) + # strip() because email.message.Message.get_all() may return a leading \n + # in case a long header was wrapped. + req = get_requirement(req_string.strip()) if not req.marker: yield req elif not extras and req.marker.evaluate({"extra": ""}): diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py index d5fcfdb..4d906fd 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py @@ -1,5 +1,6 @@ import functools import importlib.metadata +import logging import os import pathlib import sys @@ -14,9 +15,11 @@ from pip._internal.models.wheel import Wheel from pip._internal.utils.deprecation import deprecated from pip._internal.utils.filetypes import WHEEL_EXTENSION -from ._compat import BasePath, get_dist_name, get_info_location +from ._compat import BadMetadata, BasePath, get_dist_canonical_name, get_info_location from ._dists import Distribution +logger = logging.getLogger(__name__) + def _looks_like_wheel(location: str) -> bool: if not location.endswith(WHEEL_EXTENSION): @@ -56,11 +59,15 @@ class _DistributionFinder: # To know exactly where we find a distribution, we have to feed in the # paths one by one, instead of dumping the list to importlib.metadata. for dist in importlib.metadata.distributions(path=[location]): - normalized_name = canonicalize_name(get_dist_name(dist)) - if normalized_name in self._found_names: - continue - self._found_names.add(normalized_name) info_location = get_info_location(dist) + try: + name = get_dist_canonical_name(dist) + except BadMetadata as e: + logger.warning("Skipping %s due to %s", info_location, e.reason) + continue + if name in self._found_names: + continue + self._found_names.add(name) yield dist, info_location def find(self, location: str) -> Iterator[BaseDistribution]: @@ -142,8 +149,9 @@ class _DistributionFinder: def _emit_egg_deprecation(location: Optional[str]) -> None: deprecated( reason=f"Loading egg at {location} is deprecated.", - replacement="to use pip for package installation.", - gone_in=None, + replacement="to use pip for package installation", + gone_in="25.1", + issue=12330, ) @@ -166,15 +174,16 @@ class Environment(BaseEnvironment): for location in self._paths: yield from finder.find(location) for dist in finder.find_eggs(location): - # _emit_egg_deprecation(dist.location) # TODO: Enable this. + _emit_egg_deprecation(dist.location) yield dist # This must go last because that's how pkg_resources tie-breaks. yield from finder.find_linked(location) def get_distribution(self, name: str) -> Optional[BaseDistribution]: + canonical_name = canonicalize_name(name) matches = ( distribution for distribution in self.iter_all_distributions() - if distribution.canonical_name == canonicalize_name(name) + if distribution.canonical_name == canonical_name ) return next(matches, None) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py b/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py index bf79ba1..4ea84f9 100644 --- a/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py +++ b/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py @@ -3,11 +3,20 @@ import email.parser import logging import os import zipfile -from typing import Collection, Iterable, Iterator, List, Mapping, NamedTuple, Optional +from typing import ( + Collection, + Iterable, + Iterator, + List, + Mapping, + NamedTuple, + Optional, +) from pip._vendor import pkg_resources from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import InvalidWheel, NoneMetadataError, UnsupportedWheel @@ -19,13 +28,16 @@ from .base import ( BaseDistribution, BaseEntryPoint, BaseEnvironment, - DistributionVersion, InfoPath, Wheel, ) +__all__ = ["NAME", "Distribution", "Environment"] + logger = logging.getLogger(__name__) +NAME = "pkg_resources" + class EntryPoint(NamedTuple): name: str @@ -33,7 +45,7 @@ class EntryPoint(NamedTuple): group: str -class WheelMetadata: +class InMemoryMetadata: """IMetadataProvider that reads metadata files from a dictionary. This also maps metadata decoding exceptions to our internal exception type. @@ -71,6 +83,18 @@ class WheelMetadata: class Distribution(BaseDistribution): def __init__(self, dist: pkg_resources.Distribution) -> None: self._dist = dist + # This is populated lazily, to avoid loading metadata for all possible + # distributions eagerly. + self.__extra_mapping: Optional[Mapping[NormalizedName, str]] = None + + @property + def _extra_mapping(self) -> Mapping[NormalizedName, str]: + if self.__extra_mapping is None: + self.__extra_mapping = { + canonicalize_name(extra): extra for extra in self._dist.extras + } + + return self.__extra_mapping @classmethod def from_directory(cls, directory: str) -> BaseDistribution: @@ -92,12 +116,29 @@ class Distribution(BaseDistribution): dist = dist_cls(base_dir, project_name=dist_name, metadata=metadata) return cls(dist) + @classmethod + def from_metadata_file_contents( + cls, + metadata_contents: bytes, + filename: str, + project_name: str, + ) -> BaseDistribution: + metadata_dict = { + "METADATA": metadata_contents, + } + dist = pkg_resources.DistInfoDistribution( + location=filename, + metadata=InMemoryMetadata(metadata_dict, filename), + project_name=project_name, + ) + return cls(dist) + @classmethod def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: try: with wheel.as_zipfile() as zf: info_dir, _ = parse_wheel(zf, name) - metadata_text = { + metadata_dict = { path.split("/", 1)[-1]: read_wheel_metadata_file(zf, path) for path in zf.namelist() if path.startswith(f"{info_dir}/") @@ -108,7 +149,7 @@ class Distribution(BaseDistribution): raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") dist = pkg_resources.DistInfoDistribution( location=wheel.location, - metadata=WheelMetadata(metadata_text, wheel.location), + metadata=InMemoryMetadata(metadata_dict, wheel.location), project_name=name, ) return cls(dist) @@ -147,9 +188,13 @@ class Distribution(BaseDistribution): return canonicalize_name(self._dist.project_name) @property - def version(self) -> DistributionVersion: + def version(self) -> Version: return parse_version(self._dist.version) + @property + def raw_version(self) -> str: + return self._dist.version + def is_file(self, path: InfoPath) -> bool: return self._dist.has_metadata(str(path)) @@ -194,12 +239,15 @@ class Distribution(BaseDistribution): return feed_parser.close() def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: - if extras: # pkg_resources raises on invalid extras, so we sanitize. - extras = frozenset(extras).intersection(self._dist.extras) + if extras: + relevant_extras = set(self._extra_mapping) & set( + map(canonicalize_name, extras) + ) + extras = [self._extra_mapping[extra] for extra in relevant_extras] return self._dist.requires(extras) - def iter_provided_extras(self) -> Iterable[str]: - return self._dist.extras + def iter_provided_extras(self) -> Iterable[NormalizedName]: + return self._extra_mapping.keys() class Environment(BaseEnvironment): diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-310.pyc index af030fa7a08851e5166d22633dbd07ae0ef27fdb..56f564191219d6dac1052275dc3d92f3e6c5455f 100644 GIT binary patch delta 18 YcmaFQ_@0p~pO=@50SLZ5p2+nS05Y@%*8l(j delta 18 YcmaFQ_@0p~pO=@50SH9JCvrUn04pB^DgXcg diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-310.pyc index d77513c0146982a8d826955d3dae6e53a560a22c..05e7b19a8f5216fbc15d0dd0d03dc134dc191c6e 100644 GIT binary patch literal 1211 zcmZ`&%W4!s6s_v_JYqB^ppr_Lipo^Y&`D2sTU7}-%r4pb z1wl}E`5#xk&B~=47g>3#=fM!Pn!0swJ3w=dID547@qI2h*CXr~oBc0|i z+(2tP`t(;|oKmt1KH$2&;#llO3ffhxu_@7sgREkdw|t`itZ5-LdI zd;r+Q9RlVLnt0NefpB+;3^95bBaHqo5w7$FR)sGk5r}XQ3BbGXl7}I($XcJ>a-` zv;U%3s>0r)d(i4AlZ=;X?@Z=ry@T|qr&A-Jmb`z$hf?>-wA^87Zlub2wlgY(%=FGe zwQl*jiWt^Y!`OYx)sntL*YJ%W|1%fe`Sw1=)_Jr3La$8(6LL&09q2`l=_P6eql3}? z8q~^+*W(3<_{ofUJoaL4;v3pgw&FTe-NjJTo|-j;RS4;Yx15ViL!X-EQsmM^Jj;nbBNy&!}TLWmv^0*V9@hgBrYtet9GXLqrkiiU7% zB~JVY;MV`c$p>QVGPxHb}; z;89-e!2j|?xp$8nDK^R>?8(RZtGviCdT}&o3-cTtNm43E>Is_qTY%ytO#|V}Py{gH zRuPHDp!t>zsA!6%gEnH2;lL9uapE9Io3mA0bYQjgmINei0miOdc~BV3mEtxpiw$0g zTyQJL*PqHtOCt+wVjfqe1uy3+zLL#DuEc{<$N55bFY#Sa@S${#U8xP6=K=*4>j(
6Z%2S4KNcrA&gi$@%GX4CO%l-2K!_?oRDn-(}U>`d>aY+ zuI>(0k2u@i@exknc~JIjT(pR)ZJh+gbT1jGpeL^O~xS0GNwa7kpwO< zQVss9;gGr|Ha(ZIL-PH}#;ty(%Waui(+56ZD9L!0_jhHn+kce5=$qWiYZcFS_?9&N zDzDbz7AtkZ)%vg$QknH5W_#71?!w(|qyn9YwrE5nuS-4J`Z>OIY|DCc+!=+G`9L4* z*ns(M8H}LskvgDsO5X>+CT*PDKK9hL*O&F1tMPA}+&K(f1g#%(`wuDlB;24+ADJ`Y zA)y+?#MoI_eZ!X*(An?D|7)41{I?d3wLr7Sml0Zg#9h2LYi#`bP0TIWM6W=oK8NNn zWDUlQ1z@YVcLB_J^;i;s+Bz;dfyJQ08FMYhpm8H;G;?jnUXHk$?ZC03%-}Of#Hi95 zaD6yHqqghL>htJb1mik08D&x_AnG^5Qy78-);h%3V^9!HV6W+2^17|Fje2J@X{M_n zs2)hV5T))-RR+56%{A`fDVXdo)PZy5^`^?})sGaxxr=}9k8G~YEK1|+tZ!TZS;L)n V`Sz5JJE%B=@4QXgUYjoazX0g+UfBQu diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-310.pyc index f73f9b3108cca61578f600a17b2e15656de590f6..b6b54b3325893381f13c349ac7a07acf6fff137c 100644 GIT binary patch literal 7381 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 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-310.pyc index b4bf1c7ae9883bf1147069078d01f192f42cb595..6594b7526a3650e315bada9ac5d29d69c042b9ce 100644 GIT binary patch delta 19 ZcmdnNxr37{pO=@50SLZ5-pI9%1pqPi1!e#M delta 19 ZcmdnNxr37{pO=@50SH9JH*&3G0RSko1GxYI diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-310.pyc index 802f86e3d9bc26bb03545fb846198f508474259d..946de3c653f75b461d432eb54dd515d1ce91f279 100644 GIT binary patch delta 294 zcmdnSdytnepO=@50SLZ5zLL(wy^$}4iHi-$bq3<%gvm8b^7S>0Sxi98TqF)6vsm&N zQ$T#y8pZ`|3mLN5Q<&$l)`CTf^nl_VMS3NiAi9~chAD-`hM|Tjm_d`(uS(P}Um+#G zJTE6dF(p1TFD+joEx$;?O_TK&FN*Lj&dlQYl+2>ks8 zUAI_rGV`*Fgn`V-k<5mZConsSiU2txOdM=1ECS3dEF8>iZ+S%dCO>7)XEdA~%3{N) xFnJP-HlyC;eJpj7%0RV6JRkzh;svq9frQrNP}Wv91u%E=16DmonaTWY%K=f2Nm>8^ delta 245 zcmX@eyN#DGpO=@50SH9JucTXYZRAT~;$j7Ioq@PGVsZ_Wyj=-X4PzE_Gb4~>sbO5e zx{x7@Ern?gOD#y8rAP}%vKMKUaFlR@Sj~(;l}stjHVidP!3>%#lOHlkFafDQOfr*| znN3A+u_Wc^=iK7WFUm~M%uCFP&&kZoo}9sK$jXwFSzI!C2D7uU5YTcFCJr_Z78Vu` zX0{JJLPC>2Fy}KGOip02VN{$vmqnXVd-6$^I!P6v$|4>R0cP=nSYkjzeR2Y8E1M#i TJGqxld@>W8IHTlbDYoSR-Ca0X diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-310.pyc index dfebdef75036ba3da89f83398e29f69eb58ebab5..63f6f822bec07646899658ba3115e5e63daccad9 100644 GIT binary patch literal 18664 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 delta 4845 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 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-310.pyc index 2c2ea5a5bd032be86f7d18168790ba03fae66c6f..991461972ef46cc0f6eef25c69a9da846a765db6 100644 GIT binary patch delta 388 zcmYjNJx{|x47D$pT+%jtv<$#Mh*%k;!hpnrDj{IW5=HeU38%EZdX zf8b{@W$nbo#*9-%6+YR|KKtI&`A5AfD#Ne?Y`@E|$&mn9HpPFFTpY98Lkp=M6f8!cgKvHf5!L}^vuvDa)<#tq4|P?*AnSk?<-EMK{fD}^t!pG+HaMc|}u4yLf o?)nSb8eSQgjV3eAw4~cy50NX|Y+FK4F}t&ae;i~>w*UYD delta 523 zcmY+Ay-EW?5XWa{_x8?9V*EhtMC^i)Mz9hISlGyc1T3z(BD;x!e867P$UzFN1-Un{ z%RAVLFJN`0K7h5KI1>n5X8HfvVgEa`JNN#FAB}6Z5GZzbUwdx|@Xkp&Bqc3Ux<@b& zLl2C26tOr5gGSzgk+&G5QEg~=59UeC^CNM1)gkvvR4Hqb(qn>!SWqoAB9>OgoNJZr3Zve zWRO6HM3G4%W{M~?kEje#9}zi0&W0{jY6o4n(y?A@IR_W!&v@A^f+XpW`jaHt<~}@9 z9caNT6gTyD=h_Z!bLq(wyqGzjh+}676;6EuAEx_+0F+P)IsQ=MFDm>&55H047y9d; o3wP9zZiCEjlfm~(H5V-d@n!=_K+I~M=e_;CkKdc;{cP#+ z;+3>qb`h-K9zEk?Rbqh*!Z^sX2j6`({s1giTcme+5^BWx zRRU!Tc6I=Qqb6pkNj^jjH;oQr zV@(;*F|h*riFgi9s;<5(l8pVae+)hO=kc#f5QBp9fTZ(2pZYvWml4oj8a2AA;vy&@?RQb>L zGc*4wv6eUN+T1k=nXQ7LnBppSv4fA-of{ZW=bx8$D`&--w+5-?g66(^>8aOrHATFF z?NqM|rMLQ@_M?JVe$~CVdY0}5Kts#k{I`?45l5K}(_VjboIiH2zo>guC*oxdJ52zF z!mltC$rkb%Zvl7nd)_O?cD#dK4p`G3Wp{84{AW2dg$S6&+R!h;FX&Ni9_?z~) z+)bHyUZY>tVoQs&N>3>X{Uxcu&a}xzlsMEUK6Hl=7!N}Jv<&iuQ1S;c{olt^^~Glk zmwHXqz(Lt@+UZ0|N6djHUe_icS`g+AE7e;UT!DlfNfcv(!BDs{NL4z+M0-qyxq nm^8WnW38NxUdjeB-^75(^b|VC0n+;M^+R+MX0S^fql*6mOOioP delta 1433 zcmZux&2Jk;6rY)${qXuDX}W2g1PMY7t!ZVIN}!5FAqWs3s&dJtwS-p2GqyKf?`~(t zB2;TxkN_tH)&2oEH*!Pj-@uIv5*JpgREZNejvPwGn{~lS)v@O1d2il(^WN`0`|q`{ z*RRCYs*7MPul&~k@f<>bXyNoSK-hsTkM3XLuMHR5ix_b{J;#@har^uSh}q0JLd-cN zZI9tS)GYm}-FNRlyfx|S)9Gb{umfAB035Y3Lv6xv+hBwlebT1fWQ1GXUPa7!`b`N2ylNBDNONmeJ8 z;A$kIuCDUGrIVzv--Ru|1n8r&k>dBzC-pH+=@c=1jKzw=DI_#D71=kYG&Qv@HNnD| znkhZT7~Q4HIz)0)*;6Masc}pohBv0FwC_&K+J=s;)XM%M>$Z^+M!zMQXZ*5xLPQCk z6}mCah1`{@Bb59sPy=CsDkrhbY0^=H+~Nm;R5G_ZNx~y0%*>-7R_)yAhVp5QETY%& zM)m{s%d6llF9Xn8Rx%sJdXl|vdXwEV)oUgQ?4tTbIHWj5K7#y_5AE7RCwN!XK;JZS zDtXwO=PEWpJ%g9wlsmp3M1k`CcR-SwQp)jT7GTeQRd(;C=HBzAhSI z)x<*g;DqF)buBkWB78P-X{*m8evpXmLH5Y{m}#bjegMb{hDpeM?WBW<3mR7Rl><7N zgn<&8h}?>}3gfO=(+2Ar&KK%lEQTGG)BQMzirSi%cm-~<@9eF&o~dx9&y_!OP@MS? zuA_oDk{^M+yb3@u#U6ICLmrsUZH&vAUm7gUb29IaV#S4#{a$+E#W%s>6n(Yf9mv>E zK2HK&j>LwRP6X-3nnMy74gC{v!L?y?MD9B2rW!{(qoJW`2dD=v6&? z=++m85Ugm_1>39MYh=H=4brS+-;{4m@^UxqNIB$c5Hq1CL~LugsNq!&Z)kX1!#v62 zq#qCt0Q|qq2GBv2IFt~AEkd4H2Kk53%42eAF1e3u&RV1JYAy>8U5Ad@VchQrQD5k> z6gL3!3J?YPe XA?pARa&Ylkz!h8}@WG4NB}>M?;|Vv! diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc index bdba56f9530b2ca22ad7e8b1acc8dc837643e693..8ebbf1d4af5fdfe8c736d55102106a2acd80ee62 100644 GIT binary patch delta 36 qcmZqWZRO?7=jG*M0D^CiucY7K$ZN#PC^gxEbulByf{ delta 36 qcmZqWZRO?7=jG*M00L3*E9u1>d5u^ZB_=ztE@ot#{DgG@BQpSumIzM( diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-310.pyc index 39b7339fc40e8261a3bcd3ea24b011766685a8aa..58284966eb9aaff8d19ba1704f577a866f1546b8 100644 GIT binary patch delta 1286 zcmZWp&u`pB6!whAUaw<2n*i-**`#i14{poCnL>LA2nnHplz=L$s%6%bjZ@oe#$#_&n6_;zmg9M@jVjvt;-TEdy zMY8&LI%0cTU)>U`kr~Y-v!e=V$lwY+dN63K9G1`Tw=P zh%j}a3m*gYD}1*xfVT-hge6YE{sznnsiWU8%^~!$L+reUVI6Z5Y|GG%vHDH6sx3LRctTD4ux<7tDZ(KCUXh zPlMJlyzN7!H}fMdqiQT9pLN4U@T__uY}3>&pw^Pt#L6p6g4Ce z@pPcB!(4?~A=i7_ww90yFe}NP_9OjCyAJP2twU$hYuQIv zrqx;htBLdlmlIJ`e(Xcr4s6>$7#mw@<>N0e;V^L_ec;hAxlnW#Lq2%sx(3u^??I1p zDc%MxATzEGUBv>HFewx}AI#|a8qZ{cunmux^xDcRtQ`2y+yk}-Bk0tB&#g|eBZUE? z(bGbTV`v5_5Kq-17;5jJcwUOqkVb+3EjTN@PD^9NGN?-lKJ0-_=_604|J#f{G!6QI zn)ZD!SbY7+l8OsFDvs9QJH5A531P2H%RvM!mW;)qjE7g^QCf@!szuEDu5;E@J!RFV ZyVAptTcNyCR(;;>+Fjz%4t2<){scJ68>IjM delta 882 zcmZuvOHb5L6z+ZWHPe=n*YFwy4UuMWV#3xyl!Y-tGy%bMGihk27TZp9TZps5L^m$U z-MMsQNQ@hH{s`T;@h%K5{ShYKQxFpL-sH{=wM+^0F1VVYMVRz1E1VaADvpF>g-!FO9-(o5s5fzq@OS!mG{Q?`wLK|$ z7Yp3EBWUikl1)Qa1vAnT=G`dF!k0N)dB}eltBq=kafmq|;t~4r)C@i}`?8uM;GHRMe45T3g%Y&%A z{CC})9ozDmjD0dFpZBxQ-z=AI$m2Tvp1rmX3uY8bkvJ<^3*1`(DnJ|Ha@dQ#GgA^U zN&#IO3dM$sEiUZV&BgK2igj%^COM&%gFMb6hNZ&@0Oj+}98&pxXKAHc0<1$!4blDCTgR|!VPSpVe$v^!?XAR diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-310.pyc index 041c468f233e0bf47b3cbf58c208b19925132a4d..8ea527d88c1d6518199a17cd653ecab0cf5bfe63 100644 GIT binary patch delta 1614 zcmZuxO>7%Q6rP!#wbvVa?U*!e(gNEkfK7;13Kg_Oi3n9_D+oad0%^f)G81RR{&jYp zG?qg^sYHe7A=*o&ijs&69FUND1R=qJOHW9M!=8}1aN>jz2h{Rrox}k((!R`l?|bik z@6Gf4F!a-7hF>V?2>$;1?dQffy<5gH>}`!a`<#vu!z|-yZqHm#dRCpho14p}=d4q3 zjX49O7ZKA~?kZxrO)^(xWj9+J746|?$V5?v zeq>V$e4&BkTV!%$U13UFSwZ5BRwl}}@g~M-7J0)IMcUdc7_C!`T1TQB%e3)L!m@3; ztTSx@-GtsgRhiCuSe_NG18Nq%g_yBU->071`M-)+QCrzonZoD}S%*5;P`#&3wka#_ zU^wU7uS%t~gSQK;H#HflyL`Y>Of3%_u#`SRiL z9mf>bWDbl+H`!&JXgjnmoRZV&G zW+hqzX0Ejc;g_2>kZ1q|9Jw0D7Cxz}p)&);g z*NPUFL=A^c{LWOwt5y!2$HXJE!!c+YA8;q%@K%#)>~pN8IqCjHbBjW8Zl zD;t9{=BTvg? zEkE8*NjZbbJsrM2LiD?Xhthy*NxUQzz8rsD8mkt3XK|Beb_CFBCt0MlIx2;JL7v|gdzWLtw<_+`y%L*i3ME9wyE-x*V%7W%S|cR$5Y2t*__A)|KOP-kUG7&7o#dAExe<+ z`hC1dsMbOp*@ot5o1M+d4%bT80!dQKTuW>?V|R!v7@Y7mz6E>iqp6pC~VXW$U^%bA@0y_YZg$l!!wAXaqw9EqF zZ9-52X()wKs`#$II|VzTDoqb+BZH{cELK>ZZ8YH8KN>Rwr={?~I?{B68S&G|pwWG5 zKE-)QsvN{YEDsr(BQHeFBbDIJ^AbwpyzPxfgA{=K=kPtjTBG6frW}E?4Y%gi3;S>F z+v+g%I1rD>=sDsOZKCZxCuX~6PaYnl)1srCgqo~))tyDtBJBQB0BvY_0ri4a->WzI zg|=&FR`c*ojNTC6ddiz8Kywx#2LP{*p96?V2vx8dhZF-80pL-FWXbodyaajYGTU9a zE;nqsf*}cpLJ+|i5taN%>dADP;G~A|Z%eKe#@4TazNoK||z&z}GQ diff --git a/venv/Lib/site-packages/pip/_internal/models/candidate.py b/venv/Lib/site-packages/pip/_internal/models/candidate.py index a4963ae..f27f283 100644 --- a/venv/Lib/site-packages/pip/_internal/models/candidate.py +++ b/venv/Lib/site-packages/pip/_internal/models/candidate.py @@ -1,34 +1,25 @@ +from dataclasses import dataclass + +from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.models.link import Link -from pip._internal.utils.models import KeyBasedCompareMixin -class InstallationCandidate(KeyBasedCompareMixin): +@dataclass(frozen=True) +class InstallationCandidate: """Represents a potential "candidate" for installation.""" __slots__ = ["name", "version", "link"] + name: str + version: Version + link: Link + def __init__(self, name: str, version: str, link: Link) -> None: - self.name = name - self.version = parse_version(version) - self.link = link - - super().__init__( - key=(self.name, self.version, self.link), - defining_class=InstallationCandidate, - ) - - def __repr__(self) -> str: - return "".format( - self.name, - self.version, - self.link, - ) + object.__setattr__(self, "name", name) + object.__setattr__(self, "version", parse_version(version)) + object.__setattr__(self, "link", link) def __str__(self) -> str: - return "{!r} candidate (version {} at {})".format( - self.name, - self.version, - self.link, - ) + return f"{self.name!r} candidate (version {self.version} at {self.link})" diff --git a/venv/Lib/site-packages/pip/_internal/models/direct_url.py b/venv/Lib/site-packages/pip/_internal/models/direct_url.py index e75feda..fc5ec8d 100644 --- a/venv/Lib/site-packages/pip/_internal/models/direct_url.py +++ b/venv/Lib/site-packages/pip/_internal/models/direct_url.py @@ -1,8 +1,10 @@ """ PEP 610 """ + import json import re import urllib.parse -from typing import Any, Dict, Iterable, Optional, Type, TypeVar, Union +from dataclasses import dataclass +from typing import Any, ClassVar, Dict, Iterable, Optional, Type, TypeVar, Union __all__ = [ "DirectUrl", @@ -31,9 +33,7 @@ def _get( value = d[key] if not isinstance(value, expected_type): raise DirectUrlValidationError( - "{!r} has unexpected type for {} (expected {})".format( - value, key, expected_type - ) + f"{value!r} has unexpected type for {key} (expected {expected_type})" ) return value @@ -66,18 +66,13 @@ def _filter_none(**kwargs: Any) -> Dict[str, Any]: return {k: v for k, v in kwargs.items() if v is not None} +@dataclass class VcsInfo: - name = "vcs_info" + name: ClassVar = "vcs_info" - def __init__( - self, - vcs: str, - commit_id: str, - requested_revision: Optional[str] = None, - ) -> None: - self.vcs = vcs - self.requested_revision = requested_revision - self.commit_id = commit_id + vcs: str + commit_id: str + requested_revision: Optional[str] = None @classmethod def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["VcsInfo"]: @@ -103,27 +98,49 @@ class ArchiveInfo: def __init__( self, hash: Optional[str] = None, + hashes: Optional[Dict[str, str]] = None, ) -> None: + # set hashes before hash, since the hash setter will further populate hashes + self.hashes = hashes self.hash = hash + @property + def hash(self) -> Optional[str]: + return self._hash + + @hash.setter + def hash(self, value: Optional[str]) -> None: + if value is not None: + # Auto-populate the hashes key to upgrade to the new format automatically. + # We don't back-populate the legacy hash key from hashes. + try: + hash_name, hash_value = value.split("=", 1) + except ValueError: + raise DirectUrlValidationError( + f"invalid archive_info.hash format: {value!r}" + ) + if self.hashes is None: + self.hashes = {hash_name: hash_value} + elif hash_name not in self.hashes: + self.hashes = self.hashes.copy() + self.hashes[hash_name] = hash_value + self._hash = value + @classmethod def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]: if d is None: return None - return cls(hash=_get(d, str, "hash")) + return cls(hash=_get(d, str, "hash"), hashes=_get(d, dict, "hashes")) def _to_dict(self) -> Dict[str, Any]: - return _filter_none(hash=self.hash) + return _filter_none(hash=self.hash, hashes=self.hashes) +@dataclass class DirInfo: - name = "dir_info" + name: ClassVar = "dir_info" - def __init__( - self, - editable: bool = False, - ) -> None: - self.editable = editable + editable: bool = False @classmethod def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["DirInfo"]: @@ -138,16 +155,11 @@ class DirInfo: InfoType = Union[ArchiveInfo, DirInfo, VcsInfo] +@dataclass class DirectUrl: - def __init__( - self, - url: str, - info: InfoType, - subdirectory: Optional[str] = None, - ) -> None: - self.url = url - self.info = info - self.subdirectory = subdirectory + url: str + info: InfoType + subdirectory: Optional[str] = None def _remove_auth_from_netloc(self, netloc: str) -> str: if "@" not in netloc: diff --git a/venv/Lib/site-packages/pip/_internal/models/format_control.py b/venv/Lib/site-packages/pip/_internal/models/format_control.py index db3995e..ccd1127 100644 --- a/venv/Lib/site-packages/pip/_internal/models/format_control.py +++ b/venv/Lib/site-packages/pip/_internal/models/format_control.py @@ -33,9 +33,7 @@ class FormatControl: return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) def __repr__(self) -> str: - return "{}({}, {})".format( - self.__class__.__name__, self.no_binary, self.only_binary - ) + return f"{self.__class__.__name__}({self.no_binary}, {self.only_binary})" @staticmethod def handle_mutual_excludes(value: str, target: Set[str], other: Set[str]) -> None: diff --git a/venv/Lib/site-packages/pip/_internal/models/installation_report.py b/venv/Lib/site-packages/pip/_internal/models/installation_report.py index 965f095..b9c6330 100644 --- a/venv/Lib/site-packages/pip/_internal/models/installation_report.py +++ b/venv/Lib/site-packages/pip/_internal/models/installation_report.py @@ -14,7 +14,7 @@ class InstallationReport: def _install_req_to_dict(cls, ireq: InstallRequirement) -> Dict[str, Any]: assert ireq.download_info, f"No download_info for {ireq}" res = { - # PEP 610 json for the download URL. download_info.archive_info.hash may + # PEP 610 json for the download URL. download_info.archive_info.hashes may # be absent when the requirement was installed from the wheel cache # and the cache entry was populated by an older pip version that did not # record origin.json. @@ -22,7 +22,10 @@ class InstallationReport: # is_direct is true if the requirement was a direct URL reference (which # includes editable requirements), and false if the requirement was # downloaded from a PEP 503 index or --find-links. - "is_direct": bool(ireq.original_link), + "is_direct": ireq.is_direct, + # is_yanked is true if the requirement was yanked from the index, but + # was still selected by pip to conform to PEP 592. + "is_yanked": ireq.link.is_yanked if ireq.link else False, # requested is true if the requirement was specified by the user (aka # top level requirement), and false if it was installed as a dependency of a # requirement. https://peps.python.org/pep-0376/#requested @@ -33,12 +36,12 @@ class InstallationReport: } if ireq.user_supplied and ireq.extras: # For top level requirements, the list of requested extras, if any. - res["requested_extras"] = list(sorted(ireq.extras)) + res["requested_extras"] = sorted(ireq.extras) return res def to_dict(self) -> Dict[str, Any]: return { - "version": "0", + "version": "1", "pip_version": __version__, "install": [ self._install_req_to_dict(ireq) for ireq in self._install_requirements diff --git a/venv/Lib/site-packages/pip/_internal/models/link.py b/venv/Lib/site-packages/pip/_internal/models/link.py index 8fd1c3d..27ad016 100644 --- a/venv/Lib/site-packages/pip/_internal/models/link.py +++ b/venv/Lib/site-packages/pip/_internal/models/link.py @@ -1,11 +1,14 @@ import functools +import itertools import logging import os import posixpath import re import urllib.parse +from dataclasses import dataclass from typing import ( TYPE_CHECKING, + Any, Dict, List, Mapping, @@ -15,14 +18,15 @@ from typing import ( Union, ) +from pip._internal.utils.deprecation import deprecated from pip._internal.utils.filetypes import WHEEL_EXTENSION from pip._internal.utils.hashes import Hashes from pip._internal.utils.misc import ( + pairwise, redact_auth_from_url, split_auth_from_netloc, splitext, ) -from pip._internal.utils.models import KeyBasedCompareMixin from pip._internal.utils.urls import path_to_url, url_to_path if TYPE_CHECKING: @@ -36,17 +40,170 @@ logger = logging.getLogger(__name__) _SUPPORTED_HASHES = ("sha512", "sha384", "sha256", "sha224", "sha1", "md5") -class Link(KeyBasedCompareMixin): +@dataclass(frozen=True) +class LinkHash: + """Links to content may have embedded hash values. This class parses those. + + `name` must be any member of `_SUPPORTED_HASHES`. + + This class can be converted to and from `ArchiveInfo`. While ArchiveInfo intends to + be JSON-serializable to conform to PEP 610, this class contains the logic for + parsing a hash name and value for correctness, and then checking whether that hash + conforms to a schema with `.is_hash_allowed()`.""" + + name: str + value: str + + _hash_url_fragment_re = re.compile( + # NB: we do not validate that the second group (.*) is a valid hex + # digest. Instead, we simply keep that string in this class, and then check it + # against Hashes when hash-checking is needed. This is easier to debug than + # proactively discarding an invalid hex digest, as we handle incorrect hashes + # and malformed hashes in the same place. + r"[#&]({choices})=([^&]*)".format( + choices="|".join(re.escape(hash_name) for hash_name in _SUPPORTED_HASHES) + ), + ) + + def __post_init__(self) -> None: + assert self.name in _SUPPORTED_HASHES + + @classmethod + @functools.lru_cache(maxsize=None) + def find_hash_url_fragment(cls, url: str) -> Optional["LinkHash"]: + """Search a string for a checksum algorithm name and encoded output value.""" + match = cls._hash_url_fragment_re.search(url) + if match is None: + return None + name, value = match.groups() + return cls(name=name, value=value) + + def as_dict(self) -> Dict[str, str]: + return {self.name: self.value} + + def as_hashes(self) -> Hashes: + """Return a Hashes instance which checks only for the current hash.""" + return Hashes({self.name: [self.value]}) + + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: + """ + Return True if the current hash is allowed by `hashes`. + """ + if hashes is None: + return False + return hashes.is_hash_allowed(self.name, hex_digest=self.value) + + +@dataclass(frozen=True) +class MetadataFile: + """Information about a core metadata file associated with a distribution.""" + + hashes: Optional[Dict[str, str]] + + def __post_init__(self) -> None: + if self.hashes is not None: + assert all(name in _SUPPORTED_HASHES for name in self.hashes) + + +def supported_hashes(hashes: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]: + # Remove any unsupported hash types from the mapping. If this leaves no + # supported hashes, return None + if hashes is None: + return None + hashes = {n: v for n, v in hashes.items() if n in _SUPPORTED_HASHES} + if not hashes: + return None + return hashes + + +def _clean_url_path_part(part: str) -> str: + """ + Clean a "part" of a URL path (i.e. after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + return urllib.parse.quote(urllib.parse.unquote(part)) + + +def _clean_file_url_path(part: str) -> str: + """ + Clean the first part of a URL path that corresponds to a local + filesystem path (i.e. the first part after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + # Also, on Windows the path part might contain a drive letter which + # should not be quoted. On Linux where drive letters do not + # exist, the colon should be quoted. We rely on urllib.request + # to do the right thing here. + return urllib.request.pathname2url(urllib.request.url2pathname(part)) + + +# percent-encoded: / +_reserved_chars_re = re.compile("(@|%2F)", re.IGNORECASE) + + +def _clean_url_path(path: str, is_local_path: bool) -> str: + """ + Clean the path portion of a URL. + """ + if is_local_path: + clean_func = _clean_file_url_path + else: + clean_func = _clean_url_path_part + + # Split on the reserved characters prior to cleaning so that + # revision strings in VCS URLs are properly preserved. + parts = _reserved_chars_re.split(path) + + cleaned_parts = [] + for to_clean, reserved in pairwise(itertools.chain(parts, [""])): + cleaned_parts.append(clean_func(to_clean)) + # Normalize %xx escapes (e.g. %2f -> %2F) + cleaned_parts.append(reserved.upper()) + + return "".join(cleaned_parts) + + +def _ensure_quoted_url(url: str) -> str: + """ + Make sure a link is fully quoted. + For example, if ' ' occurs in the URL, it will be replaced with "%20", + and without double-quoting other characters. + """ + # Split the URL into parts according to the general structure + # `scheme://netloc/path?query#fragment`. + result = urllib.parse.urlsplit(url) + # If the netloc is empty, then the URL refers to a local filesystem path. + is_local_path = not result.netloc + path = _clean_url_path(result.path, is_local_path=is_local_path) + return urllib.parse.urlunsplit(result._replace(path=path)) + + +def _absolute_link_url(base_url: str, url: str) -> str: + """ + A faster implementation of urllib.parse.urljoin with a shortcut + for absolute http/https URLs. + """ + if url.startswith(("https://", "http://")): + return url + else: + return urllib.parse.urljoin(base_url, url) + + +@functools.total_ordering +class Link: """Represents a parsed link from a Package Index's simple URL""" __slots__ = [ "_parsed_url", "_url", + "_path", "_hashes", "comes_from", "requires_python", "yanked_reason", + "metadata_file_data", "cache_link_parsing", + "egg_fragment", ] def __init__( @@ -55,6 +212,7 @@ class Link(KeyBasedCompareMixin): comes_from: Optional[Union[str, "IndexContent"]] = None, requires_python: Optional[str] = None, yanked_reason: Optional[str] = None, + metadata_file_data: Optional[MetadataFile] = None, cache_link_parsing: bool = True, hashes: Optional[Mapping[str, str]] = None, ) -> None: @@ -72,15 +230,21 @@ class Link(KeyBasedCompareMixin): a simple repository HTML link. If the file has been yanked but no reason was provided, this should be the empty string. See PEP 592 for more information and the specification. + :param metadata_file_data: the metadata attached to the file, or None if + no such metadata is provided. This argument, if not None, indicates + that a separate metadata file exists, and also optionally supplies + hashes for that file. :param cache_link_parsing: A flag that is used elsewhere to determine - whether resources retrieved from this link - should be cached. PyPI index urls should - generally have this set to False, for - example. + whether resources retrieved from this link should be cached. PyPI + URLs should generally have this set to False, for example. :param hashes: A mapping of hash names to digests to allow us to - determine the validity of a download. + determine the validity of a download. """ + # The comes_from, requires_python, and metadata_file_data arguments are + # only used by classmethods of this class, and are not used in client + # code directly. + # url can be a UNC windows share if url.startswith("\\\\"): url = path_to_url(url) @@ -89,15 +253,126 @@ class Link(KeyBasedCompareMixin): # Store the url as a private attribute to prevent accidentally # trying to set a new value. self._url = url - self._hashes = hashes if hashes is not None else {} + # The .path property is hot, so calculate its value ahead of time. + self._path = urllib.parse.unquote(self._parsed_url.path) + + link_hash = LinkHash.find_hash_url_fragment(url) + hashes_from_link = {} if link_hash is None else link_hash.as_dict() + if hashes is None: + self._hashes = hashes_from_link + else: + self._hashes = {**hashes, **hashes_from_link} self.comes_from = comes_from self.requires_python = requires_python if requires_python else None self.yanked_reason = yanked_reason - - super().__init__(key=url, defining_class=Link) + self.metadata_file_data = metadata_file_data self.cache_link_parsing = cache_link_parsing + self.egg_fragment = self._egg_fragment() + + @classmethod + def from_json( + cls, + file_data: Dict[str, Any], + page_url: str, + ) -> Optional["Link"]: + """ + Convert an pypi json document from a simple repository page into a Link. + """ + file_url = file_data.get("url") + if file_url is None: + return None + + url = _ensure_quoted_url(_absolute_link_url(page_url, file_url)) + pyrequire = file_data.get("requires-python") + yanked_reason = file_data.get("yanked") + hashes = file_data.get("hashes", {}) + + # PEP 714: Indexes must use the name core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = file_data.get("core-metadata") + if metadata_info is None: + metadata_info = file_data.get("dist-info-metadata") + + # The metadata info value may be a boolean, or a dict of hashes. + if isinstance(metadata_info, dict): + # The file exists, and hashes have been supplied + metadata_file_data = MetadataFile(supported_hashes(metadata_info)) + elif metadata_info: + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + else: + # False or not present: the file does not exist + metadata_file_data = None + + # The Link.yanked_reason expects an empty string instead of a boolean. + if yanked_reason and not isinstance(yanked_reason, str): + yanked_reason = "" + # The Link.yanked_reason expects None instead of False. + elif not yanked_reason: + yanked_reason = None + + return cls( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + hashes=hashes, + metadata_file_data=metadata_file_data, + ) + + @classmethod + def from_element( + cls, + anchor_attribs: Dict[str, Optional[str]], + page_url: str, + base_url: str, + ) -> Optional["Link"]: + """ + Convert an anchor element's attributes in a simple repository page to a Link. + """ + href = anchor_attribs.get("href") + if not href: + return None + + url = _ensure_quoted_url(_absolute_link_url(base_url, href)) + pyrequire = anchor_attribs.get("data-requires-python") + yanked_reason = anchor_attribs.get("data-yanked") + + # PEP 714: Indexes must use the name data-core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = anchor_attribs.get("data-core-metadata") + if metadata_info is None: + metadata_info = anchor_attribs.get("data-dist-info-metadata") + # The metadata info value may be the string "true", or a string of + # the form "hashname=hashval" + if metadata_info == "true": + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + elif metadata_info is None: + # The file does not exist + metadata_file_data = None + else: + # The file exists, and hashes have been supplied + hashname, sep, hashval = metadata_info.partition("=") + if sep == "=": + metadata_file_data = MetadataFile(supported_hashes({hashname: hashval})) + else: + # Error - data is wrong. Treat as no hashes supplied. + logger.debug( + "Index returned invalid data-dist-info-metadata value: %s", + metadata_info, + ) + metadata_file_data = MetadataFile(None) + + return cls( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + metadata_file_data=metadata_file_data, + ) def __str__(self) -> str: if self.requires_python: @@ -105,15 +380,26 @@ class Link(KeyBasedCompareMixin): else: rp = "" if self.comes_from: - return "{} (from {}){}".format( - redact_auth_from_url(self._url), self.comes_from, rp - ) + return f"{redact_auth_from_url(self._url)} (from {self.comes_from}){rp}" else: return redact_auth_from_url(str(self._url)) def __repr__(self) -> str: return f"" + def __hash__(self) -> int: + return hash(self.url) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Link): + return NotImplemented + return self.url == other.url + + def __lt__(self, other: Any) -> bool: + if not isinstance(other, Link): + return NotImplemented + return self.url < other.url + @property def url(self) -> str: return self._url @@ -149,7 +435,7 @@ class Link(KeyBasedCompareMixin): @property def path(self) -> str: - return urllib.parse.unquote(self._parsed_url.path) + return self._path def splitext(self) -> Tuple[str, str]: return splitext(posixpath.basename(self.path.rstrip("/"))) @@ -165,12 +451,28 @@ class Link(KeyBasedCompareMixin): _egg_fragment_re = re.compile(r"[#&]egg=([^&]*)") - @property - def egg_fragment(self) -> Optional[str]: + # Per PEP 508. + _project_name_re = re.compile( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE + ) + + def _egg_fragment(self) -> Optional[str]: match = self._egg_fragment_re.search(self._url) if not match: return None - return match.group(1) + + # An egg fragment looks like a PEP 508 project name, along with + # an optional extras specifier. Anything else is invalid. + project_name = match.group(1) + if not self._project_name_re.match(project_name): + deprecated( + reason=f"{self} contains an egg fragment with a non-PEP 508 name.", + replacement="to use the req @ url syntax, and remove the egg fragment", + gone_in="25.1", + issue=13157, + ) + + return project_name _subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)") @@ -181,33 +483,25 @@ class Link(KeyBasedCompareMixin): return None return match.group(1) - _hash_re = re.compile( - r"({choices})=([a-f0-9]+)".format(choices="|".join(_SUPPORTED_HASHES)) - ) + def metadata_link(self) -> Optional["Link"]: + """Return a link to the associated core metadata file (if any).""" + if self.metadata_file_data is None: + return None + metadata_url = f"{self.url_without_fragment}.metadata" + if self.metadata_file_data.hashes is None: + return Link(metadata_url) + return Link(metadata_url, hashes=self.metadata_file_data.hashes) + + def as_hashes(self) -> Hashes: + return Hashes({k: [v] for k, v in self._hashes.items()}) @property def hash(self) -> Optional[str]: - for hashname in _SUPPORTED_HASHES: - if hashname in self._hashes: - return self._hashes[hashname] - - match = self._hash_re.search(self._url) - if match: - return match.group(2) - - return None + return next(iter(self._hashes.values()), None) @property def hash_name(self) -> Optional[str]: - for hashname in _SUPPORTED_HASHES: - if hashname in self._hashes: - return hashname - - match = self._hash_re.search(self._url) - if match: - return match.group(1) - - return None + return next(iter(self._hashes), None) @property def show_url(self) -> str: @@ -236,19 +530,15 @@ class Link(KeyBasedCompareMixin): @property def has_hash(self) -> bool: - return self.hash_name is not None + return bool(self._hashes) def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: """ - Return True if the link has a hash and it is allowed. + Return True if the link has a hash and it is allowed by `hashes`. """ - if hashes is None or not self.has_hash: + if hashes is None: return False - # Assert non-None so mypy knows self.hash_name and self.hash are str. - assert self.hash_name is not None - assert self.hash is not None - - return hashes.is_hash_allowed(self.hash_name, hex_digest=self.hash) + return any(hashes.is_hash_allowed(k, v) for k, v in self._hashes.items()) class _CleanResult(NamedTuple): diff --git a/venv/Lib/site-packages/pip/_internal/models/scheme.py b/venv/Lib/site-packages/pip/_internal/models/scheme.py index f51190a..06a9a55 100644 --- a/venv/Lib/site-packages/pip/_internal/models/scheme.py +++ b/venv/Lib/site-packages/pip/_internal/models/scheme.py @@ -5,10 +5,12 @@ For a general overview of available schemes and their context, see https://docs.python.org/3/install/index.html#alternate-installation. """ +from dataclasses import dataclass SCHEME_KEYS = ["platlib", "purelib", "headers", "scripts", "data"] +@dataclass(frozen=True) class Scheme: """A Scheme holds paths which are used as the base directories for artifacts associated with a Python package. @@ -16,16 +18,8 @@ class Scheme: __slots__ = SCHEME_KEYS - def __init__( - self, - platlib: str, - purelib: str, - headers: str, - scripts: str, - data: str, - ) -> None: - self.platlib = platlib - self.purelib = purelib - self.headers = headers - self.scripts = scripts - self.data = data + platlib: str + purelib: str + headers: str + scripts: str + data: str diff --git a/venv/Lib/site-packages/pip/_internal/models/search_scope.py b/venv/Lib/site-packages/pip/_internal/models/search_scope.py index e4e54c2..ee7bc86 100644 --- a/venv/Lib/site-packages/pip/_internal/models/search_scope.py +++ b/venv/Lib/site-packages/pip/_internal/models/search_scope.py @@ -3,6 +3,7 @@ import logging import os import posixpath import urllib.parse +from dataclasses import dataclass from typing import List from pip._vendor.packaging.utils import canonicalize_name @@ -14,19 +15,24 @@ from pip._internal.utils.misc import normalize_path, redact_auth_from_url logger = logging.getLogger(__name__) +@dataclass(frozen=True) class SearchScope: - """ Encapsulates the locations that pip is configured to search. """ - __slots__ = ["find_links", "index_urls"] + __slots__ = ["find_links", "index_urls", "no_index"] + + find_links: List[str] + index_urls: List[str] + no_index: bool @classmethod def create( cls, find_links: List[str], index_urls: List[str], + no_index: bool, ) -> "SearchScope": """ Create a SearchScope object after normalizing the `find_links`. @@ -60,22 +66,14 @@ class SearchScope: return cls( find_links=built_find_links, index_urls=index_urls, + no_index=no_index, ) - def __init__( - self, - find_links: List[str], - index_urls: List[str], - ) -> None: - self.find_links = find_links - self.index_urls = index_urls - def get_formatted_locations(self) -> str: lines = [] redacted_index_urls = [] if self.index_urls and self.index_urls != [PyPI.simple_url]: for url in self.index_urls: - redacted_index_url = redact_auth_from_url(url) # Parse the URL diff --git a/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py b/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py index 977bc4c..e9b50aa 100644 --- a/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py +++ b/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py @@ -3,6 +3,8 @@ from typing import Optional from pip._internal.models.format_control import FormatControl +# TODO: This needs Python 3.10's improved slots support for dataclasses +# to be converted into a dataclass. class SelectionPreferences: """ Encapsulates the candidate selection preferences for downloading diff --git a/venv/Lib/site-packages/pip/_internal/models/target_python.py b/venv/Lib/site-packages/pip/_internal/models/target_python.py index 744bd7e..88925a9 100644 --- a/venv/Lib/site-packages/pip/_internal/models/target_python.py +++ b/venv/Lib/site-packages/pip/_internal/models/target_python.py @@ -1,5 +1,5 @@ import sys -from typing import List, Optional, Tuple +from typing import List, Optional, Set, Tuple from pip._vendor.packaging.tags import Tag @@ -8,7 +8,6 @@ from pip._internal.utils.misc import normalize_version_info class TargetPython: - """ Encapsulates the properties of a Python interpreter one is targeting for a package install, download, etc. @@ -22,6 +21,7 @@ class TargetPython: "py_version", "py_version_info", "_valid_tags", + "_valid_tags_set", ] def __init__( @@ -61,8 +61,9 @@ class TargetPython: self.py_version = py_version self.py_version_info = py_version_info - # This is used to cache the return value of get_tags(). + # This is used to cache the return value of get_(un)sorted_tags. self._valid_tags: Optional[List[Tag]] = None + self._valid_tags_set: Optional[Set[Tag]] = None def format_given(self) -> str: """ @@ -84,7 +85,7 @@ class TargetPython: f"{key}={value!r}" for key, value in key_values if value is not None ) - def get_tags(self) -> List[Tag]: + def get_sorted_tags(self) -> List[Tag]: """ Return the supported PEP 425 tags to check wheel candidates against. @@ -108,3 +109,13 @@ class TargetPython: self._valid_tags = tags return self._valid_tags + + def get_unsorted_tags(self) -> Set[Tag]: + """Exactly the same as get_sorted_tags, but returns a set. + + This is important for performance. + """ + if self._valid_tags_set is None: + self._valid_tags_set = set(self.get_sorted_tags()) + + return self._valid_tags_set diff --git a/venv/Lib/site-packages/pip/_internal/models/wheel.py b/venv/Lib/site-packages/pip/_internal/models/wheel.py index 35c7037..ea85600 100644 --- a/venv/Lib/site-packages/pip/_internal/models/wheel.py +++ b/venv/Lib/site-packages/pip/_internal/models/wheel.py @@ -1,20 +1,26 @@ """Represents a wheel file and provides access to the various parts of the name that have meaning. """ + import re from typing import Dict, Iterable, List from pip._vendor.packaging.tags import Tag +from pip._vendor.packaging.utils import ( + InvalidWheelFilename as PackagingInvalidWheelName, +) +from pip._vendor.packaging.utils import parse_wheel_filename from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.utils.deprecation import deprecated class Wheel: """A wheel file""" wheel_file_re = re.compile( - r"""^(?P(?P.+?)-(?P.*?)) - ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) + r"""^(?P(?P[^\s-]+?)-(?P[^\s-]*?)) + ((-(?P\d[^-]*?))?-(?P[^\s-]+?)-(?P[^\s-]+?)-(?P[^\s-]+?) \.whl|\.dist-info)$""", re.VERBOSE, ) @@ -28,9 +34,29 @@ class Wheel: raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.") self.filename = filename self.name = wheel_info.group("name").replace("_", "-") - # we'll assume "_" means "-" due to wheel naming scheme - # (https://github.com/pypa/pip/issues/1150) - self.version = wheel_info.group("ver").replace("_", "-") + _version = wheel_info.group("ver") + if "_" in _version: + try: + parse_wheel_filename(filename) + except PackagingInvalidWheelName as e: + deprecated( + reason=( + f"Wheel filename {filename!r} is not correctly normalised. " + "Future versions of pip will raise the following error:\n" + f"{e.args[0]}\n\n" + ), + replacement=( + "to rename the wheel to use a correctly normalised " + "name (this may require updating the version in " + "the project metadata)" + ), + gone_in="25.1", + issue=12938, + ) + + _version = _version.replace("_", "-") + + self.version = _version self.build_tag = wheel_info.group("build") self.pyversions = wheel_info.group("pyver").split(".") self.abis = wheel_info.group("abi").split(".") diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-310.pyc index 5d79331d04483465d02eb2da8e5b77bc51692378..83f72d3f340ca89b0852ecf238d7ae4e3c037b3c 100644 GIT binary patch delta 18 YcmaFN_?VF^pO=@50SLZ5p2&3*05K2+vj6}9 delta 18 YcmaFN_?VF^pO=@50SH9JCvx2c04aL}1^@s6 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-310.pyc index ab9bc8f499daa7f87a6de072faf7297bf7a2e74e..c1ad14ccbad5479208a29f5067e27f707cf11518 100644 GIT binary patch literal 14486 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 H>$U#?G)JSO delta 1474 zcmZ9M&u`;I6vsW|vEw+l6DMg)OP7Yy2zi(N#li{+#IANF_Og`29?<#{+{~oSVkgnq zY-!~xD<#rOaHy)eAaO|r9Qr@Nh5rDFlaFxW$_a@}c;hTxZ*9%j^X82`@AKY_&)R=1 zJ44$x6}XmGe%}p@6K5U$cyeWPtod4``#Mr6qFPvr4ByE6dRUH3-^}}^uo79mmG_O% zjvU{Ks(v-M%V8~YeHZ#BvuK6YdxTolo)W*oRIoMbtSUWBtF$&H6XZ7^DAc9(sY2__ zn5c%oMDZiVYn=Rb`)!<+AFu)AK{Di-@!2Tp4+lZ$p{#r_h}r$1yT_y<4$=2U1yIfu zUKN+{7j_Md7=u`dyW$)CTdfKPe+3+d>g=;nf)l}u}}Kp0^o38 z{6J#21y@$4ea^Z7d%!L6PwCmUC0NzN8Hrig0pNwyj zE^d}L@8&NO{+jf?4wC76LA=Lkri}ug#KlZVZ?&__l1^79v@;5ly~{$B@7yBblHB*9 z#ZN&}Wu~O)6dmCNO_XB~DG5$7MH777I8sw}rV7t|3vG!{&5iMU`v@uWehiH&fR48_ z%y&G(x8PfOnlmySu|Y;S3n+}|;kKo-1(KoO#W+<6^IdSo652#YUNUE1o7d6i{Ln2X zR%}!>aoxTY=`i)2VhYAN1<5IHNQy*#LS|Y@PSFISPV^ME=COUGrP{2N;!_y=92f}P z6BQ`~KJe5HW5@OWWuD zgmD>iUOG=N#s)r$oDD!fvxTpoU=a~2JsGEXgp*n*iCW6~)LS;FptE0&Op(m~0Z z#gegWi)mcXS98Sk+O4tN*^AW4?U-ph2MLS$W!YEzgM{CZez_+y`^CZNvM~JraOAmJ zl~eL#A`iUGd+dN13PH1p@uTkP?88QU4`iNnN6Fd-s{#gIj0fh>eHQkuzB*`Bz&XHwmf zlQ5Q%oLrDNL-GP? ze*GKM-|tAalSxy7zu$iRcHz#=<)*E)v|~=j&01M$ z8&1y6TX|{sIR&?96{T%D+uVMuU)phJz%5xNchDMi%T`%(31`S1wuapiYs4M3Mv1~A zcPeb`F0saGlC8#RiWzL8q|9qHO*7XuYdg?!nq_&KV^!FVu_s{Hpm|z=-AP)MY!&>s z(SBg2=m0RKhpbKqX&KnshDwT6=XE+nhk@NeM_9kqPO&(!qvNy!^z?T(-BWl;EJxhp04#hgsY)^=M|7h8#mnMBWXjZl zoWtF(#I!cEI@XQef-(oOZe)#srQX(7qJhy>)(GDj^xZLOq#M1f62;TyO6#q_j^9;+ z#Kq*2#t+cwitZI3o|==ZR5#)uraJI_-3X0=*9o~&aW_bz{z|N?Px$A$u~SNr?yBHs zysxepU85UYBd3&F-|=f|W$Je#{?MwEiee}=H8d_XxE);Wuu$_`*H|sX%aBW`dn|C; zO>T%I(f#oZP&|!biVvet^{3F(0cw35tHg&8hQ-g(m-m&>lrRWZn6*2cbsC)6w7u*( z?FJnM+MfY1q6yU?x@xGJS`csRr36|UL6*;m8~Vr3?%ojFR4n-ouN6S7cC+mT%nR)K zmczV;%Z{M33XstF?E3jwj*#8rlCk6bEO24O4|q-EPov~MB#6uZQy-%BH^pho@3ejR zVB32QPWcG{Ginf%K%^0f^!fD%#%?n53`#0Bv!_|aRb+t${CTi=Rvb1fv(sqqLD&mW zi#}3283=|JM%b00SHE7$;_WNLK|-?G=m0**zC*P>BX?+(sK4<5Oi#G`RCRGIOiJxW)2>J0m<{D z;_G-PE>(w7Ixh|-&P{Btw}=|H-GYm=?XLJTF;0foe@UDrV=uzVds%)I1ztyp0fYu; zP<78|yeiJ8%JxCr*{EEoU2L~Jjy=RrqPy1aFfWWQ^H#uQNo4Z1I6sXpvN_M9g}oXQ zCa)+oux&bxV3F6w{nTXX-{CeJj$_-`#X#EG7svC@A)G zW@iTD&7xx;ysV?`1;~cW>Q!;4fPlkSwpkdxa5Z3lugPbTm4ie+1o>E?z4{f7#d_qr WI}S9iaz?qA04 z?@u%miI@Ukq5avy&kqwlWa;7l)9apPTSTFR>TbeI+DT~}ZpusBX=z8@jF+{u(l*_k zm$&oMZgUG>(Jo3m=C*qsc89d%Zl~8}cX=hd*B z1DMWj)}URq1nk&Ol_VRUH)uEQ0d_wvvkr>2lgvW8m-YdD;EY21>A*dO4s59QE8q>% zec*y0G5Vv(X@}N(DR~lY>VeseY>-WLO%K|d$_C+MLF`GKs!e@U zB}(0pUZmxLZEY$+VkvoB!S2jj0UNu5~MfO zwP@4uuMak((@KzOs*o6cpstxsvl-nW(@Mpxu14>!^^M+L6TfLgBU7I%N<|ILTeI8= z?kuxV^J}ZDlI7j7m(ZxQz-`R&HZiVG<}#9+Z*Xrm;AwDpT&(Cvx>IQ4{&^Ij(#BCT z-h)sU-|MI1U1&-uiIh<+mcjQA0hqd_n#52|Ra4XA4WrYFfu#{-`MCJNc$_}GGj_W` zGFncY#R4jTrSYR%lhG_8hs6bRta22%FyaTiqVd;oH@gdbW0kY8E zCI}+FP8G$s@tbj31ka7<#ej8VaM#~c1Hz%{IJJ5$aGbm1u{A(?wtld#k^Z+J^fbdS zVu5!NaFWpE%wKNQea45yWU}O(!N`tip|;eh)%iG*)0nO`mRUX2KjO83Nd@FyD{+1W zQ)ItgM=OWPgvo;o&H0+kmS=-Seo$;BM>=0#?%b^FI?jf8o^+?N8Tbi=s|a}0xrVTa zusc>-CFH6AtMK=+B}{l1R8{?3ji`UATI|mOlUKzzsry%V<;p`^buI$<--kB#vOG9! zN&XJPWrP`o-D%~FxU$cXza}1}hsgDFVRQ-MHo^m@N!&6lEcvvZ3K-lMVnAhCey zkMCRoo)WA1^16Jm@Cn<#yl@dNG!_;Z=W;8<7%3p&%O`sv)NkDhnBVHaqsUGn$S#$g qjAzer;d^9~g5f!Z=5enW{|& diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc index f46c10a1b92b37e8db9f18b249e4d7b772ba89b5..a656121cde7899a56c7066d9ee9274851a340294 100644 GIT binary patch delta 42 xcmX@*c-oOSpO=@50SLZ5zLI`yBkvtXMz_tc7+IJYDCpO=@50SH9JucTky$a{y8F>UiJMiwSUxykRD3pXdSWXS*k^%4wC diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-310.pyc index 73631b783a83cc1a15ce0cd5cc56e12aaa3c7d16..e373f95bf8df402f4e7bdde2e3bf14a4477c9958 100644 GIT binary patch delta 3065 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 Optional[AuthInfo]: - """Return the tuple auth for a given url from keyring.""" - global keyring - if not url or not keyring: +class Credentials(NamedTuple): + url: str + username: str + password: str + + +class KeyRingBaseProvider(ABC): + """Keyring base provider interface""" + + has_keyring: bool + + @abstractmethod + def get_auth_info( + self, url: str, username: Optional[str] + ) -> Optional[AuthInfo]: ... + + @abstractmethod + def save_auth_info(self, url: str, username: str, password: str) -> None: ... + + +class KeyRingNullProvider(KeyRingBaseProvider): + """Keyring null provider""" + + has_keyring = False + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: return None - try: - try: - get_credential = keyring.get_credential - except AttributeError: - pass - else: + def save_auth_info(self, url: str, username: str, password: str) -> None: + return None + + +class KeyRingPythonProvider(KeyRingBaseProvider): + """Keyring interface which uses locally imported `keyring`""" + + has_keyring = True + + def __init__(self) -> None: + import keyring + + self.keyring = keyring + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + # Support keyring's get_credential interface which supports getting + # credentials without a username. This is only available for + # keyring>=15.2.0. + if hasattr(self.keyring, "get_credential"): logger.debug("Getting credentials from keyring for %s", url) - cred = get_credential(url, username) + cred = self.keyring.get_credential(url, username) if cred is not None: return cred.username, cred.password return None - if username: + if username is not None: logger.debug("Getting password from keyring for %s", url) - password = keyring.get_password(url, username) + password = self.keyring.get_password(url, username) if password: return username, password + return None - except Exception as exc: - logger.warning( - "Keyring is skipped due to an exception: %s", - str(exc), + def save_auth_info(self, url: str, username: str, password: str) -> None: + self.keyring.set_password(url, username, password) + + +class KeyRingCliProvider(KeyRingBaseProvider): + """Provider which uses `keyring` cli + + Instead of calling the keyring package installed alongside pip + we call keyring on the command line which will enable pip to + use which ever installation of keyring is available first in + PATH. + """ + + has_keyring = True + + def __init__(self, cmd: str) -> None: + self.keyring = cmd + + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + # This is the default implementation of keyring.get_credential + # https://github.com/jaraco/keyring/blob/97689324abcf01bd1793d49063e7ca01e03d7d07/keyring/backend.py#L134-L139 + if username is not None: + password = self._get_password(url, username) + if password is not None: + return username, password + return None + + def save_auth_info(self, url: str, username: str, password: str) -> None: + return self._set_password(url, username, password) + + def _get_password(self, service_name: str, username: str) -> Optional[str]: + """Mirror the implementation of keyring.get_password using cli""" + if self.keyring is None: + return None + + cmd = [self.keyring, "get", service_name, username] + env = os.environ.copy() + env["PYTHONIOENCODING"] = "utf-8" + res = subprocess.run( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + env=env, ) - keyring = None # type: ignore[assignment] - return None + if res.returncode: + return None + return res.stdout.decode("utf-8").strip(os.linesep) + + def _set_password(self, service_name: str, username: str, password: str) -> None: + """Mirror the implementation of keyring.set_password using cli""" + if self.keyring is None: + return None + env = os.environ.copy() + env["PYTHONIOENCODING"] = "utf-8" + subprocess.run( + [self.keyring, "set", service_name, username], + input=f"{password}{os.linesep}".encode(), + env=env, + check=True, + ) + return None + + +@lru_cache(maxsize=None) +def get_keyring_provider(provider: str) -> KeyRingBaseProvider: + logger.verbose("Keyring provider requested: %s", provider) + + # keyring has previously failed and been disabled + if KEYRING_DISABLED: + provider = "disabled" + if provider in ["import", "auto"]: + try: + impl = KeyRingPythonProvider() + logger.verbose("Keyring provider set: import") + return impl + except ImportError: + pass + except Exception as exc: + # In the event of an unexpected exception + # we should warn the user + msg = "Installed copy of keyring fails with exception %s" + if provider == "auto": + msg = msg + ", trying to find a keyring executable as a fallback" + logger.warning(msg, exc, exc_info=logger.isEnabledFor(logging.DEBUG)) + if provider in ["subprocess", "auto"]: + cli = shutil.which("keyring") + if cli and cli.startswith(sysconfig.get_path("scripts")): + # all code within this function is stolen from shutil.which implementation + @typing.no_type_check + def PATH_as_shutil_which_determines_it() -> str: + 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 + + return path + + scripts = Path(sysconfig.get_path("scripts")) + + paths = [] + for path in PATH_as_shutil_which_determines_it().split(os.pathsep): + p = Path(path) + try: + if not p.samefile(scripts): + paths.append(path) + except FileNotFoundError: + pass + + path = os.pathsep.join(paths) + + cli = shutil.which("keyring", path=path) + + if cli: + logger.verbose("Keyring provider set: subprocess with executable %s", cli) + return KeyRingCliProvider(cli) + + logger.verbose("Keyring provider set: disabled") + return KeyRingNullProvider() class MultiDomainBasicAuth(AuthBase): def __init__( - self, prompting: bool = True, index_urls: Optional[List[str]] = None + self, + prompting: bool = True, + index_urls: Optional[List[str]] = None, + keyring_provider: str = "auto", ) -> None: self.prompting = prompting self.index_urls = index_urls + self.keyring_provider = keyring_provider # type: ignore[assignment] self.passwords: Dict[str, AuthInfo] = {} # When the user is prompted to enter credentials and keyring is # available, we will offer to save them. If the user accepts, @@ -84,6 +239,51 @@ class MultiDomainBasicAuth(AuthBase): # ``save_credentials`` to save these. self._credentials_to_save: Optional[Credentials] = None + @property + def keyring_provider(self) -> KeyRingBaseProvider: + return get_keyring_provider(self._keyring_provider) + + @keyring_provider.setter + def keyring_provider(self, provider: str) -> None: + # The free function get_keyring_provider has been decorated with + # functools.cache. If an exception occurs in get_keyring_auth that + # cache will be cleared and keyring disabled, take that into account + # if you want to remove this indirection. + self._keyring_provider = provider + + @property + def use_keyring(self) -> bool: + # We won't use keyring when --no-input is passed unless + # a specific provider is requested because it might require + # user interaction + return self.prompting or self._keyring_provider not in ["auto", "disabled"] + + def _get_keyring_auth( + self, + url: Optional[str], + username: Optional[str], + ) -> Optional[AuthInfo]: + """Return the tuple auth for a given url from keyring.""" + # Do nothing if no url was provided + if not url: + return None + + try: + return self.keyring_provider.get_auth_info(url, username) + except Exception as exc: + # Log the full exception (with stacktrace) at debug, so it'll only + # show up when running in verbose mode. + logger.debug("Keyring is skipped due to an exception", exc_info=True) + # Always log a shortened version of the exception. + logger.warning( + "Keyring is skipped due to an exception: %s", + str(exc), + ) + global KEYRING_DISABLED + KEYRING_DISABLED = True + get_keyring_provider.cache_clear() + return None + def _get_index_url(self, url: str) -> Optional[str]: """Return the original index URL matching the requested URL. @@ -100,15 +300,42 @@ class MultiDomainBasicAuth(AuthBase): if not url or not self.index_urls: return None - for u in self.index_urls: - prefix = remove_auth_from_url(u).rstrip("/") + "/" - if url.startswith(prefix): - return u - return None + url = remove_auth_from_url(url).rstrip("/") + "/" + parsed_url = urllib.parse.urlsplit(url) + + candidates = [] + + for index in self.index_urls: + index = index.rstrip("/") + "/" + parsed_index = urllib.parse.urlsplit(remove_auth_from_url(index)) + if parsed_url == parsed_index: + return index + + if parsed_url.netloc != parsed_index.netloc: + continue + + candidate = urllib.parse.urlsplit(index) + candidates.append(candidate) + + if not candidates: + return None + + candidates.sort( + reverse=True, + key=lambda candidate: commonprefix( + [ + parsed_url.path, + candidate.path, + ] + ).rfind("/"), + ) + + return urllib.parse.urlunsplit(candidates[0]) def _get_new_credentials( self, original_url: str, + *, allow_netrc: bool = True, allow_keyring: bool = False, ) -> AuthInfo: @@ -152,8 +379,8 @@ class MultiDomainBasicAuth(AuthBase): # The index url is more specific than the netloc, so try it first # fmt: off kr_auth = ( - get_keyring_auth(index_url, username) or - get_keyring_auth(netloc, username) + self._get_keyring_auth(index_url, username) or + self._get_keyring_auth(netloc, username) ) # fmt: on if kr_auth: @@ -230,18 +457,23 @@ class MultiDomainBasicAuth(AuthBase): def _prompt_for_password( self, netloc: str ) -> Tuple[Optional[str], Optional[str], bool]: - username = ask_input(f"User for {netloc}: ") + username = ask_input(f"User for {netloc}: ") if self.prompting else None if not username: return None, None, False - auth = get_keyring_auth(netloc, username) - if auth and auth[0] is not None and auth[1] is not None: - return auth[0], auth[1], False + if self.use_keyring: + auth = self._get_keyring_auth(netloc, username) + if auth and auth[0] is not None and auth[1] is not None: + return auth[0], auth[1], False password = ask_password("Password: ") return username, password, True # Factored out to allow for easy patching in tests def _should_save_password_to_keyring(self) -> bool: - if not keyring: + if ( + not self.prompting + or not self.use_keyring + or not self.keyring_provider.has_keyring + ): return False return ask("Save credentials to keyring [y/N]: ", ["y", "n"]) == "y" @@ -251,19 +483,22 @@ class MultiDomainBasicAuth(AuthBase): if resp.status_code != 401: return resp + username, password = None, None + + # Query the keyring for credentials: + if self.use_keyring: + username, password = self._get_new_credentials( + resp.url, + allow_netrc=False, + allow_keyring=True, + ) + # We are not able to prompt the user so simply return the response - if not self.prompting: + if not self.prompting and not username and not password: return resp parsed = urllib.parse.urlparse(resp.url) - # Query the keyring for credentials: - username, password = self._get_new_credentials( - resp.url, - allow_netrc=False, - allow_keyring=True, - ) - # Prompt the user for a new username and password save = False if not username and not password: @@ -276,11 +511,17 @@ class MultiDomainBasicAuth(AuthBase): # Prompt to save the password to keyring if save and self._should_save_password_to_keyring(): - self._credentials_to_save = (parsed.netloc, username, password) + self._credentials_to_save = Credentials( + url=parsed.netloc, + username=username, + password=password, + ) # Consume content and release the original connection to allow our new # request to reuse the same one. - resp.content + # The result of the assignment isn't used, it's just needed to consume + # the content. + _ = resp.content resp.raw.release_conn() # Add our new username and password to the request @@ -309,15 +550,17 @@ class MultiDomainBasicAuth(AuthBase): def save_credentials(self, resp: Response, **kwargs: Any) -> None: """Response callback to save credentials on success.""" - assert keyring is not None, "should never reach here without keyring" - if not keyring: - return + assert ( + self.keyring_provider.has_keyring + ), "should never reach here without keyring" creds = self._credentials_to_save self._credentials_to_save = None if creds and resp.status_code < 400: try: logger.info("Saving credentials to keyring") - keyring.set_password(*creds) + self.keyring_provider.save_auth_info( + creds.url, creds.username, creds.password + ) except Exception: logger.exception("Failed to save credentials") diff --git a/venv/Lib/site-packages/pip/_internal/network/cache.py b/venv/Lib/site-packages/pip/_internal/network/cache.py index a81a239..fca04e6 100644 --- a/venv/Lib/site-packages/pip/_internal/network/cache.py +++ b/venv/Lib/site-packages/pip/_internal/network/cache.py @@ -3,10 +3,11 @@ import os from contextlib import contextmanager -from typing import Generator, Optional +from datetime import datetime +from typing import BinaryIO, Generator, Optional, Union -from pip._vendor.cachecontrol.cache import BaseCache -from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache +from pip._vendor.cachecontrol.caches import SeparateBodyFileCache from pip._vendor.requests.models import Response from pip._internal.utils.filesystem import adjacent_tmp_file, replace @@ -28,10 +29,22 @@ def suppressed_cache_errors() -> Generator[None, None, None]: pass -class SafeFileCache(BaseCache): +class SafeFileCache(SeparateBodyBaseCache): """ A file based cache which is safe to use even when the target directory may not be accessible or writable. + + There is a race condition when two processes try to write and/or read the + same entry at the same time, since each entry consists of two separate + files (https://github.com/psf/cachecontrol/issues/324). We therefore have + additional logic that makes sure that both files to be present before + returning an entry; this fixes the read side of the race condition. + + For the write side, we assume that the server will only ever return the + same data for the same URL, which ought to be the case for files pip is + downloading. PyPI does not have a mechanism to swap out a wheel for + another wheel, for example. If this assumption is not true, the + CacheControl issue will need to be fixed. """ def __init__(self, directory: str) -> None: @@ -43,27 +56,63 @@ class SafeFileCache(BaseCache): # From cachecontrol.caches.file_cache.FileCache._fn, brought into our # class for backwards-compatibility and to avoid using a non-public # method. - hashed = FileCache.encode(name) + hashed = SeparateBodyFileCache.encode(name) parts = list(hashed[:5]) + [hashed] return os.path.join(self.directory, *parts) def get(self, key: str) -> Optional[bytes]: - path = self._get_cache_path(key) + # The cache entry is only valid if both metadata and body exist. + metadata_path = self._get_cache_path(key) + body_path = metadata_path + ".body" + if not (os.path.exists(metadata_path) and os.path.exists(body_path)): + return None with suppressed_cache_errors(): - with open(path, "rb") as f: + with open(metadata_path, "rb") as f: return f.read() - def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None: - path = self._get_cache_path(key) + def _write(self, path: str, data: bytes) -> None: with suppressed_cache_errors(): ensure_dir(os.path.dirname(path)) with adjacent_tmp_file(path) as f: - f.write(value) + f.write(data) + # Inherit the read/write permissions of the cache directory + # to enable multi-user cache use-cases. + mode = ( + os.stat(self.directory).st_mode + & 0o666 # select read/write permissions of cache directory + | 0o600 # set owner read/write permissions + ) + # Change permissions only if there is no risk of following a symlink. + if os.chmod in os.supports_fd: + os.chmod(f.fileno(), mode) + elif os.chmod in os.supports_follow_symlinks: + os.chmod(f.name, mode, follow_symlinks=False) replace(f.name, path) + def set( + self, key: str, value: bytes, expires: Union[int, datetime, None] = None + ) -> None: + path = self._get_cache_path(key) + self._write(path, value) + def delete(self, key: str) -> None: path = self._get_cache_path(key) with suppressed_cache_errors(): os.remove(path) + with suppressed_cache_errors(): + os.remove(path + ".body") + + def get_body(self, key: str) -> Optional[BinaryIO]: + # The cache entry is only valid if both metadata and body exist. + metadata_path = self._get_cache_path(key) + body_path = metadata_path + ".body" + if not (os.path.exists(metadata_path) and os.path.exists(body_path)): + return None + with suppressed_cache_errors(): + return open(body_path, "rb") + + def set_body(self, key: str, body: bytes) -> None: + path = self._get_cache_path(key) + ".body" + self._write(path, body) diff --git a/venv/Lib/site-packages/pip/_internal/network/download.py b/venv/Lib/site-packages/pip/_internal/network/download.py index 79b82a5..5c3bce3 100644 --- a/venv/Lib/site-packages/pip/_internal/network/download.py +++ b/venv/Lib/site-packages/pip/_internal/network/download.py @@ -1,12 +1,13 @@ """Download files with progress indicators. """ + import email.message import logging import mimetypes import os from typing import Iterable, Optional, Tuple -from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response +from pip._vendor.requests.models import Response from pip._internal.cli.progress_bars import get_download_progress_renderer from pip._internal.exceptions import NetworkConnectionError @@ -42,7 +43,7 @@ def _prepare_download( logged_url = redact_auth_from_url(url) if total_length: - logged_url = "{} ({})".format(logged_url, format_size(total_length)) + logged_url = f"{logged_url} ({format_size(total_length)})" if is_from_cache(resp): logger.info("Using cached %s", logged_url) @@ -55,12 +56,12 @@ def _prepare_download( show_progress = False elif not total_length: show_progress = True - elif total_length > (40 * 1000): + elif total_length > (512 * 1024): show_progress = True else: show_progress = False - chunks = response_chunks(resp, CONTENT_CHUNK_SIZE) + chunks = response_chunks(resp) if not show_progress: return chunks diff --git a/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py index 2d1ddaa..03f883c 100644 --- a/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py +++ b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py @@ -6,7 +6,7 @@ from bisect import bisect_left, bisect_right from contextlib import contextmanager from tempfile import NamedTemporaryFile from typing import Any, Dict, Generator, List, Optional, Tuple -from zipfile import BadZipfile, ZipFile +from zipfile import BadZipFile, ZipFile from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response @@ -23,7 +23,7 @@ class HTTPRangeRequestUnsupported(Exception): def dist_from_wheel_url(name: str, url: str, session: PipSession) -> BaseDistribution: """Return a distribution object from the given wheel URL. - This uses HTTP range requests to only fetch the potion of the wheel + This uses HTTP range requests to only fetch the portion of the wheel containing metadata, just enough for the object to be constructed. If such requests are not supported, HTTPRangeRequestUnsupported is raised. @@ -159,8 +159,8 @@ class LazyZipOverHTTP: try: # For read-only ZIP files, ZipFile only needs # methods read, seek, seekable and tell. - ZipFile(self) # type: ignore - except BadZipfile: + ZipFile(self) + except BadZipFile: pass else: break diff --git a/venv/Lib/site-packages/pip/_internal/network/session.py b/venv/Lib/site-packages/pip/_internal/network/session.py index e512ac7..5e10f8f 100644 --- a/venv/Lib/site-packages/pip/_internal/network/session.py +++ b/venv/Lib/site-packages/pip/_internal/network/session.py @@ -3,6 +3,7 @@ network request configuration and behavior. """ import email.utils +import functools import io import ipaddress import json @@ -106,6 +107,7 @@ def looks_like_ci() -> bool: return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) +@functools.lru_cache(maxsize=1) def user_agent() -> str: """ Return a string representing the user agent. @@ -230,7 +232,7 @@ class LocalFSAdapter(BaseAdapter): # to return a better error message: resp.status_code = 404 resp.reason = type(exc).__name__ - resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode("utf8")) + resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode()) else: modified = email.utils.formatdate(stats.st_mtime, usegmt=True) content_type = mimetypes.guess_type(pathname)[0] or "text/plain" @@ -316,7 +318,6 @@ class InsecureCacheControlAdapter(CacheControlAdapter): class PipSession(requests.Session): - timeout: Optional[int] = None def __init__( @@ -338,6 +339,7 @@ class PipSession(requests.Session): # Namespace the attribute with "pip_" just in case to prevent # possible conflicts with the base class. self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = [] + self.pip_proxy = None # Attach our User Agent to the request self.headers["User-Agent"] = user_agent() @@ -356,8 +358,9 @@ class PipSession(requests.Session): # is typically considered a transient error so we'll go ahead and # retry it. # A 500 may indicate transient error in Amazon S3 + # A 502 may be a transient error from a CDN like CloudFlare or CloudFront # A 520 or 527 - may indicate transient error in CloudFlare - status_forcelist=[500, 503, 520, 527], + status_forcelist=[500, 502, 503, 520, 527], # Add a small amount of back off between failed requests in # order to prevent hammering the service. backoff_factor=0.25, @@ -420,15 +423,17 @@ class PipSession(requests.Session): msg += f" (from {source})" logger.info(msg) - host_port = parse_netloc(host) - if host_port not in self.pip_trusted_origins: - self.pip_trusted_origins.append(host_port) + parsed_host, parsed_port = parse_netloc(host) + if parsed_host is None: + raise ValueError(f"Trusted host URL must include a host part: {host!r}") + if (parsed_host, parsed_port) not in self.pip_trusted_origins: + self.pip_trusted_origins.append((parsed_host, parsed_port)) self.mount( build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter ) self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter) - if not host_port[1]: + if not parsed_port: self.mount( build_url_from_netloc(host, scheme="http") + ":", self._trusted_host_adapter, diff --git a/venv/Lib/site-packages/pip/_internal/network/utils.py b/venv/Lib/site-packages/pip/_internal/network/utils.py index 134848a..bba4c26 100644 --- a/venv/Lib/site-packages/pip/_internal/network/utils.py +++ b/venv/Lib/site-packages/pip/_internal/network/utils.py @@ -1,6 +1,6 @@ from typing import Dict, Generator -from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response +from pip._vendor.requests.models import Response from pip._internal.exceptions import NetworkConnectionError @@ -25,6 +25,8 @@ from pip._internal.exceptions import NetworkConnectionError # possible to make this work. HEADERS: Dict[str, str] = {"Accept-Encoding": "identity"} +DOWNLOAD_CHUNK_SIZE = 256 * 1024 + def raise_for_status(resp: Response) -> None: http_error_msg = "" @@ -55,7 +57,7 @@ def raise_for_status(resp: Response) -> None: def response_chunks( - response: Response, chunk_size: int = CONTENT_CHUNK_SIZE + response: Response, chunk_size: int = DOWNLOAD_CHUNK_SIZE ) -> Generator[bytes, None, None]: """Given a requests Response, provide the data chunks.""" try: diff --git a/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py b/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py index 4a7d55d..22ec8d2 100644 --- a/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py +++ b/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py @@ -13,6 +13,8 @@ from pip._internal.network.utils import raise_for_status if TYPE_CHECKING: from xmlrpc.client import _HostType, _Marshallable + from _typeshed import SizedBuffer + logger = logging.getLogger(__name__) @@ -33,7 +35,7 @@ class PipXmlrpcTransport(xmlrpc.client.Transport): self, host: "_HostType", handler: str, - request_body: bytes, + request_body: "SizedBuffer", verbose: bool = False, ) -> Tuple["_Marshallable", ...]: assert isinstance(host, str) diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-310.pyc index 8f3be6a2860a6dba426b8038031e9f689e0c3be8..7d404ef7210fb2ce9222f60aa55c8d8bc381dd68 100644 GIT binary patch delta 18 YcmZ3_xSo+KpO=@50SLZ5p2)Qn04ekZ7XSbN delta 18 YcmZ3_xSo+KpO=@50SH9JCvq(X03u%lY5)KL diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-310.pyc index 85a5664f494bc2a047d59f0ee206c1f367c65bf5..fa5ea5a3f220ec8f97473b50eb7563d7836d17a6 100644 GIT binary patch delta 2351 zcmZuyO>7(25q@v~xLp40hY}@PqGZV;ElaU2#Yv1LO&ZxwV#i2eTR|5!*cIO+z4HFh zZ>7x8WhFzEf?uf1j#M8UfXlpQ&ALq$R*eI*q}k`wlhn`HHt3rhTr>UhBG@e z@A2vUZNeE032dec*ce2beGpDb+Nf))Mq*Q>RCN*HCDr}?_Ar&#w4KVxT7 zYY`FT6<7wm#xw2OYpF8O7<>{slHKW2}m_8D*7pRgxVY1;pii_S!f5~2= zgww-ie(H$YD_00BvGNnb%Di--+D&fp8gF)$8nIh^4DdvXPp7yJI~6pmsa27mu92>? z55$>cVigJ4uYvg)zLw&3z%9O>;+I$@-JQis^CY+0+x=-eA+b$d^*~rLM+mYzDmdH`y#N@I|2O@Lf&SdA`ULreL<)ixP-0h-e^g$OHA(WDVdVtjGXi5tEjwsL8*nf8A;T z(NYr23pFDqD6Pz{-dQ!LWH7$Nx4BUtw6wd&~bT$6lU_$wE0?04OKkKLHdHGCVHa3u0lTG7H^&5aL*;8PtLvl!t$QHT1BX^CJ zS6ShJ0w9-*|ttxr)Y^NkZGn*n@E3vGxvcyFnDgP(n5hH246;g8as+)4u${s_oxI z53}!d?m9glB}JU@P{f?!Fh(5()IUBt0GzQ7tmqREza&F!+J!wOCNVvrziLu4R1Ot} zEm31N)^_#Sh%>QyKn}A*XvLw$lpZ-!4wP6sAP4H+zBbejb3Y5p$#6&<*02 zE^eXeHk#6YVm-LSx!3MOVEY(j-CpcET2?xDc;{|=5IisM6QH9xJebO3Q?sZ=6{^u` zSlTm7H>mQs{txA`_HW_H$=p}QMGQJAzs}8{I)!j_;t;K%Xrg!nL@OgkgCHyU<{M{` z#<}{Re8h*qJ%trv`3&7uO=?mD!siuDNwwmJyq^zlUjse7a~l4I;RkjUP8T;2r*l{N zaf;ebx63;)Lt+b+@1kft7dX)3BM_gKnH7EiXqKywAbcAI9({o)SU4!Kt7&ClsCEOn<2%F;*}&s(QlKIaghos?Pw{h><_l%`W5~<* UN-tZ6qWmkbTF;cSd{mnG4|57R=>Px# delta 1538 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 delta 7121 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 delta 18 YcmdnWxRsGBpO=@50SH9JCvvR@03$I2d;kCd diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc index 6b737366dd3d9cc1ade5280da0772ba0b0c68cbe..9c763e0202b31cd10985ab48c9a38cff424b12f7 100644 GIT binary patch literal 4953 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 ZL%%A&$g5VBS1iXq&z+SeK3`pQ{s#)9#@+w` delta 2221 zcmZuyO>7%Q6rP!#U9au++HssTPSeCqnzpW}`$Jo3snn(|0!oBLQ)sb-EGIK@?D!{) zH%-#oq>x^#s@ek=4z`4lIDn9Pgd;a3PFz?dPF%Rcfn#}ZHf_>STl4nq+c)p`n>W85 z{`#QXN+ekZ0G zpB9HCsSS&W+$U^li)fZCauE~p2YibbNAx$8J0NEwAzUrbzC}b*q#h8F+G52~LFY(* z;4eZR|1(4_KT5~4#+>v5esg0*2IdFNYO9&20iUflm!F)Xic-h_irt_G{D0Y}H0j?l z&eMq}-y4IJ9`t|WN39ejr3U=J`H5T{*nqE;y(Kk)tW|GSDpCcekn^h*mGfuJ(a8g- zugN&-3{<37nqRHfMafg;g=MMoe%G9$$Nj#U*|b6BGOYG@KqM(rL5fUJX$U3^NS+Jx z0WWefDl8EJ&V<5PG9v9P$r2F-9yk$$ClpKXu|-@spcxYh85c~V6;~ud;)s+?Y}*|W zX^^+s!qWptp83Eq9ybvRjG8*|1(;z0WT7t0 z&DE7W4|koxt!I&(dx;T5HLDltkec0LeKtpwjwKpImdfp=dUZaq+Dqlrr_ThLRaGyoRlTLws#jW6 zc8P+r;EE?;GSNrL;K*?i}xI1X*&sj&ABjs;9fUZZRg5$ zCCg$XH!rKrN)C^zcOiGL>;LSWwOxe;R5QMjn7U#uwp63+1@YNdYk76$O{H2&orLd! zxu&WBuVLhkvJg9{4x3?x&A8$(CXQ^r2yOK)Y?_6o5fd{U#(0dz=-5+!-(j4xr>F?xwEbIJp^4lLEMV0fpE)6P9k*MPPQ?<xdX0P>=_1Hj7~m%+juQxx)J*?U^2jwyod9(mjzZ&mVo^6x zwkHUjAPSbAA}&n-ACse-E(rctMLf?7sF?%u8N}3sS|XAJ`4He6fy&Ei*aj=hC%LEXj)wW5=8KBgaf5gel2}+QenD5cBQ&ffJqK#rCF{Q8ZgP~ z?SjTt)c+zqMPvRC>B+15o{hrAIjiqibrY=~MRFSn9y5IbtK-P!kn9cGpB~I*a@1iC Qb!d!nV}$Z-hNhkW0J-zcdH?_b diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc index 3887d9302b37f8c6cb99a6f0ea0189dee3334269..0634d1950be5892513f0ab14d2084e438641a6d0 100644 GIT binary patch delta 57 zcmZqRZsX?7=jG*M0D^CiucY@)wuzY+%+f0_N-QWyEtaf@oN+!+4OX?P?#O delta 74 zcmdnSy@;DPpO=@50SH9JucU97$a{ueARx8C)X;q5vtx{_Ca-0jzd3?QiHT8Vay5%8 b6Cdy7B`hkuURMTrFksYR2ovOEL;BXk!v diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc index f1720c8aaea5c0941c61815418c5a13ba4165d0e..8fe8b7ea998baec3d59b28f6e75bd1462a4096e7 100644 GIT binary patch delta 186 zcmdlev|NZcpO=@50SLZ5zLMUzkynFBpoU>K!(66j#wNxRhAfr^teah#k{KDbC$D7I zW-np{D%E70e3w~b@?YjKM#;?~EOVK>#DJnj>>z>}L~wuzRuI7kA|!!?CTEcph%F5w zWI%*0h>!yjia_EPOJY%aagpj|YxW98?af=*c^SpjLE_BCB}HHpZm}fg=jRk@Prl9( F1pp95D5U@Z delta 175 zcmZ23v{8sRpO=@50SH9JucS}g$g9C5uz;n8VIgBPV-sTuLl)}-w#}|g$&8G;lUFip zYgE@3F#;89vfpCLFTTZ|lUZDnl37&50u;N&oRgY&i!Cj`C^xZW@+anSMybtSEOVI{ z#V5aDlVy_vY2%zMz%D8%4`dc8fwZtB7Nr*#sZBOyuVB>Kyo#NdQA`7DRB=gB5lF`^ PmZbdroFbjcXE~w(;rcGd diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc index b569116e24537eae47c8c57858c10538002998ff..1226ec93d654e3d79f6e57be7cd49616ea1ddc12 100644 GIT binary patch delta 57 zcmZ3-xrLKApO=@50SLZ5zLIV{k#`QSm{VzHPKr}va&~H7%Ek?m%)FHaMfq8&$tCd_ M`T5zC#aLzl02wtC-~a#s delta 51 zcmdnOxsH=JpO=@50SH9JucWI_0tn59=eEx$;i zN?0MeC^fMpHANvWUm-0sC$(6Q%kL#4(B)N@lRvOniWG4J*+n1$O^#b^#rZ`*wUeD$ zE0tt`LL8hdj695dj9iRBnu&vniIMF;(|Mv?5~I?fGjAY+P*C!2890RUW&UljlV delta 372 zcmZ`zO-sW-5Z&GECTVDT5Nq2A#TKemK`0bN5PyWd^->}m+iGiMc0sfoJ@n*FSn%BZ z13&O62>t;N9wh%m@FKW5d2(Rh%;UW`%w74h?8mZ;;d$z zJ=C@@_YWeeIo-n@ozj5L8j$E08sPpP{iM6WEb#!FFWZI87BR?(XZBGH(@^RbyI2d1 z6JZWyJcLku4m5I>Q=ti4P?$_EF>QTG!1JPp{j4) zN&_}>%{w1O(PR+9P-I1MHa;CpBO$_J1e^NJy; Generator["BuildTracker", None, None]: yield tracker +class TrackerId(str): + """Uniquely identifying string provided to the build tracker.""" + + class BuildTracker: + """Ensure that an sdist cannot request itself as a setup requirement. + + When an sdist is prepared, it identifies its setup requirements in the + context of ``BuildTracker.track()``. If a requirement shows up recursively, this + raises an exception. + + This stops fork bombs embedded in malicious packages.""" + def __init__(self, root: str) -> None: self._root = root - self._entries: Set[InstallRequirement] = set() + self._entries: Dict[TrackerId, InstallRequirement] = {} logger.debug("Created build tracker: %s", self._root) def __enter__(self) -> "BuildTracker": @@ -69,16 +80,15 @@ class BuildTracker: ) -> None: self.cleanup() - def _entry_path(self, link: Link) -> str: - hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + def _entry_path(self, key: TrackerId) -> str: + hashed = hashlib.sha224(key.encode()).hexdigest() return os.path.join(self._root, hashed) - def add(self, req: InstallRequirement) -> None: + def add(self, req: InstallRequirement, key: TrackerId) -> None: """Add an InstallRequirement to build tracking.""" - assert req.link # Get the file to write information about this requirement. - entry_path = self._entry_path(req.link) + entry_path = self._entry_path(key) # Try reading from the file. If it exists and can be read from, a build # is already in progress, so a LookupError is raised. @@ -88,37 +98,41 @@ class BuildTracker: except FileNotFoundError: pass else: - message = "{} is already being built: {}".format(req.link, contents) + message = f"{req.link} is already being built: {contents}" raise LookupError(message) # If we're here, req should really not be building already. - assert req not in self._entries + assert key not in self._entries # Start tracking this requirement. with open(entry_path, "w", encoding="utf-8") as fp: fp.write(str(req)) - self._entries.add(req) + self._entries[key] = req logger.debug("Added %s to build tracker %r", req, self._root) - def remove(self, req: InstallRequirement) -> None: + def remove(self, req: InstallRequirement, key: TrackerId) -> None: """Remove an InstallRequirement from build tracking.""" - assert req.link - # Delete the created file and the corresponding entries. - os.unlink(self._entry_path(req.link)) - self._entries.remove(req) + # Delete the created file and the corresponding entry. + os.unlink(self._entry_path(key)) + del self._entries[key] logger.debug("Removed %s from build tracker %r", req, self._root) def cleanup(self) -> None: - for req in set(self._entries): - self.remove(req) + for key, req in list(self._entries.items()): + self.remove(req, key) logger.debug("Removed build tracker: %r", self._root) @contextlib.contextmanager - def track(self, req: InstallRequirement) -> Generator[None, None, None]: - self.add(req) + def track(self, req: InstallRequirement, key: str) -> Generator[None, None, None]: + """Ensure that `key` cannot install itself as a setup requirement. + + :raises LookupError: If `key` was already provided in a parent invocation of + the context introduced by this method.""" + tracker_id = TrackerId(key) + self.add(req, tracker_id) yield - self.remove(req) + self.remove(req, tracker_id) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/metadata.py b/venv/Lib/site-packages/pip/_internal/operations/build/metadata.py index e2b7b44..c66ac35 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/metadata.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/metadata.py @@ -3,7 +3,7 @@ import os -from pip._vendor.pep517.wrappers import Pep517HookCaller +from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.build_env import BuildEnvironment from pip._internal.exceptions import ( @@ -15,7 +15,7 @@ from pip._internal.utils.temp_dir import TempDirectory def generate_metadata( - build_env: BuildEnvironment, backend: Pep517HookCaller, details: str + build_env: BuildEnvironment, backend: BuildBackendHookCaller, details: str ) -> str: """Generate metadata using mechanisms described in PEP 517. @@ -26,7 +26,7 @@ def generate_metadata( metadata_dir = metadata_tmpdir.path with build_env: - # Note that Pep517HookCaller implements a fallback for + # Note that BuildBackendHookCaller implements a fallback for # prepare_metadata_for_build_wheel, so we don't have to # consider the possibility that this hook doesn't exist. runner = runner_with_spinner_message("Preparing metadata (pyproject.toml)") diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py index 4c3f48b..3397ccf 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py @@ -3,7 +3,7 @@ import os -from pip._vendor.pep517.wrappers import Pep517HookCaller +from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.build_env import BuildEnvironment from pip._internal.exceptions import ( @@ -15,7 +15,7 @@ from pip._internal.utils.temp_dir import TempDirectory def generate_editable_metadata( - build_env: BuildEnvironment, backend: Pep517HookCaller, details: str + build_env: BuildEnvironment, backend: BuildBackendHookCaller, details: str ) -> str: """Generate metadata using mechanisms described in PEP 660. @@ -26,7 +26,7 @@ def generate_editable_metadata( metadata_dir = metadata_tmpdir.path with build_env: - # Note that Pep517HookCaller implements a fallback for + # Note that BuildBackendHookCaller implements a fallback for # prepare_metadata_for_build_wheel/editable, so we don't have to # consider the possibility that this hook doesn't exist. runner = runner_with_spinner_message( @@ -38,4 +38,5 @@ def generate_editable_metadata( except InstallationSubprocessError as error: raise MetadataGenerationFailed(package_details=details) from error + assert distinfo_dir is not None return os.path.join(metadata_dir, distinfo_dir) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py index e60988d..c01dd1c 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py @@ -27,7 +27,7 @@ def _find_egg_info(directory: str) -> str: if len(filenames) > 1: raise InstallationError( - "More than one .egg-info directory found in {}".format(directory) + f"More than one .egg-info directory found in {directory}" ) return os.path.join(directory, filenames[0]) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py index b0d2fc9..064811a 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py @@ -2,7 +2,7 @@ import logging import os from typing import Optional -from pip._vendor.pep517.wrappers import Pep517HookCaller +from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.utils.subprocess import runner_with_spinner_message @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) def build_wheel_pep517( name: str, - backend: Pep517HookCaller, + backend: BuildBackendHookCaller, metadata_directory: str, tempd: str, ) -> Optional[str]: diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py index cf7b01a..719d69d 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py @@ -2,7 +2,7 @@ import logging import os from typing import Optional -from pip._vendor.pep517.wrappers import HookMissing, Pep517HookCaller +from pip._vendor.pyproject_hooks import BuildBackendHookCaller, HookMissing from pip._internal.utils.subprocess import runner_with_spinner_message @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) def build_wheel_editable( name: str, - backend: Pep517HookCaller, + backend: BuildBackendHookCaller, metadata_directory: str, tempd: str, ) -> Optional[str]: diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py index c5f0492..3ee2a70 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py @@ -40,16 +40,16 @@ def get_legacy_build_wheel_path( # Sort for determinism. names = sorted(names) if not names: - msg = ("Legacy build of wheel for {!r} created no files.\n").format(name) + msg = f"Legacy build of wheel for {name!r} created no files.\n" msg += format_command_result(command_args, command_output) logger.warning(msg) return None if len(names) > 1: msg = ( - "Legacy build of wheel for {!r} created more than one file.\n" - "Filenames (choosing first): {}\n" - ).format(name, names) + f"Legacy build of wheel for {name!r} created more than one file.\n" + f"Filenames (choosing first): {names}\n" + ) msg += format_command_result(command_args, command_output) logger.warning(msg) diff --git a/venv/Lib/site-packages/pip/_internal/operations/check.py b/venv/Lib/site-packages/pip/_internal/operations/check.py index fb3ac8b..4b6fbc4 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/check.py +++ b/venv/Lib/site-packages/pip/_internal/operations/check.py @@ -2,28 +2,44 @@ """ import logging -from typing import Callable, Dict, List, NamedTuple, Optional, Set, Tuple +from contextlib import suppress +from email.parser import Parser +from functools import reduce +from typing import ( + Callable, + Dict, + FrozenSet, + Generator, + Iterable, + List, + NamedTuple, + Optional, + Set, + Tuple, +) from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.tags import Tag, parse_tag from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version from pip._internal.distributions import make_distribution_for_install_requirement from pip._internal.metadata import get_default_environment -from pip._internal.metadata.base import DistributionVersion +from pip._internal.metadata.base import BaseDistribution from pip._internal.req.req_install import InstallRequirement logger = logging.getLogger(__name__) class PackageDetails(NamedTuple): - version: DistributionVersion + version: Version dependencies: List[Requirement] # Shorthands PackageSet = Dict[NormalizedName, PackageDetails] Missing = Tuple[NormalizedName, Requirement] -Conflicting = Tuple[NormalizedName, DistributionVersion, Requirement] +Conflicting = Tuple[NormalizedName, Version, Requirement] MissingDict = Dict[NormalizedName, List[Missing]] ConflictingDict = Dict[NormalizedName, List[Conflicting]] @@ -43,7 +59,7 @@ def create_package_set_from_installed() -> Tuple[PackageSet, bool]: package_set[name] = PackageDetails(dist.version, dependencies) except (OSError, ValueError) as e: # Don't crash on unreadable or broken metadata. - logger.warning("Error parsing requirements for %s: %s", name, e) + logger.warning("Error parsing dependencies of %s: %s", name, e) problems = True return package_set, problems @@ -75,7 +91,7 @@ def check_package_set( if name not in package_set: missed = True if req.marker is not None: - missed = req.marker.evaluate() + missed = req.marker.evaluate({"extra": ""}) if missed: missing_deps.add((name, req)) continue @@ -113,6 +129,22 @@ def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDet ) +def check_unsupported( + packages: Iterable[BaseDistribution], + supported_tags: Iterable[Tag], +) -> Generator[BaseDistribution, None, None]: + for p in packages: + with suppress(FileNotFoundError): + wheel_file = p.read_text("WHEEL") + wheel_tags: FrozenSet[Tag] = reduce( + frozenset.union, + map(parse_tag, Parser().parsestr(wheel_file).get_all("Tag", [])), + frozenset(), + ) + if wheel_tags.isdisjoint(supported_tags): + yield p + + def _simulate_installation_of( to_install: List[InstallRequirement], package_set: PackageSet ) -> Set[NormalizedName]: diff --git a/venv/Lib/site-packages/pip/_internal/operations/freeze.py b/venv/Lib/site-packages/pip/_internal/operations/freeze.py index 930d4c6..ae5dd37 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/freeze.py +++ b/venv/Lib/site-packages/pip/_internal/operations/freeze.py @@ -1,10 +1,11 @@ import collections import logging import os +from dataclasses import dataclass, field from typing import Container, Dict, Generator, Iterable, List, NamedTuple, Optional, Set -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.packaging.version import Version +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import InvalidVersion from pip._internal.exceptions import BadCommand, InstallationError from pip._internal.metadata import BaseDistribution, get_environment @@ -145,9 +146,13 @@ def freeze( def _format_as_name_version(dist: BaseDistribution) -> str: - if isinstance(dist.version, Version): - return f"{dist.raw_name}=={dist.version}" - return f"{dist.raw_name}==={dist.version}" + try: + dist_version = dist.version + except InvalidVersion: + # legacy version + return f"{dist.raw_name}==={dist.raw_version}" + else: + return f"{dist.raw_name}=={dist_version}" def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: @@ -216,19 +221,16 @@ def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: ) +@dataclass(frozen=True) class FrozenRequirement: - def __init__( - self, - name: str, - req: str, - editable: bool, - comments: Iterable[str] = (), - ) -> None: - self.name = name - self.canonical_name = canonicalize_name(name) - self.req = req - self.editable = editable - self.comments = comments + name: str + req: str + editable: bool + comments: Iterable[str] = field(default_factory=tuple) + + @property + def canonical_name(self) -> NormalizedName: + return canonicalize_name(self.name) @classmethod def from_dist(cls, dist: BaseDistribution) -> "FrozenRequirement": diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc index d099615eb510c92402a4c7c029c303b03e75327d..6ebde3613a182e7753be7d0ea9868ea5ee81e86b 100644 GIT binary patch delta 18 YcmaFQ_@0p~pO=@50SLZ5p2+nS05Y@%*8l(j delta 18 YcmaFQ_@0p~pO=@50SH9JCvrUn04pB^DgXcg diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc index 66dee179e48659ee3323d84f53af71853e2b225e..749e0dbf3700c090924cac83ea8b357c325bf070 100644 GIT binary patch delta 615 zcmY*VJ8u**5cb$!pLcKX_L5wb1O!D$aY>}3MTkeFG!%5{wpm@Uvs$!|$h#LIv{4G6 zgy`gk3MC~C9UTR~fGX9t`41@&=&)Bj!i?sdZ#?6fv9G#cy4yvs=OH6kmlrW{5W2L% zbs3sq$5{D(wtedakN`nbCu1RNxs!G>9`cs6)XlumYk4Q_W`5`cl5p0O{c{Kd!6lW0 zH6&a~TJQb#UAZ89IS@T#eZvFE#K7PI zS74;y;JdJ+KjYcDqqu3-^z$N`mQqE}iu@pnl^vz*Ox4vH*tNI6daW63Ga%8{{Fvjpt*>~=;zcK%Ld)}X8Sf8sKw&9ZgL^mEbD~HM9 zI7;$Ls(g};_oqoJBAFj4YKoeh|7WLFl9uDNh~p%Wm7|Bw7BKzT*@*3qjT_7AsYy!J z@F>bBnT#T}Y%`>+R73ZRB5jAORdaX^)@%)bkQHK@%12voi>|7x@OQXf#BqR(EwBCQzAxL-^T#v@_(5Rrvg56Gb9S?XHw4fI0&k!*EE+X@{672Oph`2~q} z{hhpd*ff&t8;BB&F)X_K#}C~9ivM?W-kf8&Jr_4kd#|gH=^ZSn{zNyx(O2{qxcVpU zyLNuHslU>0B&T~vqS)tB3SZxI)?TdIHzG?>(Y>O`>Yv2A5f|Ww?eQPw1)FAk2TUb* W3{d3bE<`v2>jB2Z>^9dQoUMOXl6}Ac diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc deleted file mode 100644 index 130d66d86896668851981fc09217aca6310e17af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3324 zcmb7GTW{RP73R#6T$0PZ=q_2ZLIibzMdMY|rb(L^sgcAf3b;-YxoEpk!B9K1E6Tii zX4bN{+#s+FG%tpKKv7`znE%sR3H9yV^>r`%n@*oXeRrb8g?6yk7SV zcvjYaKX6-y@ww_;e72!;6F$C*41*Y5gCK$v)J6J_yBPkJq>`FlGqt)_YIkjJ{{_|&AE8wROUOaB{mlQaqLJETPx9-G}QvN+>dqV^@u<=Kjr z*?*N@C2R1l(d$n%7UGgZQf4LHnivSF4{79PdoAml}?J1M9a4V19@ zU78l}#fA&@*az|n$l)q5tj8T$_lf`hra`#8spD^ z5F`wOh0!;EWAq`^i22wbS4!hO<5x>#Q=mgUsg&j^8e63`F^P4GSWs3<>jaG<5Hs(7 zo!Aqr#K2J%c3C|^kI=vvJ6gi_*euOS_0$-NMLdx!2DFkU(nPtVmrs(XS; z`xIm$<9-Kb{8IxNqF&l3Frv8{rA?}*c$j>fHnH^SvT2b|78^We~eNc|n;@0KPMe zp`Ao$2gJVg3q}i?5gm>jup765EF%+nc=XN@1G(psM@iU^6UxIr%hQXIIgPE(jU?|y z34gnDQRK+&(81t(ob~h3<6n;h5|bdy1tcbkdy$}lIEbL926U!U5=2=rUjzKJ5bgvY zWXW+bPug>H1Op0b0QzNv7c7e@4EntredgMQ+{Ru_Xb#xPS^0inzDA?s;yokC(y z+5P-c=2883;p4ACE|=9qW84tBs6IhYAB~%%p9p+dnV4nsutF+;C@o=?PKipRY?Zh) z%Z5U^(gnORpVY<+!X{Sf{nq#$2IN~TYfl@P6x(kJ#4d>L;t2hirNi)f?ws+KK4 zjh_i;;u6)?t1jV`vkSPDEt-b#jt`JAhVneJMGcV7eS*rRN0`9a$4f`($Pj+nIzdkx zP>^op)_9_rngLGXw58i1ayr!nS0~!$s1PFNcUA5qQYP6B%)A;D+Sw9}I z*I{sU^+TwI3IOKlFxxhOWDTG^S9&P{azsY!ALRG#+TJl`XXDT2=Oj>V995A1LysB5x^jLlKQ2H=!jR z0rg+o?uV-D&kUk(58x$zcaVs(9konDkcJ3NG(=QqE7UgpE)aXc#~8H`{vWUX1#SQ` zoB=9m4(IvSnGbk@aqDyQO2hK8^9g?Lxec^+hCkW*ga0iPv7dtA_DixFh9vKWp{y$N zfhV=0r7e!(Vl!Y^9a2?SW&)9GP~ST9`qr6eJG0d6`sG=A?f|YKTf3pVb(u#ME_Ko4 zo&5-~N0nf?d6^~62~Bus3PQ|%!A3&?5z|RyxKC-Y|Hfqj)9DNMIely$L2~@QXUpw~@f(rf$o8B{g?R*5H;49n2&uk0-3)}ch kT*d#y4*myr@!zqB|AuS$3+&^+;yV5dZs0%TX5&x)2Gx_HwEzGB diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc index 754773acd82893624196fa02ab126d713f522534..0065756083f5d8c0f76f435d2abed54371a2f233 100644 GIT binary patch delta 6724 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 LDrLNDy6JxbO;58P delta 6571 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 LuP50&HeUDt<(`1< diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py index bb548cd..9aaa699 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py +++ b/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py @@ -1,7 +1,8 @@ """Legacy editable installation process, i.e. `setup.py develop`. """ + import logging -from typing import List, Optional, Sequence +from typing import Optional, Sequence from pip._internal.build_env import BuildEnvironment from pip._internal.utils.logging import indent_log @@ -12,7 +13,7 @@ logger = logging.getLogger(__name__) def install_editable( - install_options: List[str], + *, global_options: Sequence[str], prefix: Optional[str], home: Optional[str], @@ -31,7 +32,6 @@ def install_editable( args = make_setuptools_develop_args( setup_py_path, global_options=global_options, - install_options=install_options, no_user_config=isolated, prefix=prefix, home=home, diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py b/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py deleted file mode 100644 index 290967d..0000000 --- a/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Legacy installation process, i.e. `setup.py install`. -""" - -import logging -import os -from typing import List, Optional, Sequence - -from pip._internal.build_env import BuildEnvironment -from pip._internal.exceptions import InstallationError, LegacyInstallFailure -from pip._internal.locations.base import change_root -from pip._internal.models.scheme import Scheme -from pip._internal.utils.misc import ensure_dir -from pip._internal.utils.setuptools_build import make_setuptools_install_args -from pip._internal.utils.subprocess import runner_with_spinner_message -from pip._internal.utils.temp_dir import TempDirectory - -logger = logging.getLogger(__name__) - - -def write_installed_files_from_setuptools_record( - record_lines: List[str], - root: Optional[str], - req_description: str, -) -> None: - def prepend_root(path: str) -> str: - if root is None or not os.path.isabs(path): - return path - else: - return change_root(root, path) - - for line in record_lines: - directory = os.path.dirname(line) - if directory.endswith(".egg-info"): - egg_info_dir = prepend_root(directory) - break - else: - message = ( - "{} did not indicate that it installed an " - ".egg-info directory. Only setup.py projects " - "generating .egg-info directories are supported." - ).format(req_description) - raise InstallationError(message) - - new_lines = [] - for line in record_lines: - filename = line.strip() - if os.path.isdir(filename): - filename += os.path.sep - new_lines.append(os.path.relpath(prepend_root(filename), egg_info_dir)) - new_lines.sort() - ensure_dir(egg_info_dir) - inst_files_path = os.path.join(egg_info_dir, "installed-files.txt") - with open(inst_files_path, "w") as f: - f.write("\n".join(new_lines) + "\n") - - -def install( - install_options: List[str], - global_options: Sequence[str], - root: Optional[str], - home: Optional[str], - prefix: Optional[str], - use_user_site: bool, - pycompile: bool, - scheme: Scheme, - setup_py_path: str, - isolated: bool, - req_name: str, - build_env: BuildEnvironment, - unpacked_source_directory: str, - req_description: str, -) -> bool: - - header_dir = scheme.headers - - with TempDirectory(kind="record") as temp_dir: - try: - record_filename = os.path.join(temp_dir.path, "install-record.txt") - install_args = make_setuptools_install_args( - setup_py_path, - global_options=global_options, - install_options=install_options, - record_filename=record_filename, - root=root, - prefix=prefix, - header_dir=header_dir, - home=home, - use_user_site=use_user_site, - no_user_config=isolated, - pycompile=pycompile, - ) - - runner = runner_with_spinner_message( - f"Running setup.py install for {req_name}" - ) - with build_env: - runner( - cmd=install_args, - cwd=unpacked_source_directory, - ) - - if not os.path.exists(record_filename): - logger.debug("Record file %s not found", record_filename) - # Signal to the caller that we didn't install the new package - return False - - except Exception as e: - # Signal to the caller that we didn't install the new package - raise LegacyInstallFailure(package_details=req_name) from e - - # At this point, we have successfully installed the requirement. - - # We intentionally do not use any encoding to read the file because - # setuptools writes the file using distutils.file_util.write_file, - # which does not specify an encoding. - with open(record_filename) as f: - record_lines = f.read().splitlines() - - write_installed_files_from_setuptools_record(record_lines, root, req_description) - return True diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py b/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py index 1af8978..aef42aa 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py +++ b/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py @@ -28,6 +28,7 @@ from typing import ( List, NewType, Optional, + Protocol, Sequence, Set, Tuple, @@ -50,7 +51,7 @@ from pip._internal.metadata import ( from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl from pip._internal.models.scheme import SCHEME_KEYS, Scheme from pip._internal.utils.filesystem import adjacent_tmp_file, replace -from pip._internal.utils.misc import captured_stdout, ensure_dir, hash_file, partition +from pip._internal.utils.misc import StreamWrapper, ensure_dir, hash_file, partition from pip._internal.utils.unpacking import ( current_umask, is_within_directory, @@ -60,7 +61,6 @@ from pip._internal.utils.unpacking import ( from pip._internal.utils.wheel import parse_wheel if TYPE_CHECKING: - from typing import Protocol class File(Protocol): src_record_path: "RecordPath" @@ -143,16 +143,18 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: # We don't want to warn for directories that are on PATH. not_warn_dirs = [ - os.path.normcase(i).rstrip(os.sep) + os.path.normcase(os.path.normpath(i)).rstrip(os.sep) for i in os.environ.get("PATH", "").split(os.pathsep) ] # If an executable sits with sys.executable, we don't warn for it. # This covers the case of venv invocations without activating the venv. - not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + not_warn_dirs.append( + os.path.normcase(os.path.normpath(os.path.dirname(sys.executable))) + ) warn_for: Dict[str, Set[str]] = { parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() - if os.path.normcase(parent_dir) not in not_warn_dirs + if os.path.normcase(os.path.normpath(parent_dir)) not in not_warn_dirs } if not warn_for: return None @@ -162,16 +164,14 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: for parent_dir, dir_scripts in warn_for.items(): sorted_scripts: List[str] = sorted(dir_scripts) if len(sorted_scripts) == 1: - start_text = "script {} is".format(sorted_scripts[0]) + start_text = f"script {sorted_scripts[0]} is" else: start_text = "scripts {} are".format( ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] ) msg_lines.append( - "The {} installed in '{}' which is not on PATH.".format( - start_text, parent_dir - ) + f"The {start_text} installed in '{parent_dir}' which is not on PATH." ) last_line_fmt = ( @@ -265,9 +265,9 @@ def get_csv_rows_for_installed( path = _fs_to_record_path(f, lib_dir) digest, length = rehash(f) installed_rows.append((path, digest, length)) - for installed_record_path in installed.values(): - installed_rows.append((installed_record_path, "", "")) - return installed_rows + return installed_rows + [ + (installed_record_path, "", "") for installed_record_path in installed.values() + ] def get_console_script_specs(console: Dict[str, str]) -> List[str]: @@ -288,17 +288,15 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]: # the wheel metadata at build time, and so if the wheel is installed with # a *different* version of Python the entry points will be wrong. The # correct fix for this is to enhance the metadata to be able to describe - # such versioned entry points, but that won't happen till Metadata 2.0 is - # available. - # In the meantime, projects using versioned entry points will either have + # such versioned entry points. + # Currently, projects using versioned entry points will either have # incorrect versioned entry points, or they will not be able to distribute # "universal" wheels (i.e., they will need a wheel per Python version). # # Because setuptools and pip are bundled with _ensurepip and virtualenv, - # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # we need to use universal wheels. As a workaround, we # override the versioned entry points in the wheel and generate the - # correct ones. This code is purely a short-term measure until Metadata 2.0 - # is available. + # correct ones. # # To add the level of hack in this section of code, in order to support # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment @@ -319,13 +317,11 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]: scripts_to_generate.append("pip = " + pip_script) if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": - scripts_to_generate.append( - "pip{} = {}".format(sys.version_info[0], pip_script) - ) + scripts_to_generate.append(f"pip{sys.version_info[0]} = {pip_script}") scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}") # Delete any other versioned pip entry points - pip_ep = [k for k in console if re.match(r"pip(\d(\.\d)?)?$", k)] + pip_ep = [k for k in console if re.match(r"pip(\d+(\.\d+)?)?$", k)] for k in pip_ep: del console[k] easy_install_script = console.pop("easy_install", None) @@ -334,13 +330,11 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]: scripts_to_generate.append("easy_install = " + easy_install_script) scripts_to_generate.append( - "easy_install-{} = {}".format( - get_major_minor_version(), easy_install_script - ) + f"easy_install-{get_major_minor_version()} = {easy_install_script}" ) # Delete any other versioned easy_install entry points easy_install_ep = [ - k for k in console if re.match(r"easy_install(-\d\.\d)?$", k) + k for k in console if re.match(r"easy_install(-\d+\.\d+)?$", k) ] for k in easy_install_ep: del console[k] @@ -364,12 +358,6 @@ class ZipBackedFile: return self._zip_file.getinfo(self.src_record_path) def save(self) -> None: - # directory creation is lazy and after file filtering - # to ensure we don't install empty dirs; empty dirs can't be - # uninstalled. - parent_dir = os.path.dirname(self.dest_path) - ensure_dir(parent_dir) - # When we open the output file below, any existing file is truncated # before we start writing the new contents. This is fine in most # cases, but can cause a segfault if pip has loaded a shared @@ -383,9 +371,13 @@ class ZipBackedFile: zipinfo = self._getinfo() - with self._zip_file.open(zipinfo) as f: - with open(self.dest_path, "wb") as dest: - shutil.copyfileobj(f, dest) + # optimization: the file is created by open(), + # skip the decompression when there is 0 bytes to decompress. + with open(self.dest_path, "wb") as dest: + if zipinfo.file_size > 0: + with self._zip_file.open(zipinfo) as f: + blocksize = min(zipinfo.file_size, 1024 * 1024) + shutil.copyfileobj(f, dest, blocksize) if zip_item_is_executable(zipinfo): set_extracted_file_to_default_mode_plus_executable(self.dest_path) @@ -406,10 +398,10 @@ class ScriptFile: class MissingCallableSuffix(InstallationError): def __init__(self, entry_point: str) -> None: super().__init__( - "Invalid script entry point: {} - A callable " + f"Invalid script entry point: {entry_point} - A callable " "suffix is required. Cf https://packaging.python.org/" "specifications/entry-points/#use-for-scripts for more " - "information.".format(entry_point) + "information." ) @@ -420,12 +412,14 @@ def _raise_for_invalid_entrypoint(specification: str) -> None: class PipScriptMaker(ScriptMaker): - def make(self, specification: str, options: Dict[str, Any] = None) -> List[str]: + def make( + self, specification: str, options: Optional[Dict[str, Any]] = None + ) -> List[str]: _raise_for_invalid_entrypoint(specification) return super().make(specification, options) -def _install_wheel( +def _install_wheel( # noqa: C901, PLR0915 function is too long name: str, wheel_zip: ZipFile, wheel_path: str, @@ -509,9 +503,9 @@ def _install_wheel( _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) except ValueError: message = ( - "Unexpected file in {}: {!r}. .data directory contents" - " should be named like: '/'." - ).format(wheel_path, record_path) + f"Unexpected file in {wheel_path}: {record_path!r}. .data directory" + " contents should be named like: '/'." + ) raise InstallationError(message) try: @@ -519,10 +513,11 @@ def _install_wheel( except KeyError: valid_scheme_keys = ", ".join(sorted(scheme_paths)) message = ( - "Unknown scheme key used in {}: {} (for file {!r}). .data" - " directory contents should be in subdirectories named" - " with a valid scheme key ({})" - ).format(wheel_path, scheme_key, record_path, valid_scheme_keys) + f"Unknown scheme key used in {wheel_path}: {scheme_key} " + f"(for file {record_path!r}). .data directory contents " + f"should be in subdirectories named with a valid scheme " + f"key ({valid_scheme_keys})" + ) raise InstallationError(message) dest_path = os.path.join(scheme_path, dest_subpath) @@ -583,7 +578,15 @@ def _install_wheel( script_scheme_files = map(ScriptFile, script_scheme_files) files = chain(files, script_scheme_files) + existing_parents = set() for file in files: + # directory creation is lazy and after file filtering + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + parent_dir = os.path.dirname(file.dest_path) + if parent_dir not in existing_parents: + ensure_dir(parent_dir) + existing_parents.add(parent_dir) file.save() record_installed(file.src_record_path, file.dest_path, file.changed) @@ -606,7 +609,9 @@ def _install_wheel( # Compile all of the pyc files for the installed files if pycompile: - with captured_stdout() as stdout: + with contextlib.redirect_stdout( + StreamWrapper.from_stream(sys.stdout) + ) as stdout: with warnings.catch_warnings(): warnings.filterwarnings("ignore") for path in pyc_source_file_paths(): @@ -708,7 +713,7 @@ def req_error_context(req_description: str) -> Generator[None, None, None]: try: yield except InstallationError as e: - message = "For req: {}. {}".format(req_description, e.args[0]) + message = f"For req: {req_description}. {e.args[0]}" raise InstallationError(message) from e diff --git a/venv/Lib/site-packages/pip/_internal/operations/prepare.py b/venv/Lib/site-packages/pip/_internal/operations/prepare.py index 80723ff..e6aa344 100644 --- a/venv/Lib/site-packages/pip/_internal/operations/prepare.py +++ b/venv/Lib/site-packages/pip/_internal/operations/prepare.py @@ -4,10 +4,11 @@ # The following comment should be removed at some point in the future. # mypy: strict-optional=False -import logging import mimetypes import os import shutil +from dataclasses import dataclass +from pathlib import Path from typing import Dict, Iterable, List, Optional from pip._vendor.packaging.utils import canonicalize_name @@ -19,12 +20,12 @@ from pip._internal.exceptions import ( HashMismatch, HashUnpinned, InstallationError, + MetadataInconsistent, NetworkConnectionError, - PreviousBuildDirError, VcsHashUnsupported, ) from pip._internal.index.package_finder import PackageFinder -from pip._internal.metadata import BaseDistribution +from pip._internal.metadata import BaseDistribution, get_metadata_distribution from pip._internal.models.direct_url import ArchiveInfo from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel @@ -36,6 +37,7 @@ from pip._internal.network.lazy_wheel import ( from pip._internal.network.session import PipSession from pip._internal.operations.build.build_tracker import BuildTracker from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils._log import getLogger from pip._internal.utils.direct_url_helpers import ( direct_url_for_editable, direct_url_from_link, @@ -46,13 +48,13 @@ from pip._internal.utils.misc import ( display_path, hash_file, hide_url, - is_installable_dir, + redact_auth_from_requirement, ) from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.unpacking import unpack_file from pip._internal.vcs import vcs -logger = logging.getLogger(__name__) +logger = getLogger(__name__) def _get_prepared_distribution( @@ -64,10 +66,12 @@ def _get_prepared_distribution( ) -> BaseDistribution: """Prepare a distribution for installation.""" abstract_dist = make_distribution_for_install_requirement(req) - with build_tracker.track(req): - abstract_dist.prepare_distribution_metadata( - finder, build_isolation, check_build_deps - ) + tracker_id = abstract_dist.build_tracker_id + if tracker_id is not None: + with build_tracker.track(req, tracker_id): + abstract_dist.prepare_distribution_metadata( + finder, build_isolation, check_build_deps + ) return abstract_dist.get_metadata_distribution() @@ -77,13 +81,14 @@ def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None: vcs_backend.unpack(location, url=hide_url(link.url), verbosity=verbosity) +@dataclass class File: - def __init__(self, path: str, content_type: Optional[str]) -> None: - self.path = path - if content_type is None: - self.content_type = mimetypes.guess_type(path)[0] - else: - self.content_type = content_type + path: str + content_type: Optional[str] = None + + def __post_init__(self) -> None: + if self.content_type is None: + self.content_type = mimetypes.guess_type(self.path)[0] def get_http_url( @@ -178,7 +183,10 @@ def unpack_url( def _check_download_dir( - link: Link, download_dir: str, hashes: Optional[Hashes] + link: Link, + download_dir: str, + hashes: Optional[Hashes], + warn_on_hash_mismatch: bool = True, ) -> Optional[str]: """Check download_dir for previously downloaded file with correct hash If a correct file is found return its path else None @@ -194,10 +202,11 @@ def _check_download_dir( try: hashes.check_against_path(download_path) except HashMismatch: - logger.warning( - "Previously-downloaded file %s has bad hash. Re-downloading.", - download_path, - ) + if warn_on_hash_mismatch: + logger.warning( + "Previously-downloaded file %s has bad hash. Re-downloading.", + download_path, + ) os.unlink(download_path) return None return download_path @@ -221,6 +230,7 @@ class RequirementPreparer: use_user_site: bool, lazy_wheel: bool, verbosity: int, + legacy_resolver: bool, ) -> None: super().__init__() @@ -254,6 +264,9 @@ class RequirementPreparer: # How verbose should underlying tooling be? self.verbosity = verbosity + # Are we using the legacy resolver? + self.legacy_resolver = legacy_resolver + # Memoized downloaded files, as mapping of url: path. self._downloaded: Dict[str, str] = {} @@ -262,18 +275,28 @@ class RequirementPreparer: def _log_preparing_link(self, req: InstallRequirement) -> None: """Provide context for the requirement being prepared.""" - if req.link.is_file and not req.original_link_is_in_wheel_cache: + if req.link.is_file and not req.is_wheel_from_cache: message = "Processing %s" information = str(display_path(req.link.file_path)) else: message = "Collecting %s" - information = str(req.req or req) + information = redact_auth_from_requirement(req.req) if req.req else str(req) + + # If we used req.req, inject requirement source if available (this + # would already be included if we used req directly) + if req.req and req.comes_from: + if isinstance(req.comes_from, str): + comes_from: Optional[str] = req.comes_from + else: + comes_from = req.comes_from.from_path() + if comes_from: + information += f" (from {comes_from})" if (message, information) != self._previous_requirement_header: self._previous_requirement_header = (message, information) logger.info(message, information) - if req.original_link_is_in_wheel_cache: + if req.is_wheel_from_cache: with indent_log(): logger.info("Using cached %s", req.link.filename) @@ -298,21 +321,7 @@ class RequirementPreparer: autodelete=True, parallel_builds=parallel_builds, ) - - # If a checkout exists, it's unwise to keep going. version - # inconsistencies are logged later, but do not fail the - # installation. - # FIXME: this won't upgrade when there's an existing - # package unpacked in `req.source_dir` - # TODO: this check is now probably dead code - if is_installable_dir(req.source_dir): - raise PreviousBuildDirError( - "pip can't proceed with requirements '{}' due to a" - "pre-existing build directory ({}). This is likely " - "due to a previous installation that failed . pip is " - "being responsible and not assuming it can delete this. " - "Please delete it and try again.".format(req, req.source_dir) - ) + req.ensure_pristine_source_checkout() def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: # By the time this is called, the requirement's link should have @@ -337,7 +346,7 @@ class RequirementPreparer: # a surprising hash mismatch in the future. # file:/// URLs aren't pinnable, so don't complain about them # not being pinned. - if req.original_link is None and not req.is_pinned: + if not req.is_direct and not req.is_pinned: raise HashUnpinned() # If known-good hashes are missing for this requirement, @@ -346,19 +355,77 @@ class RequirementPreparer: # showing the user what the hash should be. return req.hashes(trust_internet=False) or MissingHashes() + def _fetch_metadata_only( + self, + req: InstallRequirement, + ) -> Optional[BaseDistribution]: + if self.legacy_resolver: + logger.debug( + "Metadata-only fetching is not used in the legacy resolver", + ) + return None + if self.require_hashes: + logger.debug( + "Metadata-only fetching is not used as hash checking is required", + ) + return None + # Try PEP 658 metadata first, then fall back to lazy wheel if unavailable. + return self._fetch_metadata_using_link_data_attr( + req + ) or self._fetch_metadata_using_lazy_wheel(req.link) + + def _fetch_metadata_using_link_data_attr( + self, + req: InstallRequirement, + ) -> Optional[BaseDistribution]: + """Fetch metadata from the data-dist-info-metadata attribute, if possible.""" + # (1) Get the link to the metadata file, if provided by the backend. + metadata_link = req.link.metadata_link() + if metadata_link is None: + return None + assert req.req is not None + logger.verbose( + "Obtaining dependency information for %s from %s", + req.req, + metadata_link, + ) + # (2) Download the contents of the METADATA file, separate from the dist itself. + metadata_file = get_http_url( + metadata_link, + self._download, + hashes=metadata_link.as_hashes(), + ) + with open(metadata_file.path, "rb") as f: + metadata_contents = f.read() + # (3) Generate a dist just from those file contents. + metadata_dist = get_metadata_distribution( + metadata_contents, + req.link.filename, + req.req.name, + ) + # (4) Ensure the Name: field from the METADATA file matches the name from the + # install requirement. + # + # NB: raw_name will fall back to the name from the install requirement if + # the Name: field is not present, but it's noted in the raw_name docstring + # that that should NEVER happen anyway. + if canonicalize_name(metadata_dist.raw_name) != canonicalize_name(req.req.name): + raise MetadataInconsistent( + req, "Name", req.req.name, metadata_dist.raw_name + ) + return metadata_dist + def _fetch_metadata_using_lazy_wheel( self, link: Link, ) -> Optional[BaseDistribution]: """Fetch metadata using lazy wheel, if possible.""" + # --use-feature=fast-deps must be provided. if not self.use_lazy_wheel: return None - if self.require_hashes: - logger.debug("Lazy wheel is not used as hash checking is required") - return None if link.is_file or not link.is_wheel: logger.debug( - "Lazy wheel is not used as %r does not points to a remote wheel", + "Lazy wheel is not used as %r does not point to a remote wheel", link, ) return None @@ -402,7 +469,19 @@ class RequirementPreparer: for link, (filepath, _) in batch_download: logger.debug("Downloading link %s to %s", link, filepath) req = links_to_fully_download[link] + # Record the downloaded file path so wheel reqs can extract a Distribution + # in .get_dist(). req.local_file_path = filepath + # Record that the file is downloaded so we don't do it again in + # _prepare_linked_requirement(). + self._downloaded[req.link.url] = filepath + + # If this is an sdist, we need to unpack it after downloading, but the + # .source_dir won't be set up until we are in _prepare_linked_requirement(). + # Add the downloaded archive to the install requirement to unpack after + # preparing the source dir. + if not req.is_wheel: + req.needs_unpacked_archive(Path(filepath)) # This step is necessary to ensure all lazy wheels are processed # successfully by the 'download', 'wheel', and 'install' commands. @@ -414,25 +493,35 @@ class RequirementPreparer: ) -> BaseDistribution: """Prepare a requirement to be obtained from req.link.""" assert req.link - link = req.link self._log_preparing_link(req) with indent_log(): # Check if the relevant file is already available # in the download directory file_path = None - if self.download_dir is not None and link.is_wheel: + if self.download_dir is not None and req.link.is_wheel: hashes = self._get_linked_req_hashes(req) - file_path = _check_download_dir(req.link, self.download_dir, hashes) + file_path = _check_download_dir( + req.link, + self.download_dir, + hashes, + # When a locally built wheel has been found in cache, we don't warn + # about re-downloading when the already downloaded wheel hash does + # not match. This is because the hash must be checked against the + # original link, not the cached link. It that case the already + # downloaded file will be removed and re-fetched from cache (which + # implies a hash check against the cache entry's origin.json). + warn_on_hash_mismatch=not req.is_wheel_from_cache, + ) if file_path is not None: # The file is already available, so mark it as downloaded self._downloaded[req.link.url] = file_path else: # The file is not available, attempt to fetch only metadata - wheel_dist = self._fetch_metadata_using_lazy_wheel(link) - if wheel_dist is not None: + metadata_dist = self._fetch_metadata_only(req) + if metadata_dist is not None: req.needs_more_preparation = True - return wheel_dist + return metadata_dist # None of the optimizations worked, fully prepare the requirement return self._prepare_linked_requirement(req, parallel_builds) @@ -473,9 +562,35 @@ class RequirementPreparer: assert req.link link = req.link - self._ensure_link_req_src_dir(req, parallel_builds) hashes = self._get_linked_req_hashes(req) + if hashes and req.is_wheel_from_cache: + assert req.download_info is not None + assert link.is_wheel + assert link.is_file + # We need to verify hashes, and we have found the requirement in the cache + # of locally built wheels. + if ( + isinstance(req.download_info.info, ArchiveInfo) + and req.download_info.info.hashes + and hashes.has_one_of(req.download_info.info.hashes) + ): + # At this point we know the requirement was built from a hashable source + # artifact, and we verified that the cache entry's hash of the original + # artifact matches one of the hashes we expect. We don't verify hashes + # against the cached wheel, because the wheel is not the original. + hashes = None + else: + logger.warning( + "The hashes of the source archive found in cache entry " + "don't match, ignoring cached built wheel " + "and re-downloading source." + ) + req.link = req.cached_wheel_source_link + link = req.link + + self._ensure_link_req_src_dir(req, parallel_builds) + if link.is_existing_dir(): local_file = None elif link.url not in self._downloaded: @@ -490,8 +605,8 @@ class RequirementPreparer: ) except NetworkConnectionError as exc: raise InstallationError( - "Could not install requirement {} because of HTTP " - "error {} for URL {}".format(req, exc, link) + f"Could not install requirement {req} because of HTTP " + f"error {exc} for URL {link}" ) else: file_path = self._downloaded[link.url] @@ -508,12 +623,15 @@ class RequirementPreparer: # Make sure we have a hash in download_info. If we got it as part of the # URL, it will have been verified and we can rely on it. Otherwise we # compute it from the downloaded file. + # FIXME: https://github.com/pypa/pip/issues/11943 if ( isinstance(req.download_info.info, ArchiveInfo) - and not req.download_info.info.hash + and not req.download_info.info.hashes and local_file ): hash = hash_file(local_file.path)[0].hexdigest() + # We populate info.hash for backward compatibility. + # This will automatically populate info.hashes. req.download_info.info.hash = f"sha256={hash}" # For use in later processing, @@ -568,9 +686,9 @@ class RequirementPreparer: with indent_log(): if self.require_hashes: raise InstallationError( - "The editable requirement {} cannot be installed when " + f"The editable requirement {req} cannot be installed when " "requiring hashes, because there is no single file to " - "hash.".format(req) + "hash." ) req.ensure_has_source_dir(self.src_dir) req.update_editable() @@ -598,7 +716,7 @@ class RequirementPreparer: assert req.satisfied_by, "req should have been satisfied but isn't" assert skip_reason is not None, ( "did not get skip reason skipped but req.satisfied_by " - "is set to {}".format(req.satisfied_by) + f"is set to {req.satisfied_by}" ) logger.info( "Requirement %s: %s (%s)", skip_reason, req, req.satisfied_by.version diff --git a/venv/Lib/site-packages/pip/_internal/pyproject.py b/venv/Lib/site-packages/pip/_internal/pyproject.py index 1e9119f..0e8452f 100644 --- a/venv/Lib/site-packages/pip/_internal/pyproject.py +++ b/venv/Lib/site-packages/pip/_internal/pyproject.py @@ -1,16 +1,22 @@ import importlib.util import os +import sys from collections import namedtuple from typing import Any, List, Optional -from pip._vendor import tomli -from pip._vendor.packaging.requirements import InvalidRequirement, Requirement +if sys.version_info >= (3, 11): + import tomllib +else: + from pip._vendor import tomli as tomllib + +from pip._vendor.packaging.requirements import InvalidRequirement from pip._internal.exceptions import ( InstallationError, InvalidPyProjectBuildRequires, MissingPyProjectBuildRequires, ) +from pip._internal.utils.packaging import get_requirement def _is_list_of_str(obj: Any) -> bool: @@ -61,13 +67,13 @@ def load_pyproject_toml( if has_pyproject: with open(pyproject_toml, encoding="utf-8") as f: - pp_toml = tomli.loads(f.read()) + pp_toml = tomllib.loads(f.read()) build_system = pp_toml.get("build-system") else: build_system = None # The following cases must use PEP 517 - # We check for use_pep517 being non-None and falsey because that means + # We check for use_pep517 being non-None and falsy because that means # the user explicitly requested --no-use-pep517. The value 0 as # opposed to False can occur when the value is provided via an # environment variable or config file option (due to the quirk of @@ -91,14 +97,19 @@ def load_pyproject_toml( # If we haven't worked out whether to use PEP 517 yet, # and the user hasn't explicitly stated a preference, # we do so if the project has a pyproject.toml file - # or if we cannot import setuptools. + # or if we cannot import setuptools or wheels. - # We fallback to PEP 517 when without setuptools, + # We fallback to PEP 517 when without setuptools or without the wheel package, # so setuptools can be installed as a default build backend. # For more info see: # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9 + # https://github.com/pypa/pip/issues/8559 elif use_pep517 is None: - use_pep517 = has_pyproject or not importlib.util.find_spec("setuptools") + use_pep517 = ( + has_pyproject + or not importlib.util.find_spec("setuptools") + or not importlib.util.find_spec("wheel") + ) # At this point, we know whether we're going to use PEP 517. assert use_pep517 is not None @@ -118,7 +129,7 @@ def load_pyproject_toml( # a version of setuptools that supports that backend. build_system = { - "requires": ["setuptools>=40.8.0", "wheel"], + "requires": ["setuptools>=40.8.0"], "build-backend": "setuptools.build_meta:__legacy__", } @@ -146,7 +157,7 @@ def load_pyproject_toml( # Each requirement must be valid as per PEP 508 for requirement in requires: try: - Requirement(requirement) + get_requirement(requirement) except InvalidRequirement as error: raise InvalidPyProjectBuildRequires( package=req_name, @@ -159,9 +170,8 @@ def load_pyproject_toml( if backend is None: # If the user didn't specify a backend, we assume they want to use # the setuptools backend. But we can't be sure they have included - # a version of setuptools which supplies the backend, or wheel - # (which is needed by the backend) in their requirements. So we - # make a note to check that those requirements are present once + # a version of setuptools which supplies the backend. So we + # make a note to check that this requirement is present once # we have set up the environment. # This is quite a lot of work to check for a very specific case. But # the problem is, that case is potentially quite common - projects that @@ -170,6 +180,6 @@ def load_pyproject_toml( # tools themselves. The original PEP 518 code had a similar check (but # implemented in a different way). backend = "setuptools.build_meta:__legacy__" - check = ["setuptools>=40.8.0", "wheel"] + check = ["setuptools>=40.8.0"] return BuildSystemDetails(requires, backend, check, backend_path) diff --git a/venv/Lib/site-packages/pip/_internal/req/__init__.py b/venv/Lib/site-packages/pip/_internal/req/__init__.py index 8d56359..422d851 100644 --- a/venv/Lib/site-packages/pip/_internal/req/__init__.py +++ b/venv/Lib/site-packages/pip/_internal/req/__init__.py @@ -1,5 +1,6 @@ import collections import logging +from dataclasses import dataclass from typing import Generator, List, Optional, Sequence, Tuple from pip._internal.utils.logging import indent_log @@ -18,12 +19,9 @@ __all__ = [ logger = logging.getLogger(__name__) +@dataclass(frozen=True) class InstallationResult: - def __init__(self, name: str) -> None: - self.name = name - - def __repr__(self) -> str: - return f"InstallationResult(name={self.name!r})" + name: str def _validate_requirements( @@ -36,7 +34,6 @@ def _validate_requirements( def install_given_reqs( requirements: List[InstallRequirement], - install_options: List[str], global_options: Sequence[str], root: Optional[str], home: Optional[str], @@ -71,7 +68,6 @@ def install_given_reqs( try: requirement.install( - install_options, global_options, root=root, home=home, diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-310.pyc index d89fdb1ec1988c66b5d2945537d11d978fe4175b..b7c8b54551f8d7455394e1972209528959a380c9 100644 GIT binary patch delta 1261 zcmY*Y&x_ke6rMMdMx!6LY_H>8ubqXEQZQ^Fx%CiApegNXDNRF&XfW>1*f>aXcBD<3 zAmg$Q^t6;B=%Ey9_tw9p=R!|9HuO+>Z<{vV^o`aj=?w49d*6F+toP>gSMASR`?Ffj zCAfZn_S57ZTFC= zup{b{$)LL+B9NAJG`wxnI1?ag^%b9Q7` zY@_U;1bBG|Z)u6H*u`6R1>7Qo-miKP2LmV_G0H}V(I|zq*oTutA93YrrH5Cxrb(KO zqG&joK9tE&$)ofmtYTv|dm@uVO!?n3(7S<>c2G$Yf*>KiO{5`B0oRG3_}fO&r@O|% zz$(5q2D@c29FCG?mW{IMEJ=sM?}^gIs#BcM53Z;HZSAKfDwp`QLP{UM4yVQ4NM(SwSz}#VB+RNbk(-TI>U#fXo`(X-Ozv6^e~p{uIXpoXhR*$ zGo`WOH}m#_qw#9h(9k1#2PJI-AsJagMsu=+HOzU=RXa0Q*s-81E9Wb=CTmzzO^Ugb z*-P@p1PJ1MO>UBVcR!|cckboheMh}p)fu^~v#ZQHW_tHsE=*ya!rU)@ur4qBCv^n9 z9CDf)xtUuz%WYww+Cc7*q-m1Oe>?`FcaD?7+*&Gge^p;2azY+y^npfE`>Q~sxwC3y z&D_;306E&bLj*I4NtT9=-6GdWx_pEYz1iKWpg3Yb!o{M-`^C_{2)$x%?*T8qv8OHl zYJ*z!0;-R;I!}9x-`qQYT#f0sPfpsiHc>vd0fFqBJ9w=8m$oVp`cn&$)C}zi7#k z0K@S#lIL{yw7a2v^)D!GjifSDei1o4i>9uBQ!Cw~YHOuAQktL4W>NKVud%J_wW1uq z9?!&aB;Q81ko0|2oN(}=4?e|>7N@SwjRsJY0e#t~?iuCUVw9dSgZ{%z`hsm)^l!@O PU(}}0DW`ujr~b#kaE%E< literal 2582 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 V&^|?5=of4;m+2oq41c6`TS8ot_DND@v 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 pv)+|5zvB}=m1Y-4YiJ40$$ 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 delta 9718 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 diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-310.pyc index 1f7668d5254ca09d9c3f4fbcd60bb5fbd354e2d9..c16ed77e29bd1073914d41f71510e2d88bb89a59 100644 GIT binary patch delta 19 Zcmdlaw@HpGpO=@50SLZ5-pHlF4*)Xe1qlEE delta 19 Zcmdlaw@HpGpO=@50SH9JH*#t40{|(c16%+A diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc index a5571e0640ca3eb81e9bfd64dc57f7246cdf65a9..1b00f73fc1444b6c50e18daf73f3c6fb8d9c04ac 100644 GIT binary patch delta 6071 zcmZuVZEzdcarX{~!{LJ<2!bEr2MF*Rq(n(3Ma32+QI=#|Qf#S~WYtXK>k02j9t|9* zcL!2b!J%x)iKlfE$uE4U3_di(JeXFUL{P5Ped8QDb zixY`T)SquHB<2!@wz)PjR`czJj=2tj2lAbTCI&W#eu>@~C3$=n!iGRJ8Yo@R3wjhP|92qp8rq%^P578<{y%8*K-v33GyWm>oNGZlF?ycGBbx1zx>}c9~&wTqptq1g)F) zfau~`(so=UpZD4?*j5dF)N&llUU=Nh z6&dBv%U4vz^BK<5Jmx#ulOw$l) z7eNYur3UGEC5e&Ow;xh%QXwP2^+!rK?FlcR7lKS`)g0^>yVb2y<0PIIL zRO+YzG~X~$0&EgcPodzS909cc(*QxP96Zi%^WMPNM$(nb67_wWJWI;*ap@BW)_tyT zNvZhDr0m<2*OjvJghZsWQc{W4u3%U@YSBrF_(A5EI6}Z+UAvIcG%!QYMPu# z15eGy#}FGw5!ER&*QD$e4t$2a#&!Xg^|9mpqtVo~u;5YT7FiI;6${Ho&i!SW5qYMm zD&$s_$Ug1=6n}`w*A&9eS1VDUJd3iRD2>v>Jk2h$LJn4UTV|(W)+2YUt*sMhLNnCL zx%igDm-+W&t2=ByjC!6xAlSEMf-{a;6LI+SEtA0$LbbvA_@A~+KQsm-*g9zx6!E!$ z7zQaz*vAlWREJjTOGV3G0jeVdND%(xcpul}ryjnyx<^o5eNn5hpA}Xty4#^(XMo`< zs#5^S*V6n}ONO_!9{ULD6MS3Z^tR6nP>bQlW*A|x*JbIAd6t-6|w5I@%2$N0X%F8*p)8yVw&(AA%8(5dOVWm~SUzsEo9+M}R3 z{BI`Ost3E<$Qcp1G)!%$FSzcx`h=%B#)_#!!ZbL{OJKN=VCLK+Thrl8au(mOzS8qL z$$SdMp9hc)HEs>zzh^m34W34iWz`+;QWi~vdK$z>M~wYCs`(6ph7~o7ccU9?uly1u^XtZVNH>oVe558{roe7lcbNoH#oKNNo1Z!upNcp#335VUIpN3%dEI;GIx!= zhI6kY*j6vFA)I>#z&r5N&IU;#AzxgJN8{b0wopKBO%TD61CH%qwKOzHRB<}?@mGf1 zLO!4!gU6ZT?+lM5-9SZigPWu*=^-kes};O#n2qzF4EJx~8@-5LD6W`PUpCxDhwa0u zV4juqoRM2JSv!u~#qKup)>Tum)o8Sy1mgAED-w%Azl@{9BYTYVj; zBQ3KTpyx0b>p#T(@Q77l)8pJ?U8x(2@7m#dG}H^}5F1EWILD{aUTmq}NJU;Jg$@U<0FKxg|Etm6X=o^=C3%Ig zcHS~Jxga)?S~FhQ`#T`#wQfcFth;!k*0yagqF#sp2w2%Hg1b}53m6o#(p@}{He(uv zs&9^s%NxQMFQLH82)+)$)0nX;y7{>o>qK!CQrs=-uorVCv}|vo zsEYuX$j&1W`xbW~L-Uylz*Cut+XGrq;o@(hZ`eEh^zN|~y4&-CfenVU_ki$;D&M`E zMBwmu7T9rA*T?^IV*Qlxl%H*zk0x&008aTfP6!DR&jzPxa3(?UjkR^o_x#|g_kkH~ z69p)Mg4YlT4~a7#v!%AoHo)pdQ>^jNk+h273WB@e!~O*3u2%nU?-Y4lxaxJ}5mr|a zL#MNM5r`PPirALZ>f7zlaJE4&a(Tb&zf>kmUF=`o?lPfqap56LJvRvpm;IGi+?GUgqf5<|Uc_lDTxgoaxJ|&6 zm`%WjjRJpPIZE5gO?a6hl6@I8r$JM%o8hZW8AR|Iz;L%u}Z%+Fn+_DAA5`3}7d` zDFXkKWf@@C%R!!*PVPySRj_!6ZD1?f6>#OsD24UH7&L=y7Oc9#t?B(2zk;i-t*;y} zw}Q5wmq7}>aFbkq;i6ShdSHOyAOPRU^|#k+#_b#WWHVf;6O8(yqgg&fFW#V9k~8LYbc0A zzzjE*JYH+@#_~hne*eiftc>h_1P>tCkKh};>w%%5KRxOe(^p5beD;A$;VC5aAn4;? zd!V{!7*J2acfbzXB6?wQN7R?$K62+mQF}N4?7?nwAAj@U#jb-W*<{)CMLl248F)Xv zvpaduOy4l8;!A!HnSyYlC^%Q6sY<7YF%Av$)?LdQ8wE%}% z-eg}whOlMpCAjN4a1O9$l#cS>IFvb#Upu_`V@3Dq@p|)mLUc_rnw z_r=5UaC>WKFy0&L2{p+|Ct+{$)nqRxN6&=+7+)n$C~U7%eC=rO2~oloPZ6;YRrUyQ zK_7*8393W)YC822C`7k61GZE z(~Xd0vq)*M8-seW8hL0hIUND5=d*#Dc41is1%zdo`@#&?0$g=R;9D9M;z`5!ryf37 z%eG)+wu$r-i6$~jB$dcEA-HXwz(n9M86K1&!|_PcB)G5oL(TDShV$8J(K^?9I#Dye z3$tF-DlGG(kI(B*Y3Tgwx0U4<=c8~KTP!Esm=n8hyk+V5t8j5es@8e(5~U3U}3 z_tFV0pN7j?__dQs-g7cY;(YjIMr}ov3I6EG6kk4haKlU8OLqHPX{~?$G71To3-<_r z4CCA+0<286R>?)|8iHpK;Jy-W*b#&+zj@kBp*T)UdGj!YOmfZw(8QfUgZut2__!Jq gA6g^uF{~4w2%k7L*qrHV9qy0ri(1l#v=Q(9euN-?H*?r z#DjN%Vo-K0+Io%3kFr$(EZZ_1TXJ%Wohm=%I4L`+sPtj;!`@0s>N?VFkI>FMt2>FJ)=UnIYJiG=NNI3&PdedFEP-@FiRC-1zl$GAWQUC{lR zST;Tt&(=-V@xGj?&o)do@OB{6m~EPB;%z0CPMy3Y!Y9pbC;fokUdW{i+7SYL!uUVK;^r&8YTbkOV#|%Y}11_+G6PpE~ zzQ^c{q}S>7Fl*Qt)*Fn53Z9bQs5jk~)>g^Xh~8{e841oPg1<1eMQ??v$$Mbh^mf3E z?!wd!gl7=Wi!{>|6dB(!uKF>!SlmJ&4qjV;Ghv znXZxDB(xvLdl2*@QeLpk8w%`ikS?zSc3y(d zzabXC!qHXvzy|qKv7i)!`5?Gk=xNy5LTGEMk`L)sjY4_)uJP*K<2TOmjSXu* zD+ZK9q^4qH*+g)Cb!GI7W?8nYg6T@TuHHgR6^7MI_n*0NX;PgrGlq&3Gxma|CliE@ zfx$dq&djaIw+bgt+$yY0sgKzUYSx^cbJb}>)uv&JYpc{q+cyoW&QLq6x^t$Z-ZZsi z>HthtORGJYQAb8*Y??MksIe`;$cSZ+=tj;_ZxsfTD+B5|({higSLO^gr=_oJvxd5; zIa?euhOSO817(u^F4#z_SuoVK>dC+}tGQlqi>E<7g=&l39lZd^iMrLu{nwMG zHODA5`z|g z;#1Q9(6hy#hwhS2l`roYxm^b(I6iAw#!`-+oM%6&9!r*$y9Cs92&c%7O~QxK3+$Z+bvH$N z0r`?GsY;6DNN8L)(=Kv5xx#)}v$#vP(}1T_2sn9pPH@~YN>lPI9UTjvM@B@W9qcco zhsG1ogRrwB1$_)z;4Xrbrm$Vf4y8=Z+orY3YHOYUhryp9gKaey6U39KZM$V7)5}1x z#(q?5A3+H?VuxPe^mzf@q!{<;lZc+)rs4MFlb>O;vHqzvB0kJvh8iE9aR-NH0VE=P z6X_Lbd-6>!vtT$|JL$NTK8$po>_1|Cow%tKcO9Hn%Xw9))U4rRcul1eLD=g(@vBwb zK76@e_L+DSaoN}6BV?&~H~x8%9A?>ut0x}>4!gIyWZy0Gz%k3{2Cc9&eFEnE11^7! ziH(QuL$9N!5OA5w`!$1O76QI=k7DaO0)7%@)4|x22!pUIjeYHlh*1G}(bTrP=_w>} z=ra3$<6uc0u2V1jZKFy)%c4!~#K)3NJ>)jKbE=)$O}~YkC)GSg5{xx>H*@0B3}mdN zQl@3PsnlES?dDOU7T;?gAqPK!3zwxvS-~Qo!ci4~r#RY8BL$nj+Yao>)@E|IxYGI+ z(sc((KMf!es^CMp2|mG2wfBa(M6LXowoH0N}C|*2#td*PjA+8Yzf*k-gt}@d}z1 z1O<$m59o5&{)~CmKtYhES-T z$xOq|)QkclRY&Yw};c_X8B?5Gaz1`P6 zjjMRosVrRmI(Hlgq9b=M&ZR6EmkHH7h;|D>11>$-NW2VJns>65i{N{g4L7-cHmS<~ zyuYq-M-KD=SICn!0$D6!Kk8pN3h}=lMz_~hp}or>{9X&Cz+&J;a1)N>^2kn+*)s!& z&*ApC!aRW_j_^E8gyatUK3B?%YlOEU`P(3ngOz$RQabHujJ&WOz#dJos=*O*A3HkO zxr&!Q1hSn2N>9T84|B8uTNqP3*;s=8S;#v3@{ z%Lv{;a00gl5pS~34G(pw zi1xwq6=KmJ1LDczyTcSmAK>=z)3T6pq}dS#R4>m|5mlkO z0udE9Qd@qCy_@{^C;k~oKtz7H14w=w0k^{tws7Z5+T#9g2PCfQPZ4zsK_0;e*P(w8 zV})YZ-UH+kx7a4qaH+qFt+Hvkr7?z-ZMS`BeuASFe39}C?A3kW9N}!&kpxdmB^@HZ zMz&5>L}axiamMyHhJrBegU@-b_{RPQLVm~oW$e|}m-A%4h5p)Y)nn^z(5~KqvkY|< znQwod&`93D9?y##ga~eAzGl4x+j<-dqA>5*bJ)p8>)=2ly_%2c_4zOsLqxE$z^My3 zsctt$3A~63)toD=M1Di@*y1AA^t29mv;05hw!g+5>{#kdJ;*&>K-b_-)FI z0GnS9fTD~ZY#8l?dXVV5iIB%p~RkL)cLKhr$(NN*G#hO-2rx&Q^8kuEPH(b0BEGRDL%=8?udmVLr+Q`_} zELO9oyM0sB6 z7DxL)8BanJK+xDhdR4rTOy!_N*{V27reUX!wUVRk@nct8j^fO)Y0cRD83x~IwgM7+ z>sV*P^Eu0oC+Da!V=j3?=%j6H#+>yOOc{9|SBus>!D^2W9w=W(e}{vokarwvu7#Wn z*^0wcOkT?Ho9GzQbg}I5%RTfsl18`7YdxhoDPwlFbg%KG_6O{p;~i(tBAEo)iB-De z6bfd8^vi(q8cOLLCeK+AHDl0MkhIFQQVUQuJCGOB2(A}qljB{JQAEZbvfYVE6P^`Z zn=bR0DO!UxJc7#5N;G)BbjB$?QH0SM%0~Jn+Z=y|sO+OBE+4?1fI>J861emi*dbe9 z_%`z6t{B8;3k=xqH!zg_p4~lh>mZisq9_sZed&*i5|W}k@f4wGk4cJHO(KAieIZ{R z6z(1G$v%lF?AH?j?a=bY$}6HK53rA)9)VN? zGBx&(r>CN2N8_bllqDychbE8%>bQO9+#_A!_zT4w6A`f=mjKcW@Z(A7M3wi>Wx$y1 zt7ps$8_=Tsri7@uyL!VqzzZyD6yCdL>94UD-1bR_N=W=L&gDlzHmtM_1?~j9HrX@A z75)Rx@Z;i8wLlTY#kiN;xMNQgi<5iFgJIx$1@dFgolC~AVJ_J#xEP8-v7Fg91g=u4 z9A3W5Ecub+C07box)S#tw0$WT;~v9ZiQn(#Jt}V$?)G^Rd^-dUMTn7@KU5QIr8u5A zK=&dqzH$GGt#<%;5i^@(|M?M}ee7(D9LC`YyK%OS)UapIswB!@KifTs@x^O}N4_Lf z({PL}EtBLiIhnC%XVL6fFG5E5zh^rn%xqZ0x$)JKI@~&36D~T2N&bFIF_4t~$=qck_TVKc+C&9RagGsN#s|)&Kwi diff --git a/venv/Lib/site-packages/pip/_internal/req/constructors.py b/venv/Lib/site-packages/pip/_internal/req/constructors.py index dea7c3b..56a964f 100644 --- a/venv/Lib/site-packages/pip/_internal/req/constructors.py +++ b/venv/Lib/site-packages/pip/_internal/req/constructors.py @@ -8,10 +8,12 @@ These are meant to be used elsewhere within pip to create instances of InstallRequirement. """ +import copy import logging import os import re -from typing import Any, Dict, Optional, Set, Tuple, Union +from dataclasses import dataclass +from typing import Collection, Dict, List, Optional, Set, Tuple, Union from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.requirements import InvalidRequirement, Requirement @@ -57,6 +59,31 @@ def convert_extras(extras: Optional[str]) -> Set[str]: return get_requirement("placeholder" + extras.lower()).extras +def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requirement: + """ + Returns a new requirement based on the given one, with the supplied extras. If the + given requirement already has extras those are replaced (or dropped if no new extras + are given). + """ + match: Optional[re.Match[str]] = re.fullmatch( + # see https://peps.python.org/pep-0508/#complete-grammar + r"([\w\t .-]+)(\[[^\]]*\])?(.*)", + str(req), + flags=re.ASCII, + ) + # ireq.req is a valid requirement so the regex should always match + assert ( + match is not None + ), f"regex match on requirement {req} failed, this should never happen" + pre: Optional[str] = match.group(1) + post: Optional[str] = match.group(3) + assert ( + pre is not None and post is not None + ), f"regex group selection for requirement {req} failed, this should never happen" + extras: str = "[{}]".format(",".join(sorted(new_extras)) if new_extras else "") + return get_requirement(f"{pre}{extras}{post}") + + def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: """Parses an editable requirement into: - a requirement name @@ -106,8 +133,8 @@ def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: package_name = link.egg_fragment if not package_name: raise InstallationError( - "Could not detect requirement name for '{}', please specify one " - "with #egg=your_package_name".format(editable_req) + f"Could not detect requirement name for '{editable_req}', " + "please specify one with #egg=your_package_name" ) return package_name, url, set() @@ -136,7 +163,7 @@ def check_first_requirement_in_file(filename: str) -> None: # If there is a line continuation, drop it, and append the next line. if line.endswith("\\"): line = line[:-2].strip() + next(lines, "") - Requirement(line) + get_requirement(line) return @@ -165,18 +192,12 @@ def deduce_helpful_msg(req: str) -> str: return msg +@dataclass(frozen=True) class RequirementParts: - def __init__( - self, - requirement: Optional[Requirement], - link: Optional[Link], - markers: Optional[Marker], - extras: Set[str], - ): - self.requirement = requirement - self.link = link - self.markers = markers - self.extras = extras + requirement: Optional[Requirement] + link: Optional[Link] + markers: Optional[Marker] + extras: Set[str] def parse_req_from_editable(editable_req: str) -> RequirementParts: @@ -184,9 +205,9 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts: if name is not None: try: - req: Optional[Requirement] = Requirement(name) - except InvalidRequirement: - raise InstallationError(f"Invalid requirement: '{name}'") + req: Optional[Requirement] = get_requirement(name) + except InvalidRequirement as exc: + raise InstallationError(f"Invalid requirement: {name!r}: {exc}") else: req = None @@ -201,15 +222,16 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts: def install_req_from_editable( editable_req: str, comes_from: Optional[Union[InstallRequirement, str]] = None, + *, use_pep517: Optional[bool] = None, isolated: bool = False, - options: Optional[Dict[str, Any]] = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, user_supplied: bool = False, permit_editable_wheels: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: - parts = parse_req_from_editable(editable_req) return InstallRequirement( @@ -222,9 +244,8 @@ def install_req_from_editable( constraint=constraint, use_pep517=use_pep517, isolated=isolated, - install_options=options.get("install_options", []) if options else [], - global_options=options.get("global_options", []) if options else [], - hash_options=options.get("hashes", {}) if options else {}, + global_options=global_options, + hash_options=hash_options, config_settings=config_settings, extras=parts.extras, ) @@ -338,8 +359,8 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar def _parse_req_string(req_as_string: str) -> Requirement: try: - req = get_requirement(req_as_string) - except InvalidRequirement: + return get_requirement(req_as_string) + except InvalidRequirement as exc: if os.path.sep in req_as_string: add_msg = "It looks like a path." add_msg += deduce_helpful_msg(req_as_string) @@ -349,21 +370,10 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar add_msg = "= is not a valid operator. Did you mean == ?" else: add_msg = "" - msg = with_source(f"Invalid requirement: {req_as_string!r}") + msg = with_source(f"Invalid requirement: {req_as_string!r}: {exc}") if add_msg: msg += f"\nHint: {add_msg}" raise InstallationError(msg) - else: - # Deprecate extras after specifiers: "name>=1.0[extras]" - # This currently works by accident because _strip_extras() parses - # any extras in the end of the string and those are saved in - # RequirementParts - for spec in req.specifier: - spec_str = str(spec) - if spec_str.endswith("]"): - msg = f"Extras after version '{spec_str}'." - raise InstallationError(msg) - return req if req_as_string is not None: req: Optional[Requirement] = _parse_req_string(req_as_string) @@ -376,13 +386,15 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar def install_req_from_line( name: str, comes_from: Optional[Union[str, InstallRequirement]] = None, + *, use_pep517: Optional[bool] = None, isolated: bool = False, - options: Optional[Dict[str, Any]] = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, line_source: Optional[str] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. @@ -399,9 +411,8 @@ def install_req_from_line( markers=parts.markers, use_pep517=use_pep517, isolated=isolated, - install_options=options.get("install_options", []) if options else [], - global_options=options.get("global_options", []) if options else [], - hash_options=options.get("hashes", {}) if options else {}, + global_options=global_options, + hash_options=hash_options, config_settings=config_settings, constraint=constraint, extras=parts.extras, @@ -415,12 +426,11 @@ def install_req_from_req_string( isolated: bool = False, use_pep517: Optional[bool] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, ) -> InstallRequirement: try: req = get_requirement(req_string) - except InvalidRequirement: - raise InstallationError(f"Invalid requirement: '{req_string}'") + except InvalidRequirement as exc: + raise InstallationError(f"Invalid requirement: {req_string!r}: {exc}") domains_not_allowed = [ PyPI.file_storage_domain, @@ -436,7 +446,7 @@ def install_req_from_req_string( raise InstallationError( "Packages installed from PyPI cannot depend on packages " "which are not also hosted on PyPI.\n" - "{} depends on {} ".format(comes_from.name, req) + f"{comes_from.name} depends on {req} " ) return InstallRequirement( @@ -445,7 +455,6 @@ def install_req_from_req_string( isolated=isolated, use_pep517=use_pep517, user_supplied=user_supplied, - config_settings=config_settings, ) @@ -454,7 +463,7 @@ def install_req_from_parsed_requirement( isolated: bool = False, use_pep517: Optional[bool] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: if parsed_req.is_editable: req = install_req_from_editable( @@ -473,7 +482,14 @@ def install_req_from_parsed_requirement( comes_from=parsed_req.comes_from, use_pep517=use_pep517, isolated=isolated, - options=parsed_req.options, + global_options=( + parsed_req.options.get("global_options", []) + if parsed_req.options + else [] + ), + hash_options=( + parsed_req.options.get("hashes", {}) if parsed_req.options else {} + ), constraint=parsed_req.constraint, line_source=parsed_req.line_source, user_supplied=user_supplied, @@ -493,9 +509,52 @@ def install_req_from_link_and_ireq( markers=ireq.markers, use_pep517=ireq.use_pep517, isolated=ireq.isolated, - install_options=ireq.install_options, global_options=ireq.global_options, hash_options=ireq.hash_options, config_settings=ireq.config_settings, user_supplied=ireq.user_supplied, ) + + +def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement: + """ + Creates a new InstallationRequirement using the given template but without + any extras. Sets the original requirement as the new one's parent + (comes_from). + """ + return InstallRequirement( + req=( + _set_requirement_extras(ireq.req, set()) if ireq.req is not None else None + ), + comes_from=ireq, + editable=ireq.editable, + link=ireq.link, + markers=ireq.markers, + use_pep517=ireq.use_pep517, + isolated=ireq.isolated, + global_options=ireq.global_options, + hash_options=ireq.hash_options, + constraint=ireq.constraint, + extras=[], + config_settings=ireq.config_settings, + user_supplied=ireq.user_supplied, + permit_editable_wheels=ireq.permit_editable_wheels, + ) + + +def install_req_extend_extras( + ireq: InstallRequirement, + extras: Collection[str], +) -> InstallRequirement: + """ + Returns a copy of an installation requirement with some additional extras. + Makes a shallow copy of the ireq object. + """ + result = copy.copy(ireq) + result.extras = {*ireq.extras, *extras} + result.req = ( + _set_requirement_extras(ireq.req, result.extras) + if ireq.req is not None + else None + ) + return result diff --git a/venv/Lib/site-packages/pip/_internal/req/req_file.py b/venv/Lib/site-packages/pip/_internal/req/req_file.py index 4550c72..f6ba70f 100644 --- a/venv/Lib/site-packages/pip/_internal/req/req_file.py +++ b/venv/Lib/site-packages/pip/_internal/req/req_file.py @@ -2,11 +2,16 @@ Requirements file parsing """ +import codecs +import locale +import logging import optparse import os import re import shlex +import sys import urllib.parse +from dataclasses import dataclass from optparse import Values from typing import ( TYPE_CHECKING, @@ -16,6 +21,7 @@ from typing import ( Generator, Iterable, List, + NoReturn, Optional, Tuple, ) @@ -23,17 +29,10 @@ from typing import ( from pip._internal.cli import cmdoptions from pip._internal.exceptions import InstallationError, RequirementsFileParseError from pip._internal.models.search_scope import SearchScope -from pip._internal.network.session import PipSession -from pip._internal.network.utils import raise_for_status -from pip._internal.utils.encoding import auto_decode -from pip._internal.utils.urls import get_url_scheme if TYPE_CHECKING: - # NoReturn introduced in 3.6.2; imported only for type checking to maintain - # pip compatibility with older patch versions of Python 3.6 - from typing import NoReturn - from pip._internal.index.package_finder import PackageFinder + from pip._internal.network.session import PipSession __all__ = ["parse_requirements"] @@ -69,63 +68,87 @@ SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [ # options to be passed to requirements SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [ - cmdoptions.install_options, cmdoptions.global_options, cmdoptions.hash, + cmdoptions.config_settings, ] +SUPPORTED_OPTIONS_EDITABLE_REQ: List[Callable[..., optparse.Option]] = [ + cmdoptions.config_settings, +] + + # the 'dest' string values SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] +SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [ + str(o().dest) for o in SUPPORTED_OPTIONS_EDITABLE_REQ +] + +# order of BOMS is important: codecs.BOM_UTF16_LE is a prefix of codecs.BOM_UTF32_LE +# so data.startswith(BOM_UTF16_LE) would be true for UTF32_LE data +BOMS: List[Tuple[bytes, str]] = [ + (codecs.BOM_UTF8, "utf-8"), + (codecs.BOM_UTF32, "utf-32"), + (codecs.BOM_UTF32_BE, "utf-32-be"), + (codecs.BOM_UTF32_LE, "utf-32-le"), + (codecs.BOM_UTF16, "utf-16"), + (codecs.BOM_UTF16_BE, "utf-16-be"), + (codecs.BOM_UTF16_LE, "utf-16-le"), +] + +PEP263_ENCODING_RE = re.compile(rb"coding[:=]\s*([-\w.]+)") +DEFAULT_ENCODING = "utf-8" + +logger = logging.getLogger(__name__) +@dataclass(frozen=True) class ParsedRequirement: - def __init__( - self, - requirement: str, - is_editable: bool, - comes_from: str, - constraint: bool, - options: Optional[Dict[str, Any]] = None, - line_source: Optional[str] = None, - ) -> None: - self.requirement = requirement - self.is_editable = is_editable - self.comes_from = comes_from - self.options = options - self.constraint = constraint - self.line_source = line_source + # TODO: replace this with slots=True when dropping Python 3.9 support. + __slots__ = ( + "requirement", + "is_editable", + "comes_from", + "constraint", + "options", + "line_source", + ) + + requirement: str + is_editable: bool + comes_from: str + constraint: bool + options: Optional[Dict[str, Any]] + line_source: Optional[str] +@dataclass(frozen=True) class ParsedLine: - def __init__( - self, - filename: str, - lineno: int, - args: str, - opts: Values, - constraint: bool, - ) -> None: - self.filename = filename - self.lineno = lineno - self.opts = opts - self.constraint = constraint + __slots__ = ("filename", "lineno", "args", "opts", "constraint") - if args: - self.is_requirement = True - self.is_editable = False - self.requirement = args - elif opts.editables: - self.is_requirement = True - self.is_editable = True + filename: str + lineno: int + args: str + opts: Values + constraint: bool + + @property + def is_editable(self) -> bool: + return bool(self.opts.editables) + + @property + def requirement(self) -> Optional[str]: + if self.args: + return self.args + elif self.is_editable: # We don't support multiple -e on one line - self.requirement = opts.editables[0] - else: - self.is_requirement = False + return self.opts.editables[0] + return None def parse_requirements( filename: str, - session: PipSession, + session: "PipSession", finder: Optional["PackageFinder"] = None, options: Optional[optparse.Values] = None, constraint: bool = False, @@ -166,7 +189,6 @@ def handle_requirement_line( line: ParsedLine, options: Optional[optparse.Values] = None, ) -> ParsedRequirement: - # preserve for the nested code path line_comes_from = "{} {} (line {})".format( "-c" if line.constraint else "-r", @@ -174,37 +196,27 @@ def handle_requirement_line( line.lineno, ) - assert line.is_requirement + assert line.requirement is not None + # get the options that apply to requirements if line.is_editable: - # For editable requirements, we don't support per-requirement - # options, so just return the parsed requirement. - return ParsedRequirement( - requirement=line.requirement, - is_editable=line.is_editable, - comes_from=line_comes_from, - constraint=line.constraint, - ) + supported_dest = SUPPORTED_OPTIONS_EDITABLE_REQ_DEST else: - if options: - # Disable wheels if the user has specified build options - cmdoptions.check_install_build_global(options, line.opts) + supported_dest = SUPPORTED_OPTIONS_REQ_DEST + req_options = {} + for dest in supported_dest: + if dest in line.opts.__dict__ and line.opts.__dict__[dest]: + req_options[dest] = line.opts.__dict__[dest] - # get the options that apply to requirements - req_options = {} - for dest in SUPPORTED_OPTIONS_REQ_DEST: - if dest in line.opts.__dict__ and line.opts.__dict__[dest]: - req_options[dest] = line.opts.__dict__[dest] - - line_source = f"line {line.lineno} of {line.filename}" - return ParsedRequirement( - requirement=line.requirement, - is_editable=line.is_editable, - comes_from=line_comes_from, - constraint=line.constraint, - options=req_options, - line_source=line_source, - ) + line_source = f"line {line.lineno} of {line.filename}" + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + options=req_options, + line_source=line_source, + ) def handle_option_line( @@ -213,8 +225,14 @@ def handle_option_line( lineno: int, finder: Optional["PackageFinder"] = None, options: Optional[optparse.Values] = None, - session: Optional[PipSession] = None, + session: Optional["PipSession"] = None, ) -> None: + if opts.hashes: + logger.warning( + "%s line %s has --hash but no requirement, and will be ignored.", + filename, + lineno, + ) if options: # percolate options upward @@ -229,11 +247,13 @@ def handle_option_line( if finder: find_links = finder.find_links index_urls = finder.index_urls - if opts.index_url: - index_urls = [opts.index_url] + no_index = finder.search_scope.no_index if opts.no_index is True: + no_index = True index_urls = [] - if opts.extra_index_urls: + if opts.index_url and not no_index: + index_urls = [opts.index_url] + if opts.extra_index_urls and not no_index: index_urls.extend(opts.extra_index_urls) if opts.find_links: # FIXME: it would be nice to keep track of the source @@ -253,6 +273,7 @@ def handle_option_line( search_scope = SearchScope( find_links=find_links, index_urls=index_urls, + no_index=no_index, ) finder.search_scope = search_scope @@ -272,7 +293,7 @@ def handle_line( line: ParsedLine, options: Optional[optparse.Values] = None, finder: Optional["PackageFinder"] = None, - session: Optional[PipSession] = None, + session: Optional["PipSession"] = None, ) -> Optional[ParsedRequirement]: """Handle a single parsed requirements line; This can result in creating/yielding requirements, or updating the finder. @@ -297,7 +318,7 @@ def handle_line( affect the finder. """ - if line.is_requirement: + if line.requirement is not None: parsed_req = handle_requirement_line(line, options) return parsed_req else: @@ -315,7 +336,7 @@ def handle_line( class RequirementsFileParser: def __init__( self, - session: PipSession, + session: "PipSession", line_parser: LineParser, ) -> None: self._session = session @@ -325,13 +346,18 @@ class RequirementsFileParser: self, filename: str, constraint: bool ) -> Generator[ParsedLine, None, None]: """Parse a given file, yielding parsed lines.""" - yield from self._parse_and_recurse(filename, constraint) + yield from self._parse_and_recurse( + filename, constraint, [{os.path.abspath(filename): None}] + ) def _parse_and_recurse( - self, filename: str, constraint: bool + self, + filename: str, + constraint: bool, + parsed_files_stack: List[Dict[str, Optional[str]]], ) -> Generator[ParsedLine, None, None]: for line in self._parse_file(filename, constraint): - if not line.is_requirement and ( + if line.requirement is None and ( line.opts.requirements or line.opts.constraints ): # parse a nested requirements file @@ -349,12 +375,30 @@ class RequirementsFileParser: # original file and nested file are paths elif not SCHEME_RE.search(req_path): # do a join so relative paths work - req_path = os.path.join( - os.path.dirname(filename), - req_path, + # and then abspath so that we can identify recursive references + req_path = os.path.abspath( + os.path.join( + os.path.dirname(filename), + req_path, + ) ) - - yield from self._parse_and_recurse(req_path, nested_constraint) + parsed_files = parsed_files_stack[0] + if req_path in parsed_files: + initial_file = parsed_files[req_path] + tail = ( + f" and again in {initial_file}" + if initial_file is not None + else "" + ) + raise RequirementsFileParseError( + f"{req_path} recursively references itself in {filename}{tail}" + ) + # Keeping a track where was each file first included in + new_parsed_files = parsed_files.copy() + new_parsed_files[req_path] = filename + yield from self._parse_and_recurse( + req_path, nested_constraint, [new_parsed_files, *parsed_files_stack] + ) else: yield line @@ -394,7 +438,12 @@ def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser: args_str, options_str = break_args_options(line) - opts, _ = parser.parse_args(shlex.split(options_str), defaults) + try: + options = shlex.split(options_str) + except ValueError as e: + raise OptionParsingError(f"Could not split options: {options_str}") from e + + opts, _ = parser.parse_args(options, defaults) return args_str, opts @@ -515,7 +564,7 @@ def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines: yield line_number, line -def get_file_content(url: str, session: PipSession) -> Tuple[str, str]: +def get_file_content(url: str, session: "PipSession") -> Tuple[str, str]: """Gets the content of a file; it may be a filename, file: URL, or http: URL. Returns (location, content). Content is unicode. Respects # -*- coding: declarations on the retrieved files. @@ -523,10 +572,12 @@ def get_file_content(url: str, session: PipSession) -> Tuple[str, str]: :param url: File path or url. :param session: PipSession instance. """ - scheme = get_url_scheme(url) - + scheme = urllib.parse.urlsplit(url).scheme # Pip has special support for file:// URLs (LocalFSAdapter). if scheme in ["http", "https", "file"]: + # Delay importing heavy network modules until absolutely necessary. + from pip._internal.network.utils import raise_for_status + resp = session.get(url) raise_for_status(resp) return resp.url, resp.text @@ -534,7 +585,39 @@ def get_file_content(url: str, session: PipSession) -> Tuple[str, str]: # Assume this is a bare path. try: with open(url, "rb") as f: - content = auto_decode(f.read()) + raw_content = f.read() except OSError as exc: raise InstallationError(f"Could not open requirements file: {exc}") + + content = _decode_req_file(raw_content, url) + return url, content + + +def _decode_req_file(data: bytes, url: str) -> str: + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom) :].decode(encoding) + + for line in data.split(b"\n")[:2]: + if line[0:1] == b"#": + result = PEP263_ENCODING_RE.search(line) + if result is not None: + encoding = result.groups()[0].decode("ascii") + return data.decode(encoding) + + try: + return data.decode(DEFAULT_ENCODING) + except UnicodeDecodeError: + locale_encoding = locale.getpreferredencoding(False) or sys.getdefaultencoding() + logging.warning( + "unable to decode data from %s with default encoding %s, " + "falling back to encoding from locale: %s. " + "If this is intentional you should specify the encoding with a " + "PEP-263 style comment, e.g. '# -*- coding: %s -*-'", + url, + DEFAULT_ENCODING, + locale_encoding, + locale_encoding, + ) + return data.decode(locale_encoding) diff --git a/venv/Lib/site-packages/pip/_internal/req/req_install.py b/venv/Lib/site-packages/pip/_internal/req/req_install.py index a1e376c..3262d82 100644 --- a/venv/Lib/site-packages/pip/_internal/req/req_install.py +++ b/venv/Lib/site-packages/pip/_internal/req/req_install.py @@ -1,6 +1,3 @@ -# The following comment should be removed at some point in the future. -# mypy: strict-optional=False - import functools import logging import os @@ -8,6 +5,8 @@ import shutil import sys import uuid import zipfile +from optparse import Values +from pathlib import Path from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union from pip._vendor.packaging.markers import Marker @@ -16,10 +15,10 @@ from pip._vendor.packaging.specifiers import SpecifierSet from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version -from pip._vendor.pep517.wrappers import Pep517HookCaller +from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment -from pip._internal.exceptions import InstallationError, LegacyInstallFailure +from pip._internal.exceptions import InstallationError, PreviousBuildDirError from pip._internal.locations import get_scheme from pip._internal.metadata import ( BaseDistribution, @@ -38,27 +37,25 @@ from pip._internal.operations.build.metadata_legacy import ( from pip._internal.operations.install.editable_legacy import ( install_editable as install_editable_legacy, ) -from pip._internal.operations.install.legacy import install as install_legacy from pip._internal.operations.install.wheel import install_wheel from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path from pip._internal.req.req_uninstall import UninstallPathSet from pip._internal.utils.deprecation import deprecated -from pip._internal.utils.direct_url_helpers import ( - direct_url_for_editable, - direct_url_from_link, -) from pip._internal.utils.hashes import Hashes from pip._internal.utils.misc import ( - ConfiguredPep517HookCaller, + ConfiguredBuildBackendHookCaller, ask_path_exists, backup_dir, display_path, hide_url, + is_installable_dir, + redact_auth_from_requirement, redact_auth_from_url, ) -from pip._internal.utils.packaging import safe_extra +from pip._internal.utils.packaging import get_requirement from pip._internal.utils.subprocess import runner_with_spinner_message from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.unpacking import unpack_file from pip._internal.utils.virtualenv import running_under_virtualenv from pip._internal.vcs import vcs @@ -81,10 +78,10 @@ class InstallRequirement: markers: Optional[Marker] = None, use_pep517: Optional[bool] = None, isolated: bool = False, - install_options: Optional[List[str]] = None, + *, global_options: Optional[List[str]] = None, hash_options: Optional[Dict[str, List[str]]] = None, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, constraint: bool = False, extras: Collection[str] = (), user_supplied: bool = False, @@ -96,7 +93,6 @@ class InstallRequirement: self.constraint = constraint self.editable = editable self.permit_editable_wheels = permit_editable_wheels - self.legacy_install_reason: Optional[int] = None # source_dir is the local directory where the linked requirement is # located, or unpacked. In case unpacking is needed, creating and @@ -109,11 +105,17 @@ class InstallRequirement: if link.is_file: self.source_dir = os.path.normpath(os.path.abspath(link.file_path)) + # original_link is the direct URL that was provided by the user for the + # requirement, either directly or via a constraints file. if link is None and req and req.url: # PEP 508 URL requirement link = Link(req.url) self.link = self.original_link = link - self.original_link_is_in_wheel_cache = False + + # When this InstallRequirement is a wheel obtained from the cache of locally + # built wheels, this is the source link corresponding to the cache entry, which + # was used to download and build the cached wheel. + self.cached_wheel_source_link: Optional[Link] = None # Information about the location of the artifact that was downloaded . This # property is guaranteed to be set in resolver results. @@ -127,7 +129,7 @@ class InstallRequirement: if extras: self.extras = extras elif req: - self.extras = {safe_extra(extra) for extra in req.extras} + self.extras = req.extras else: self.extras = set() if markers is None and req: @@ -144,7 +146,6 @@ class InstallRequirement: # Set to True after successful installation self.install_succeeded: Optional[bool] = None # Supplied options - self.install_options = install_options if install_options else [] self.global_options = global_options if global_options else [] self.hash_options = hash_options if hash_options else {} self.config_settings = config_settings @@ -171,7 +172,7 @@ class InstallRequirement: self.requirements_to_check: List[str] = [] # The PEP 517 backend we should use to build the project - self.pep517_backend: Optional[Pep517HookCaller] = None + self.pep517_backend: Optional[BuildBackendHookCaller] = None # Are we using PEP 517 for this requirement? # After pyproject.toml has been loaded, the only valid values are True @@ -180,20 +181,37 @@ class InstallRequirement: # but after loading this flag should be treated as read only. self.use_pep517 = use_pep517 + # If config settings are provided, enforce PEP 517. + if self.config_settings: + if self.use_pep517 is False: + logger.warning( + "--no-use-pep517 ignored for %s " + "because --config-settings are specified.", + self, + ) + self.use_pep517 = True + # This requirement needs more preparation before it can be built self.needs_more_preparation = False + # This requirement needs to be unpacked before it can be installed. + self._archive_source: Optional[Path] = None + def __str__(self) -> str: if self.req: - s = str(self.req) + s = redact_auth_from_requirement(self.req) if self.link: - s += " from {}".format(redact_auth_from_url(self.link.url)) + s += f" from {redact_auth_from_url(self.link.url)}" elif self.link: s = redact_auth_from_url(self.link.url) else: s = "" if self.satisfied_by is not None: - s += " in {}".format(display_path(self.satisfied_by.location)) + if self.satisfied_by.location is not None: + location = display_path(self.satisfied_by.location) + else: + location = "" + s += f" in {location}" if self.comes_from: if isinstance(self.comes_from, str): comes_from: Optional[str] = self.comes_from @@ -204,8 +222,9 @@ class InstallRequirement: return s def __repr__(self) -> str: - return "<{} object: {} editable={!r}>".format( - self.__class__.__name__, str(self), self.editable + return ( + f"<{self.__class__.__name__} object: " + f"{str(self)} editable={self.editable!r}>" ) def format_debug(self) -> str: @@ -213,7 +232,7 @@ class InstallRequirement: attributes = vars(self) names = sorted(attributes) - state = ("{}={!r}".format(attr, attributes[attr]) for attr in sorted(names)) + state = (f"{attr}={attributes[attr]!r}" for attr in sorted(names)) return "<{name} object: {{{state}}}>".format( name=self.__class__.__name__, state=", ".join(state), @@ -226,7 +245,7 @@ class InstallRequirement: return None return self.req.name - @functools.lru_cache() # use cached_property in python 3.8+ + @functools.cached_property def supports_pyproject_editable(self) -> bool: if not self.use_pep517: return False @@ -240,15 +259,22 @@ class InstallRequirement: @property def specifier(self) -> SpecifierSet: + assert self.req is not None return self.req.specifier + @property + def is_direct(self) -> bool: + """Whether this requirement was specified as a direct URL.""" + return self.original_link is not None + @property def is_pinned(self) -> bool: """Return whether I am pinned to an exact version. For example, some-package==1.2 is pinned; some-package>1.2 is not. """ - specifiers = self.specifier + assert self.req is not None + specifiers = self.req.specifier return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="} def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> bool: @@ -289,8 +315,14 @@ class InstallRequirement: """ good_hashes = self.hash_options.copy() - link = self.link if trust_internet else self.original_link + if trust_internet: + link = self.link + elif self.is_direct and self.user_supplied: + link = self.original_link + else: + link = None if link and link.hash: + assert link.hash_name is not None good_hashes.setdefault(link.hash_name, []).append(link.hash) return Hashes(good_hashes) @@ -300,6 +332,7 @@ class InstallRequirement: return None s = str(self.req) if self.comes_from: + comes_from: Optional[str] if isinstance(self.comes_from, str): comes_from = self.comes_from else: @@ -331,7 +364,7 @@ class InstallRequirement: # When parallel builds are enabled, add a UUID to the build directory # name so multiple builds do not interfere with each other. - dir_name: str = canonicalize_name(self.name) + dir_name: str = canonicalize_name(self.req.name) if parallel_builds: dir_name = f"{dir_name}_{uuid.uuid4().hex}" @@ -363,7 +396,7 @@ class InstallRequirement: else: op = "===" - self.req = Requirement( + self.req = get_requirement( "".join( [ self.metadata["Name"], @@ -374,6 +407,7 @@ class InstallRequirement: ) def warn_on_mismatching_name(self) -> None: + assert self.req is not None metadata_name = canonicalize_name(self.metadata["Name"]) if canonicalize_name(self.req.name) == metadata_name: # Everything is fine. @@ -388,7 +422,7 @@ class InstallRequirement: metadata_name, self.name, ) - self.req = Requirement(metadata_name) + self.req = get_requirement(metadata_name) def check_if_exists(self, use_user_site: bool) -> None: """Find an installed distribution that satisfies or conflicts @@ -434,9 +468,16 @@ class InstallRequirement: return False return self.link.is_wheel + @property + def is_wheel_from_cache(self) -> bool: + # When True, it means that this InstallRequirement is a local wheel file in the + # cache of locally built wheels. + return self.cached_wheel_source_link is not None + # Things valid for sdists @property def unpacked_source_directory(self) -> str: + assert self.source_dir, f"No source dir for {self}" return os.path.join( self.source_dir, self.link and self.link.subdirectory_fragment or "" ) @@ -473,6 +514,7 @@ class InstallRequirement: ) if pyproject_toml_data is None: + assert not self.config_settings self.use_pep517 = False return @@ -480,7 +522,7 @@ class InstallRequirement: requires, backend, check, backend_path = pyproject_toml_data self.requirements_to_check = check self.pyproject_requires = requires - self.pep517_backend = ConfiguredPep517HookCaller( + self.pep517_backend = ConfiguredBuildBackendHookCaller( self, self.unpacked_source_directory, backend, @@ -496,7 +538,7 @@ class InstallRequirement: if ( self.editable and self.use_pep517 - and not self.supports_pyproject_editable() + and not self.supports_pyproject_editable and not os.path.isfile(self.setup_py_path) and not os.path.isfile(self.setup_cfg_path) ): @@ -514,7 +556,7 @@ class InstallRequirement: Under PEP 517 and PEP 660, call the backend hook to prepare the metadata. Under legacy processing, call setup.py egg-info. """ - assert self.source_dir + assert self.source_dir, f"No source dir for {self}" details = self.name or f"from {self.link}" if self.use_pep517: @@ -522,7 +564,7 @@ class InstallRequirement: if ( self.editable and self.permit_editable_wheels - and self.supports_pyproject_editable() + and self.supports_pyproject_editable ): self.metadata_directory = generate_editable_metadata( build_env=self.build_env, @@ -563,8 +605,10 @@ class InstallRequirement: if self.metadata_directory: return get_directory_distribution(self.metadata_directory) elif self.local_file_path and self.is_wheel: + assert self.req is not None return get_wheel_distribution( - FilesystemWheel(self.local_file_path), canonicalize_name(self.name) + FilesystemWheel(self.local_file_path), + canonicalize_name(self.req.name), ) raise AssertionError( f"InstallRequirement {self} has no metadata directory and no wheel: " @@ -572,9 +616,9 @@ class InstallRequirement: ) def assert_source_matches_version(self) -> None: - assert self.source_dir + assert self.source_dir, f"No source dir for {self}" version = self.metadata["version"] - if self.req.specifier and version not in self.req.specifier: + if self.req and self.req.specifier and version not in self.req.specifier: logger.warning( "Requested %s, but installing version %s", self, @@ -611,6 +655,27 @@ class InstallRequirement: parallel_builds=parallel_builds, ) + def needs_unpacked_archive(self, archive_source: Path) -> None: + assert self._archive_source is None + self._archive_source = archive_source + + def ensure_pristine_source_checkout(self) -> None: + """Ensure the source directory has not yet been built in.""" + assert self.source_dir is not None + if self._archive_source is not None: + unpack_file(str(self._archive_source), self.source_dir) + elif is_installable_dir(self.source_dir): + # If a checkout exists, it's unwise to keep going. + # version inconsistencies are logged later, but do not fail + # the installation. + raise PreviousBuildDirError( + f"pip can't proceed with requirements '{self}' due to a " + f"pre-existing build directory ({self.source_dir}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again." + ) + # For editable installations def update_editable(self) -> None: if not self.link: @@ -667,9 +732,10 @@ class InstallRequirement: name = name.replace(os.path.sep, "/") return name + assert self.req is not None path = os.path.join(parentdir, path) name = _clean_zip_name(path, rootdir) - return self.name + "/" + name + return self.req.name + "/" + name def archive(self, build_dir: Optional[str]) -> None: """Saves archive to provided build_dir. @@ -686,8 +752,8 @@ class InstallRequirement: if os.path.exists(archive_path): response = ask_path_exists( - "The file {} exists. (i)gnore, (w)ipe, " - "(b)ackup, (a)bort ".format(display_path(archive_path)), + f"The file {display_path(archive_path)} exists. (i)gnore, (w)ipe, " + "(b)ackup, (a)bort ", ("i", "w", "b", "a"), ) if response == "i": @@ -740,7 +806,6 @@ class InstallRequirement: def install( self, - install_options: List[str], global_options: Optional[Sequence[str]] = None, root: Optional[str] = None, home: Optional[str] = None, @@ -749,8 +814,9 @@ class InstallRequirement: use_user_site: bool = False, pycompile: bool = True, ) -> None: + assert self.req is not None scheme = get_scheme( - self.name, + self.req.name, user=use_user_site, home=home, root=root, @@ -758,100 +824,60 @@ class InstallRequirement: prefix=prefix, ) - global_options = global_options if global_options is not None else [] if self.editable and not self.is_wheel: - install_editable_legacy( - install_options, - global_options, - prefix=prefix, - home=home, - use_user_site=use_user_site, - name=self.name, - setup_py_path=self.setup_py_path, - isolated=self.isolated, - build_env=self.build_env, - unpacked_source_directory=self.unpacked_source_directory, - ) - self.install_succeeded = True - return - - if self.is_wheel: - assert self.local_file_path - direct_url = None - # TODO this can be refactored to direct_url = self.download_info - if self.editable: - direct_url = direct_url_for_editable(self.unpacked_source_directory) - elif self.original_link: - direct_url = direct_url_from_link( - self.original_link, - self.source_dir, - self.original_link_is_in_wheel_cache, - ) - install_wheel( - self.name, - self.local_file_path, - scheme=scheme, - req_description=str(self.req), - pycompile=pycompile, - warn_script_location=warn_script_location, - direct_url=direct_url, - requested=self.user_supplied, - ) - self.install_succeeded = True - return - - # TODO: Why don't we do this for editable installs? - - # Extend the list of global and install options passed on to - # the setup.py call with the ones from the requirements file. - # Options specified in requirements file override those - # specified on the command line, since the last option given - # to setup.py is the one that is used. - global_options = list(global_options) + self.global_options - install_options = list(install_options) + self.install_options - - try: - success = install_legacy( - install_options=install_options, - global_options=global_options, - root=root, - home=home, - prefix=prefix, - use_user_site=use_user_site, - pycompile=pycompile, - scheme=scheme, - setup_py_path=self.setup_py_path, - isolated=self.isolated, - req_name=self.name, - build_env=self.build_env, - unpacked_source_directory=self.unpacked_source_directory, - req_description=str(self.req), - ) - except LegacyInstallFailure as exc: - self.install_succeeded = False - raise exc - except Exception: - self.install_succeeded = True - raise - - self.install_succeeded = success - - if success and self.legacy_install_reason == 8368: deprecated( reason=( - "{} was installed using the legacy 'setup.py install' " - "method, because a wheel could not be built for it.".format( - self.name - ) + f"Legacy editable install of {self} (setup.py develop) " + "is deprecated." ), - replacement="to fix the wheel build issue reported above", - gone_in=None, - issue=8368, + replacement=( + "to add a pyproject.toml or enable --use-pep517, " + "and use setuptools >= 64. " + "If the resulting installation is not behaving as expected, " + "try using --config-settings editable_mode=compat. " + "Please consult the setuptools documentation for more information" + ), + gone_in="25.1", + issue=11457, ) + if self.config_settings: + logger.warning( + "--config-settings ignored for legacy editable install of %s. " + "Consider upgrading to a version of setuptools " + "that supports PEP 660 (>= 64).", + self, + ) + install_editable_legacy( + global_options=global_options if global_options is not None else [], + prefix=prefix, + home=home, + use_user_site=use_user_site, + name=self.req.name, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + ) + self.install_succeeded = True + return + + assert self.is_wheel + assert self.local_file_path + + install_wheel( + self.req.name, + self.local_file_path, + scheme=scheme, + req_description=str(self.req), + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=self.download_info if self.is_direct else None, + requested=self.user_supplied, + ) + self.install_succeeded = True def check_invalid_constraint_type(req: InstallRequirement) -> str: - # Check for unsupported forms problem = "" if not req.name: @@ -877,3 +903,32 @@ def check_invalid_constraint_type(req: InstallRequirement) -> str: ) return problem + + +def _has_option(options: Values, reqs: List[InstallRequirement], option: str) -> bool: + if getattr(options, option, None): + return True + for req in reqs: + if getattr(req, option, None): + return True + return False + + +def check_legacy_setup_py_options( + options: Values, + reqs: List[InstallRequirement], +) -> None: + has_build_options = _has_option(options, reqs, "build_options") + has_global_options = _has_option(options, reqs, "global_options") + if has_build_options or has_global_options: + deprecated( + reason="--build-option and --global-option are deprecated.", + issue=11859, + replacement="to use --config-settings", + gone_in=None, + ) + logger.warning( + "Implying --no-binary=:all: due to the presence of " + "--build-option / --global-option. " + ) + options.format_control.disallow_binaries() diff --git a/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py b/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py index 15b6738..26df208 100644 --- a/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py +++ b/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -5,14 +5,15 @@ import sysconfig from importlib.util import cache_from_source from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Set, Tuple -from pip._internal.exceptions import UninstallationError +from pip._internal.exceptions import LegacyDistutilsInstall, UninstallMissingRecord from pip._internal.locations import get_bin_prefix, get_bin_user from pip._internal.metadata import BaseDistribution from pip._internal.utils.compat import WINDOWS from pip._internal.utils.egg_link import egg_link_path_from_location from pip._internal.utils.logging import getLogger, indent_log -from pip._internal.utils.misc import ask, is_local, normalize_path, renames, rmtree +from pip._internal.utils.misc import ask, normalize_path, renames, rmtree from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory +from pip._internal.utils.virtualenv import running_under_virtualenv logger = getLogger(__name__) @@ -60,7 +61,7 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: UninstallPathSet.add() takes care of the __pycache__ .py[co]. - If RECORD is not found, raises UninstallationError, + If RECORD is not found, raises an error, with possible information from the INSTALLER file. https://packaging.python.org/specifications/recording-installed-packages/ @@ -70,17 +71,7 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: entries = dist.iter_declared_entries() if entries is None: - msg = "Cannot uninstall {dist}, RECORD file not found.".format(dist=dist) - installer = dist.installer - if not installer or installer == "pip": - dep = "{}=={}".format(dist.raw_name, dist.version) - msg += ( - " You might be able to recover from this via: " - "'pip install --force-reinstall --no-deps {}'.".format(dep) - ) - else: - msg += " Hint: The package was installed by {}.".format(installer) - raise UninstallationError(msg) + raise UninstallMissingRecord(distribution=dist) for entry in entries: path = os.path.join(location, entry) @@ -171,8 +162,7 @@ def compress_for_output_listing(paths: Iterable[str]) -> Tuple[Set[str], Set[str folders.add(os.path.dirname(path)) files.add(path) - # probably this one https://github.com/python/mypy/issues/390 - _normcased_files = set(map(os.path.normcase, files)) # type: ignore + _normcased_files = set(map(os.path.normcase, files)) folders = compact(folders) @@ -273,7 +263,7 @@ class StashedUninstallPathSet: def commit(self) -> None: """Commits the uninstall by removing stashed files.""" - for _, save_dir in self._save_dirs.items(): + for save_dir in self._save_dirs.values(): save_dir.cleanup() self._moves = [] self._save_dirs = {} @@ -312,6 +302,10 @@ class UninstallPathSet: self._pth: Dict[str, UninstallPthEntries] = {} self._dist = dist self._moved_paths = StashedUninstallPathSet() + # Create local cache of normalize_path results. Creating an UninstallPathSet + # can result in hundreds/thousands of redundant calls to normalize_path with + # the same args, which hurts performance. + self._normalize_path_cached = functools.lru_cache(normalize_path) def _permitted(self, path: str) -> bool: """ @@ -319,14 +313,17 @@ class UninstallPathSet: remove/modify, False otherwise. """ - return is_local(path) + # aka is_local, but caching normalized sys.prefix + if not running_under_virtualenv(): + return True + return path.startswith(self._normalize_path_cached(sys.prefix)) def add(self, path: str) -> None: head, tail = os.path.split(path) # we normalize the head to resolve parent directory symlinks, but not # the tail, since we only want to uninstall symlinks, not their targets - path = os.path.join(normalize_path(head), os.path.normcase(tail)) + path = os.path.join(self._normalize_path_cached(head), os.path.normcase(tail)) if not os.path.exists(path): return @@ -341,7 +338,7 @@ class UninstallPathSet: self.add(cache_from_source(path)) def add_pth(self, pth_file: str, entry: str) -> None: - pth_file = normalize_path(pth_file) + pth_file = self._normalize_path_cached(pth_file) if self._permitted(pth_file): if pth_file not in self._pth: self._pth[pth_file] = UninstallPthEntries(pth_file) @@ -360,7 +357,7 @@ class UninstallPathSet: ) return - dist_name_version = f"{self._dist.raw_name}-{self._dist.version}" + dist_name_version = f"{self._dist.raw_name}-{self._dist.raw_version}" logger.info("Uninstalling %s:", dist_name_version) with indent_log(): @@ -502,13 +499,7 @@ class UninstallPathSet: paths_to_remove.add(f"{path}.pyo") elif dist.installed_by_distutils: - raise UninstallationError( - "Cannot uninstall {!r}. It is a distutils installed project " - "and thus we cannot accurately determine which files belong " - "to it which would lead to only a partial uninstall.".format( - dist.raw_name, - ) - ) + raise LegacyDistutilsInstall(distribution=dist) elif dist.installed_as_egg: # package installed by easy_install @@ -531,12 +522,14 @@ class UninstallPathSet: # above, so this only covers the setuptools-style editable. with open(develop_egg_link) as fh: link_pointer = os.path.normcase(fh.readline().strip()) - normalized_link_pointer = normalize_path(link_pointer) + normalized_link_pointer = paths_to_remove._normalize_path_cached( + link_pointer + ) assert os.path.samefile( normalized_link_pointer, normalized_dist_location ), ( - f"Egg-link {link_pointer} does not match installed location of " - f"{dist.raw_name} (at {dist_location})" + f"Egg-link {develop_egg_link} (to {link_pointer}) does not match " + f"installed location of {dist.raw_name} (at {dist_location})" ) paths_to_remove.add(develop_egg_link) easy_install_pth = os.path.join( diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc index 2c5719abc87016fa32ceb7fe2c915f24aeb1c399..bdc48b9a2711e07ee88ea1c8294c5f5602d20c12 100644 GIT binary patch delta 18 YcmZ3_xSo+KpO=@50SLZ5p2)Qn04ekZ7XSbN delta 18 YcmZ3_xSo+KpO=@50SH9JCvq(X03u%lY5)KL diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-310.pyc index 1e10e7c1f6c8db0fd1abd66b5277f4b3705e7e4e..97449d5ffeeb1c516c7e5c708d30939a201e7850 100644 GIT binary patch delta 19 ZcmZqXXy)L`=jG*M0D^CiH*)=C1^_Db1w;S< delta 19 YcmZqXXy)L`=jG*M00L3*ja)yO0U@#jmjD0& diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc index c40e61a39d4fe57a45211fcdafdeaa846594ac1f..df5eb6c2a02122f139d78297dff72fde50d6694c 100644 GIT binary patch delta 18 YcmdnSxQ&r3pO=@50SLZ5p2)QZ04nJPEC2ui delta 18 YcmdnSxQ&r3pO=@50SH9JCvvR;03%cbe*gdg diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc index 19eadb6298aea5739ad714d7cdf5c194f3b4154b..8c9216156a27917a02e6df606635631386647034 100644 GIT binary patch delta 2788 zcmZuzYit}>6`p%{c4ps>cWuXB+v&!S)Y~}D%XShcw!uyu8rM-8yM)AP#^aswW*?qi z?#u>z87EQwCrE%qF5*XwD;rTnRF$e-Bve}Q5E7LTLIPC?R!9Yk)IT5uNc=!?!Z~-7 z;#k<4Z_b=^?>+Bx_czWrO5s8{9FXAe-yeODmcJHmC$GM>e};I2=5UKtxlMGL{EGkC z`%c`Ivi>z{sIIyu89vvuM%R^9@(M}%D{m;1bij8(Pv!KqnJDi`F!S@J3^VP7o-i^C z3nnuyCvjofxn8h_5@lb)DmaOZl}JYTQNPQ7;6Fi*@qhTgs2l@3?9Xr(7>xu7CGsPD zUy`=sjE zv{YWVZB1in5Ic@=4#24_)%~85m-xk~yZ1%p&LF%5P_29H^CGya*`~v0`QM`*?E|<# zobt(0RTUyr$loyU@xIt7d6`?WDe`mvUTik%db2)=u4kQMWL=t#@MJ^lvvn@rBt&v) znizC}PD^E#ErpNMkuF=mtQVMO3p5*+!(Z zjXBSX&-JmdI$^`>QqZc1%&K@Q*L?Dq00R z@2$ey!1Na0!jJ53q_ewoG$gI~T|fH~DDw*ik`Y+%+!r#thutV*k1<-G|5=l z_`l`zMwAfokzK$EV4*AYk%C1}<%fzA03M|QsyyO9YwhatiGGlY0{tMXAfzGLM-6OY47w)RDZm+a5-{nhwM!0YhThz#On5MhjHfNG#&~^uj2z+r zY+}NR9H>J30;t-)`dfHjVIEZPaRK+PO?o%UHIf=kum9!M8dr zGQ;zoeW!X{IqNOP4YJ||=RDYtu6IpZmsb==*-%|Y^r8#}C!a5ePFV%ZOr$e6Olzck znt#xFy1N_?Tr_pNU?mm`EHQ6ptaM^ow{oU2lt}t&_KxyYSI?~jXkZ^eQr(t~TWDuw z-n1PprCUbE&>fSZZ&d}#7|yMF7VY#-$C|W-jAdxs$51|Fq>&0xtqd4j+gySoo73xx~2zJ%+ZTJlt zx>VYv(2ccqff7tv-~|B%M+?DMSnQap{IdHVJz75e|LskbEOV)7rl9xo%W#o6C1#mM z;ygr|FZ7J@`#l}OJK#?33K-$P?U{~WX-?^oRYUv2b<@micA>;lriR}0bIE5ee^Tew zpjfBDh-S+>;}_A2g<>fWu@*b;V%(m?xP?O`N@aMUH)|2Z&LvUetNbK+gOFi<3@*$O z{^k9Xg!A9+Pc({~=r$UOb^rLD;^E#7rDh5r=>gMB3weafN&MzGC)#c-$WWWT&c55^H2H(i;T^2 zez3n?3_#(P@CUETs;V2J4rTtAgU^#W-gjtP6H4P^@>G3AW)^h@!*vahKY=iXATIA9 zQeFgM++L*6!fM@h-QHf_Ow2N2_c;IKp|OL5xT-z_&7v7*(X96&cFjb6% zE@rm5JWNHo^9=2dZJGEFaN_lexvLo5(wJiBUJT%nT+(4-!Z=u@IV?!ty(lGd6 DNv*7F delta 2532 zcmZ8jZ%kX)75BaG`T5z{m>6up#>8Ntc;Qc)1PCOAgwUidNs|Ff(k095gZD80gYDe+ z$dd3pqNE>Mb@{MerK&nLHIt^TS}QH`I<1r1X4MC^~CJop* zmn5Y@;`h!y=iGbFJ^!v>U-_LKC-ATi7u1h@PD{J z2vzDGSJvxz9BEy;O>U8tr}}|1O#=td>I*qNZ6;PbSeXaC?G3BtM4@OWG6lg(1^KAg zQESR#kuB>sf8RSw4)RaEtI8Nyw5E8;H{p|sO6Zon#m1^1`ZlE01c=yCgkuON5l$dX zAv}Z7gK(Vxy?%=K1>1+d;0Zmk<5^I7ht#~9wvg8?OVijv+%$?X4REb`Blssu&hfdB z(=mhGuOXZRs0EpMWhKMRWwT&wmT9v~{IgJJd>9qPDUXk;d6;Px^H8$I9>X6DVkW1^N>^bi$ z)X6S8#Fv{o)*Ah;qT_h7O(1Q`Q9*|RX%^9w4QC@rXCpbOtU4-t)eabLuu36Qc%I0W zIh!G+N(-QyQ(e(=Nw@z5vf%d=Gf;;=2xA%eu2IxX8BTsNYrgI$rj3 zFrlCcbQdpXcpQ(`2=%d zubyY7Zd@0YSMEy`^ks7#t1@+CiQjBZQaI%YtuK){SE92Kk!7#7QYsahZ5nJBW_CZ% zMo-qC#{y8yYc|s@$ot39lVMREmr>;<1RY_X$6_zGez_Rf1(5s-{;k*fomea(6Im3t ztkNxo$Xk@kn~LHiK0>KaQa1UoV_lt(s$W(?K>e~x6xsyJvP20bDwQ|5zwHpY#Gh@u zIC=yQKf%TU=h$Jul(gL*IiMMO{tjir+e^sU;T`{TTMHTG|7kmwXa^B=vx|8gk|kNn zdpa#x%6~>-<5yyKd*P|BgrNCJEeF0o{6~ z+T30*lf%5H^YR!rWi7a{WG>{i%%Wyq%UHH0&SW=0wB6EWq^=`~rcEPtlz-IO85P&~ z7Or>LgJmtu&m_a-6mLit$P8ag4#b~w}UX(VkVP7^_$)r)bUlSX5KCxhe0qUq|^&S8wxvbfh0)03hXg z7-jzLu6T^SjBZKGR{BX-BRtq0iQmHbw1AF})I&wcM3EG%0XKaA``zvd@*{qlFHgWbxm(0y7MFb!^m-Az^-?1493J_4nOxQeNqu zBy;?4y`6QhqPt>*PViuAwxhPY$TI0nLCu`o8KhGPCc*`TuOfT{;p+e?h22AXo_{^V5MPWLLQr?i2E~+;8CGOrg6!=_D(hc8VK^uN^4u7J?tba(nm+=YEV! z5!?trI}{<~;QKJN(bCWe42H_kzTMNPfisD}WyZ jhq%9bc)4h-ZWgtmr?!h#f3#^Sj2oWjzb-Fjwf z3e>bon;1<37L(s=2ypb3m3{S?y#Q0=m(33$a*Hp(bmc(P@HOtD2o-geGa~I+;*tnr2oNnpsg-h@A(! zg=WFduBdi_wla(6r~$P_sLj&?)NX;CA~hh#fSfkEWl|}%{f-EfNMO*4AFWK+DxO!; zL@(LV15R^tj!jo*s*F!EA8f1K;BKW>y~=30;<6GEpOS?o4Q3dJ;q3siNIY#(nFJ6& zSA4QaR>&9R19egP44_<8L56N=u&!2KC%e|k+w0_fNe#5ijcPs6y$1IgEroazCgLd& zcAPEvyy7`*VUDjUJP*G0bK?i5=6K^WoA$ja&lh*p<6=2fT(U@t@FHZKfvxH@ym6J) zr@`Ft3xjn8hPMoYDK?>st)5i?YK@W+?1DyB_}5tkdZN(~=uw)bVXCic0JH&C1e&8! zWk#b>fD^rOsz-e!Pcv>}8gRfr z=FZia%j(drO_OuvKoFj#~#P@abbamTIr)0doDwLS~HQTObV3$78qALmDUaCsPG-p zsR0RxYVLjX7=N8)MIjAcQb9x`S5v3id-GK;+qnmWO(>htKS;C{4?H^yKM1~4Vy`vYG6ve3TINr! zDpssMGAZs@M^hN(uc2seNT|sk{SCBFh+WCv@(8MjP#gvkMB!S`G45aCQS==}U&!-0 ze+5km9IhNB$AKtSc(K^=Mq_q+NqX@8z@rzBy$UvvChj%n z`81Op;&JJFn1%Tp;o^hfvtf8T2pxK&5k3fg2y_dx@#1!nvAa&%BHho!T%MzX=@a5c zW*FM^ZRY2`Npw871P?rm8OOx;ExQLEq5S_vFF}DXda^GxaX<591u>iL(ihM^D{f|o zpN;>N?bH{W@dw$V-Lh{_)njB6GN-|}+^m>t9nWv9fa@Y}*jwVu)?R%T(@uzATMsClJHG5 z@rxjDEyp8q4TYr6In?C6MFu>i7q*{8$|DE41?0|) hKMTq2_>`GSftc_*m?R}-R^1YcMpDG;&27!-{{dgx)&Kwi delta 2509 zcmZuy&5zqe6!+MUV<&OqIN4;kEbVR=XtV96Ezl34vTfB;D3mR9X#qoJrI|@ zLc46)!d6HiK7>Yy3rO_XGvbC268`}L4wm4+4T+Bff&)mvdy_W(!mIi1yf?p@dGp?H zCSPp%_}+4C+XV%_vF10YX#M^2GQ_gBg>+X;2e5CUEYg%|)d({uAb)mCLMy;yyC-c$PcX58{4{ zWTnLc>ju4m@kN%l)U3P^^QaRBON=gbB9>LVoqpU8y3*zM!38AyFgw-hoP*%w*xu8<*6SAyO{S$Rry-Y5v5L<4cOJL5m zPlb*KEx|Sp@S3u$oXB4wDJ-)}jw?htqf%J>3R!3oZUF-#GSv3gj4N&<|4I$DAc79z!!ofh^Vb$NdDd z8T8ZkHIDd9+gclLpz|r<@;pLC{HbjsYsGr~o#}hfA%{i*KrkE7+d`PZU5i$a$B`d! zc4oc!RrlA)m?6ZIaU9+lBFwl#_+2!UuW+^ zHcrVZLE0j8 z9;u1nDwCgnXKg2Bi!95!qD}UQx#B!IAj0C0#fM-ueh@*9w{(1}4uSnU25jb+oTKc_ zStvagsf~lftU2O?(iZZdn6B1x^T0eRzAx>o9e~~yb%Ec!>PB)*c=kaDNBQFj*EbYj z*;V5i^c@kIefPp1?CwR_2auTq9uF8#&vW@aJc2$Abj}||icA#lo>lfk`2*TX+2J^T z@$7&v;P?}mxfb3)Bqa_2X3in1!u4pXFU9Rl{xR zyT*bekL?7{^U#J@kd%l{_)bx&WCm`+G3|Gf1E1PXnHX0O3)95F)r~F^4vG2db|^tw z{h@da9oI<(JX(al$HbC5H_GWPwA^l>yd=JMcMkJ<{DxKV{%x+=#uECT7JF*j|Ci$y zLA{IyY3F3fULA6;)b78X3!xXDg7MdfoI-tnQ`T~{CkS3%5l?FD<+^LUfz%`7z4`;U zFNfj%Tpu^y9C8X{dxxAGrGZ;M0po8EIWLdRtlTUO{v?i!RKbs;iK)w+kruB0&~i-G zP%Khu&!VX#$oq&V;~Ik0!gJV@mk|rhF$noah(Amxht)kPrW>>6wV9Eg9|ZkV@@9)( zh1HxPWii*BYRgAr5vQI& ykjKH_zv1gFBa?DR<#7ju-4yRMD^rtTPAVnU0aZI{36xj|T%(oq<&BNCuJIq{s1GFo diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc index c2dc27cdb41507f4540b0895c5ea37a99bdd16d3..eb18e37042343221973c335d9431ecd66658131a 100644 GIT binary patch literal 19448 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 literal 18570 zcmbV!S&SSISTkSA8*Fbi#+!vo zp*c~Rkh0wN1Vl=3He?^4Z3GbD^@(++W!*=2#V&i1?qOn)1!Hp|QwN-TJYAXn z2=vR@U-HAMR}HIITeWs8s0X3n3Nh5w3)R4X5k*yBT4zVVV832(-HfIhNCVgZaJ_!3 z+R&}j@80nJ2AUkG>$zOzf9Ni&cGLB}dMGQL+w}?q5$c&3zPC7}@|$|dSr7SI=&q}V z9*EPT^?WPY2=|s=ty^y`w||VYlPcNK*yU==t7AcaG}X<<+Y*iUO%aVRbD*%hcP~|I zVOwor?+!fQP=3|hh~e_R?m*G>m3TS5stN8&x7a!I?3)|mjdsi7>YaGP;89)qTr^he z!k1BgxUO0?LZ1AY$XIwT;|UHU2~(jFn#%vrCEZOQ922&1`<4B@>JrI1fYJSO7Cs;MVgidZ3KDXAW27w>k zPpQ**{h53D!uuedRUjpJ9|Q%eb*pRj_iy>FTkpSKUwS{NhyJ5$)!NPKiXXhcR$n_0 z%z(Z@)aR8Sv>QT4I(y4+)R)e8=L*Ve8_{$%a0fvsVcwvK#I#JqH0&?(Y1^<3b(Y}T zB#0;%`pq?vwqN7cC4V+D1w68i4P-Wr)s)Jv@AS$jj+Dp}jo0Ky*aBi{b*=S-t@Rb{^udOxez8B?d?WP~dQHb(* z<*xZ_Uwi!NC|AeMV*Szrhfh_p=}|TrZxW|^xxV5Cei+tUD?w>G$|dkb7EWnop-*Jt zn5j8zlzNQG<4m4l@+6a|kVLjuuZ8Ly%a5{LAfyT0>g%kUXsh~49r$*M8%6Yi^7x}3 z=6j;dk8B+54~3?5a)z%CHmf&%(2H=Y9{1olU&H%={fkz{C>R-2XaRJf{{vm<|Gu!( zng5k5W>8X>(0qU*NF5V+gd$!+26#&aU5W?|PylgHeA;*hXdoOzO_v5@{7(S?V;b9Y zU2M17VHe%%5lmCcjo#7uHD5LBVV6a^x5-5V#RbcTmWt|W=4Y8)U@{6j>UqBXMJ8Pg zsb^UvVsOH{NZ7gYM~82GLL+aYd*C1`;s_>NK4jxRRWG0si6jUIHh$nJehY1|l_@ob z4act>z6In=wZJ3zeH>7hR_*Vnet-kn8jEX9{HAqXn2|%;J)CGSs0rn8qEy5)3FHu! zQ=Tn{l!tR#4rh9?V>y?cj(PE-AV{4DOr;t141UxvFyU53MersqUqwL3?nl{}!#?<= zj6_3J2q1%lWgKUBX#*#N#3(02J;&VNU_xHocPXw4e1dc(Q)Z z%Xwp7-XHVx2U6ZRe#h}!@a*Lxb-+*3m4a9BCzefb(wlZP-LCrpBd-L7`YG$Fo6)b4tqyFu~D;MYQ|A> z)H^0M2jZC>?>I(2h?0%BC%lJHI^>zYEl}IuN$(VD4#)3LduLEO0$pz(YK{VyV+T^A zk5cEeD-LSM{G7n|h<6S($2}V?p&XrXW96Yw<9Gq0u}_z%{vYt9=bf$$be813v$Ww< zTh8_Cy9c;_y`0ZG_`7xkQbqY|kg8CY0;lT4Vi%PkuKPjg+^&Z=oDjM}SXC>2=#Vch z`49k3RqHk~PQ4{%lEy&3ESx6Ec;>YhVMyz%$|L(3=n()7(>cX z!{Md$1CVRfETJzrP`R9D8}LCzA#@FY#kt*9H-8bOdLRRd*5UXct+k5Hg3ofg0l_U4{d?dqLdi;cc%4y5f&9=Im35=fa(f-sLh zvFkvfz$%S|K7a#RA4k%2L4R)pR|3FUzr0e`Ag*n!)yr+QQqnUE=X+^Uv)b{#Z4n+A zWtX)su8x8!MK-M)bp=`V5RzIJN%F@$j*%AYR9H44$lVkqM9MWbZKUQVlsnhjOe3{7 zGf0uUm)TAsm-V1Y-#2Ker3EWd!R-Sk%DFKhcul1RKZFJKu^>PWhY(cf%Zf_b$PWC* zvX-`20gmSBu=-Q#H72r(9V|ZQLhpeZ;Qnp25Op^*mH|K4{}qkSBVWx-%E=f5)&wmJ z3(sW^Jc9&MG$k@NwQ5kB(uP?4%y90TJ@D=u>KdBv6hv9q1y#H5?{X||`Hazdcu#;y zw_R{iFA%u)BjZ6A0Bn%_v~pI#!=YrEfX-U%%-<1~AUnTx_6{lQxY{bg*v$7{$c~rN zQAV?fXw22-i|YbK($#gfbpItxr+$UWZZwdky6zv~WspN+0|hxF^Rqo7K=ZnrlC0j3kgaY)F|sNkU^94zPb1k6ql1|sG%iQ3CJKJA)6X2c5H3Ng}cCY z{|K*w43dITgf7`B?TLKYbJwPlvPnIkayS5qbF8=0P>ZM;hG50>_|MpfYtERR@*bw| z;|9B6;4p+CIEaKWc*c54<+*t&ivEPECh)g6Afw4&~f}^JkC?5=- zEOxPEsb9wUT339Lxnaaxh=&nU{}%*`8r$VwL$J zum~slW4^qBq;qBulXE|IO}cw~Q^U45K0)d&&Pa4<9y<&$GT$HK(R*Xc-t2{i#ms&e zglUW=1VD24jC z%GP1+L*_Bhibe`M;CU%asYt3D( zkU@r6HT@}E)$AMCCRO*Sr#Zp;lJI8u>-H_S!>e%7h+oh5#OpY89dn5&b^GKEmLCM@iI;l*+sNSsQNGss1UTTjsaS+Xmj-8>jK!!h0YGc79skTHms68@GYndqBswVE~Ex z_|3iT`%ZPKeM_4o?e%bNJuG8i*D$%Fk4SInGtBWAMOkc7=zkQd4^e{j>+Wr2_>tv* zRMXqr-DCAO+WmJtA{k8htcpg?HjUiJMe$zcJ~qXZxi`HcRxqOp+H~}c(McW*kTmy@ z%&5jWsce25t5rGdR_dOyooay$x3F(7raqW}!xDRV&w{Jdx=VsiZ=2sp8L1E9RYpBY zIJKJHHdrUxvAHO#gCC0+il*V@Rj%i+`7O_H)#`qr-eA4<-^I|;lGIN7V9l>-y^CZT zIpWMn*5Iy*r#x8`dqtBwUMAbU&hEM7Wn`$Gdwv@Y{x_b0#AJRv16th=mq_QSJ<#f| zH4RWGrQdD|STZ!33=uTZ0!;3HUuJTx@j2lmGlNjRum`wC3v2;RxfPtdC>o(io zIs}9Z#jMpRW6Ef(#icDtdLnazQf!KoQ;h_aT=;Hk+3@n-_$L#UF%KRx_?rse1bjr} z-%Z)6N&(zxQto16J6Jmcd3wd{?Xi4q^%5`1UjZ4)Uv7Ue1KQj)wlbR*6cE_F+vZkw z6P7Im+I(o-Gr<$HP(Hvv`HOob2(C@@uDO-l%u%_&X$B`=O+mP!w3=4$$!{ijFU(3V z2OsSi9N=TCdF1l2sq^S@`PI~>{e2VSF^|;x0W3C*kd|5B3&+vAfY#%%y2sJ_JzTul z_a;~ZeBe81t0BAtn2M^tX#x^+brK3*-AixgaFLQ-otDu8=1?=!%7y!2zoWgE`JTy| zaQ1F$bq=e^Z02C)+n7K5y^Q8trQBlY&^x%}TG1X4kIoUlA&!X)&Z(edJI60NoxI3n zdDS^^2X-ZEVY9(*$eEP#>Er#IUfH~K})>e6@n0H?_ATcipFI-^xCu+ zCoOA^@_Ok69x{wbNW3R7BE;gAqb{eM(?O7@f=kHQxdNCtM5d8PIt4MBHx3&)=hr39~jVV4U+=Bf`L;xCFat(pJ<@H<< zB!fx17#j^NVrjkJ@B+vuk$>QP+7A>RjC0~pf~UVvCW^#Jl(WB!$@*BGte?#B39g?Y z<*???Lp#=x4BoFJt8bz8{Rt5W>Q_1J$4H`a&{1-Y^A!x9B0@NGG!Z*aYJQ^u+0o;| ze}_#3$m7USAOSn-*~|up;vngf4q9NUayR5!}8E zWD!)nm;yn42e0f56&Ox|7@+5Y;YgYS?}_hayXzy;bf!o((cy#&67=pOvSAjMAow** zr6?GL#w|ym34lm&e{s)qNaqF2C8^SgXVVlvy z7Q$67o*+u)5(S8~+mC`+Xs0V#C z9^9<2p$(K#_P?q>AKF);)om$9^WwdYqgwdN`- z8=|Kxsn%)*djT)F6^U&F6{o(rCr&og5FV~{{;k#c!fkl zQq|W88nz57VRcvRyf| zb9(gTKc~Z1-5fP15x9XlwY&D{=ozWOjW&#bpX0xd1p18}xGSS35=**4s zyP~hqg4#8wM9U1@*dL(Fx4Uzm8okIqooUxv2TlhO+q+8h%pdUL-&#~O7dr*#Y6TUN=rC|bcs?i_YIuUDkkADbz#tRfv$%o8{X?xn zyMJ*1gnZ)u$+M-#Un~m59v3O_5r*qIaiBJd1B@W3O(v(iiJT&K{99O6Km*16m_EcJ z&(fEjM@Fx3?=F~6iH0t;dh%f?rz_#N0EVz09OTDGPd>uWQaZ9jrB-(_rgm+J#w-pK zO0yjv67>n|s!WI%^&KY5On#jS#a^FpMEoprT1cfzyd*@WcEucKPH@2m_3gFnx@GN@@#ju01wQjSU+N{M=A_j^ISB4WL5LA>A_f_u6ow35d}@+g*XNjG*QJQE*!N7y<<=iZT}G7 z9F7$?t)?B3)<>naju<-TrE%C#Mw3_I6s`tc6SMk1L7UI_#d3re!6scKe$$`v+x44*7_!At;X5Zk-98Dk4d0i1Lfje46Z(K)p$0)jMjNl;P}8N*m5D8kq-Y&V0o0(uG< z(bU3jB(QYxxZ$i|p*M7(%oAnjT?X~s_RlEa0iP1W;X1l^#bvIC#WZO z&S(<%u>ZiaGywqwHzdvqpEk6cxbX0Ll=S!q-Fv^s%a2LCU6;z9_&`>goXjW6kCmNQ z^ufWm1|aC}1|-BlETQ|wzM(Fnn+yXeK^0*gLHHX)5xxc)gdP-209RUd338LgX#`ds z+=VS;ze0^fIRAl$D5H6bc&Zm`R-X`Ip8ES`5hF;ny{ZGWx>6iE;~(Ok`iDpo{i0jZ zC-X$yQQ-a|#T^xaOd59E{vG^cxVcDBDA5FzbI2s-B7NkZxoy60ZsDHHv+lu&fWI2i zV^EJ^R?EeGTB~;I06KQY?reSY&ejLG#{bMX2isXLNC+_erl6)!Ot;8hMKs;Ony70> zHugWtBY#dDG!*TMBK$YOksnb zi>1QFI~tQ>mRe$#_F*Qy(i&c?{~j`(`Q12tpvgF3 z(a1!!2#4AZeDUX;NUW&CJ12Ued6;agI4<=mV8oIR^TNeu9b;q7M>uy63Leg(puC0` zKLRM?MwzlYvpa#=yX7deT^ThIU;Jfv&ASfBD0?xBZgN15B9p}F+%vcFX{B6*3a!bf?Y#e7;KRb1k z@=mL6m%)hvH2MENGKq05pxkA}urtRO|Ear0yU0TBujCsW-}^bH6T@WKbbRrjyVD)o ziTDRu)1w#1`=p_ZfoiQYY8lHeB8wRrYW*8YE&i0g!dVtwH6`ReL z$N-QB+#c!uTILkLLNwlgbtWuU z5>Wy;)qevi1Qg`v$G9i7Y4^_Bv$!XO{VQHjq@T}Z>3*=kwDIv6oDo0m9N$HxJ0n^~ zAB?|`$>bbrwm{7$ou0c7f=?D1g!oEsbLF=%|K02Y9>)57e}a>ipQAprs30o zZvx*brTu;Ie$2*x0{sQk9BR}4y!Z*kJAum}ij;+DA+}!v{S|N*oi8ooK6xX#4wu{a zvX1tk%AEXJ$Pg1ep}})Vpq(F^7zd@&KW8O4bK__9G#K{2+^f5t&Aq5++H!gocnIqVUb~W0A2l z1TGqTcExYuD<1XS6b}RG*8F%r)p>HnR&-VN^0SRLzG@GiD|bhL5GFkMQgtH$`{?`X zTNO~RD3T=tGBF+gH7kC|M98y8qdYX@gon}~$G8IXC|vws1=GMjfyBEO&8M7SGkknb z0c0aItCNjC07rO(1SJpS5 z*xFyiizAp({Rd<^heyr#V5M=TJI`N?nuprran5st^Nif#QCcH7I z1;gH5?P`zm?vd`K=SNLCO6u+3DfRAhVIqAp%w?H;!bAj~=oKRMew}rBCZu4kg!DY= zBG5ClYZ1Jjwilyi5#TA+)`{=x)5a<#6>0OPf?CCAwF|M zfjHEjf05S$LT@$XJ!*{Y58)q4D1-gCytXRqPdL%NjDIHqUxCZo#?h>DWO%cfaD@j( z`=yO&bnqva5tQufe_=pJG#5GNBnPC!J6_UT8gy7jrzw-VuKJfu{ymek zOfE5bfyv8EUSV>aiNl0fDWb;+k@Sfmo?i)}igM5Dpxx(q(gP1k4&vynF=ZBvS+f8Y zslb3YyMW*Qh-*dY8!vRA#^$s0mRUfk(UFc%T3P diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc index 8eb549a3c4cc6cc6cc6b6298758702cda4467ceb..8ed0e7c0e2b4fc753e916461bebf748d04281be2 100644 GIT binary patch literal 21655 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

j^ya5w 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 Fe*mux`cwb_ delta 8425 zcmb7JX>c6Jb)KG?ojtGsmbmX5AQm7&@V-Fs00{5|L4YE~k*U=ZJpgyPvkUeNNCFyY zDFU(J#MF^?B*iSrfR(sHTbAjlB3ZE=OL8emmE%M%%du)IiT+qlBqxy)$EuQLk$JBN zpg>BMs_fQ$`?~w}F|Xg%y-!>t?|zBoWpZ;v5`2nF-x&L4>an~kQuJ8+$t;nmM3q#5 zS*RBZT1^$1#d@)zeW?<&R4+Bl^fFP_QsriaULk0Is?w~|tITS>T9gB+8naffHS6>` zvtF+^8}tUVQEwD&!BmsktTziflxi_o>MPAwy%ow?iRPrDW}Dt78pEk}bCteI(7CDA zW{2J(=)BY#vs3RBbbe~BxlUhauGiO#awN6E+^BC9^orCbbF;o#&;_Y2=2m^HpbJym z%~C<`MmfIj9esNA;uTkUm5tLuK!Rgey{t zIjj#8sb8X%v}#tORmSj)qU*;DdHycr_yW;S7!g`ML-e~1pV4OAJt~(=`bl7~p|!wX zYvdq1lg>^P0v@%`zMOxj9Vwvo2^hYBZze@*>ijp_z_;%S-y7Q>C)B99x)N@UV} z!uNMX<$JV#{;XCWjuJO8$TD_jB$MLr`78Ka+Bn(D2mQsl?XaM066=K@*2|gybny-# z`{A)PfRGd*VZwIscl=*JwF@fPZiGDueuNH$9s~uzRV!skaR*NT@DgD%&UWA*&>j3v9ZD^D3@s1C>+&j2`!yf z^&(nk6yItoH%g$jbTmLKXeG3k(G^DCZLL*?W|YGi)$m&(#?p+^a%nUy_D$6*X`NAJ zlt4?pQB50+8ro(kc=v4nvQCsOGyx*G=Q6k8C)A8$(WjU0h1&JB z�pPVsRT_qQH5faB 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 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc index 738c8466c32206e4297acee4e42bb8e5d3d4562c..434a20aad79dee84995b9aa152feead0495702e8 100644 GIT binary patch delta 1528 zcmZuxO>Epm6rLH+dNe zi675q8<~tj;Q8a{A8Nl9A7qEiIweF9iwG*1M=cun%wo`Mo>u1;r^s>d!Kt3#&xAI^oManDGd#oNxB-`tief!kvmuZ=msTz@n>?x6D)@jy&)YYQo z_{|#hndH`>=#pJ>phScLJ!-k=7U}!kDvFHk0rvX;XCC&G|JtOfg_y2S@72#&lTYnt+Jy-j=G^$p*7zJxJv?Z zk8IO6d5OGzG~K{lahj&v*`HZ|wBJj{MALZ9lTK5b zEoiIm>g@D$l?$f3Y;HDMrZ1&1gGS5+D{k}O=_{|4labbxfx-+;M!MIi)uf7&8;N3(CA*jrRjkD zuK^>q%YIK~7}aT-@?X@*;X>kDIx`4$L;k-IkCLTM1F;i+T_~5(Di5m{Q8^C~CGi%+?G67dEbkPd7AkOpkOklI zD)LTMt_Dz9&G^bgcu+GcjIIyufN&KjEZmf9EeZ8^)$xT3KN#6L5fc@7 z7;!Wwg&8fTX6p^n^5h)+oJkY6%Sp;eK@FUtX@;-Cii|UZ^7JW$`pX16M9LwC<^ zO^;ETWsMu~q!Q}jRZp@gcv$c#_zwu85a_c9y?FEBN#E-Yo1kk$ef6rouikt0QGNgH zA7@&_C~7kNdb7W*zc_QRb#(hTTq!1)0>x7hfU}eG%n=UIo}0Q^P1G_^cv)T4Ghg^w zLo~9cXl8*3Dorg7vq(f3d#awcvbJag(}9k3eVyrsZqKt@e1C|Ju9?f)p*<1jTyHxf zR=)OiXP&7B&LnnKQw4Wj(N&>t|A+Ndq*};M{SVt#9b~6pU@BJKyG(U;yyJ+T;@4S! zYVbWUcB4qrq)7DWM6q`bdfevD`I|K~!o{(MV{{ea4lCFW+ky$Z%HEoPlW*}YXTm4& zE;H>-Z{i^5PFw|JW@d5izQKS^;0u`WF9F!5rvMA`55BgqH?G+oSI4jQdFhOFQ91*q z`ZW{TPio8VE;Bv*L+$p-GgNp6fq&?EA^5<-dw?Ohf0^06q4y(fcTr(F2)mw{qc|dn z2`XxeqG^KO0Z`U*K_-PZa&?@fg}j{<@5l|KH*~JFdK&o=CBxE99}X$LfaDrSupfE7 zy`TJ?A8+Goza({I<_R7tY2OYO;T5|T^x??fSHVRNbGD4WT|P#-s_{jNj{oZzE=ym^ zBu@${$M(C{MQGXITQ`=-9`pDi>OjhMUEtj^DeqX-{`t}gRH4^AQRei6@cfe{tnGrS zvQ%AGo-|h0b*|srFjqdaX=mltla&84f?0x71ax(C1flQjA1A|0pUfN-L$iP93nZ#i zQuE}q{Mi24dFjGgBKid92rAtpF5zBTmonA4l=n!mY&YU#5ZF)SmzS&Z)D6Cv{QX1E zVzt%bFqQIi>vbpRLK3^QWBlq|k{4!)^3u~bPY^ssaLIntU08gE!iU`)_+pMCk=kFo z{SHO_8M8vlXA$hu)U9oIbuiL~ikZs@Wqe(4j&;7KpBv;VQ3Jex<==sIRl>t6mHtXL pRO3`%!T*wts5h7S%@9sQ$U{EIUETyYTyS{If&cB%;P(0H?mz1%_Mrd( diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc index 1fe08dd3d4d9d5b050a3e17578e3f5cc2d0480c2..688eca538d0741ee4f2e278e959be703ab3eda26 100644 GIT binary patch delta 2711 zcmZuzPi))P8RvVXD2k#aT9z%zmTkIDvdD0gw#(KvHk@E>vt=F96zS59?VwS5Pc{>Y z)E=odHY7Me0yKxEK=uX11|&CQ!m4I*t&mB_kEP> z1YRic$H(t|-}k=%)EgV`Z5F~p!BpV-$A`b)`ruw+f$HSmS|dvorZBa4?}hqaKkw%I zmTRRXtykz5-6E_rOz)NYwrlsN+^K%qEvK|>Z@OP`E9u(k&Gcv8S)%Zaa6w%TWUFp9 z)noQ*{kmI+y*e**yG!eeJI9N-=JQ<@-WmbrMYqA*d6vIL+y$Oz7CaYOf#>)5X^D+-%tmD>ud@Ww6Gbr`v#G-p0SZ!a}TlIw|KtK)UH z`Ti5+Lz7Qy8N}8tVi1jpW%*m+Sd$-Ve{lH>GuZrH z!W!IS3%tOx-013TkuBZUz~I>fTA5pQrK>TAErW4YUIXKGHqFbd4311>9%C!1Or05E z>al%WuTWB#$BpkVE}>x$z=7Aq*ywrvHuE;O=fLnz- zxyo zkhbc)xPP`-CG^6}@}<%`IVta!jxQ}j_K((2ZexoF{Ki0R{y_e&v~D!%rIbZl_Id>? z6k5^<2V8h@D4MF+l&{*0^G8b8-01mH+zI=G%^%4h+Ix>56z{VrPsJuY63rLykeiwJwvDL(_YNCTiZ%gPo!;ri>jW+~AiOfk3tIZFyx;&5;gR$lCfL89*Z zgGBX$okVMgVNW~(GKuj5-+5k$P>3eHikVd;s*rAhE+py}kA*Flrsqzj&7F?8FCphM z2xk#C0Nm2H7r|uch61VrPLo%sZ|;@aUgvr&0AN-QBR=uuA__SGNfETS27-5?RDurg z0WEqNfHo=whNVhB(J~q>lOi#wPA#h6H}o=E{aDMJ#HNO3 zWi(YIS_v2^{1CN&?#{_SmFDD)%2VdykolVYMdjHFG?>BkyE-&V_R?gE*Y~qCU#FLA zV9W)mr_=Bh%Lo`WNDamzG0~+~D4^0s>eOLElbIIp`CERw$6FAR)^M;TJjUOb?^LfA zII7Sm=d`6>TY08~+Dd-ZiXe7T*XOL&-f89%HHw9}44ad)AIDV@c{98}hP%I?+GTGZ;IH;f4t6 z|K6?1_o}ry=(KF#yAk=jJjp||454HC(EZ}7{7Y?Z{h+5(lhlbx13dofp$&&YO6~p| z9!&vED!ux>)uZ(<&OJi#IiP(k8*}H#Df!x5{cP$vo{$t?_v7u>fmzX!ΠnH<)xh zfX`9K=h5Hg&*$!(Nex8z#a96!-D#C$S&Q!=q!vFg8!Pl*^7{PKWKO;_e`;?Ed9WA7 zbp%XMnzTgqAuM0OR}-OxP(XMZA&Y>YKaoK&5Ilqc0Yj1oNJOwotSE-k==6EK9WsFy z99lJduym047{H5gM{VgfHZQ+QDZO8WJ}PSTzk0^}kFi=Kvntin)PAZH`YEOM{Zy>E zES^LaI0uqkcNlbHm=aNHNutL)1DN#k&y5u-Oi33`oX#Vk*7l$WQm0bCQy7`O3nHZ%^aPeLaAO7`Z8h}e(94IMgugC*_>lGZCj3QE PB22!a7{ro)TsZwd7xhNZ delta 2429 zcmZuzU2Gdg5Wd|zpU;=`Z(=956Q@l|si6eu52bCIq88dBXelb?#~@tCyH2k4*=Fwo zO=J^9i&CUgR8~kJ@jxH@z*AmOUl0l~cp6u|qbJs4%$LMwK^43w^Gb)##$uAR)X-sbpcuvIu+F+4p+)Gpv zUb2$(Qk9hAna#A9sbmx#Z4P=vl_8>WT|5W67U*UxS!E~I%z49=VOSgHDV}K1yjB_E z4$?f|(BZ4lqTHzzc#PTSNTtY+#@GN5qs-w^p68>e!s0y761>Qg+~&nTuVJwiOP@C? zV}~`CVT0#2HpmO-^h$}56IyxbCp_V?)hEdhbRY|)$RP~NUB(zG$&<#}ojZZyI{=nr zk(B8Wix@;~07f0ge;$;242C};Y2>>pR^$#F<#86}R>NdttOR~!*EkvOEon}f-XY~s8D=Ne%acsIGa-5jE1L>{p&mP%k)+=g-Z46W&A&6{PlnTGt``h432 zicBJGLbwNEGs1ecYSnGILACml{66MBd@qQUi74Vk#dcJ{L;p|9WxN%*jm3HSy1kL) z}?HuWufz~xIX|K>;v}ZA$8IY5R zlCf}I$;7%*W-gGP9S{~(Ycb@5_CP?pF_@jD=mqWcvW{kZ@fWn#grNn-;z^?68$?c< zz4(gOAj|@F>yGUcL6pUm$wc2Ivxl`_@+GaMzo9X^m+U6Nu+=5g8qE5qu`WStS7 zoFuZG+Dq=0Jay0b7({A)tYg!2yv5IU#LPSLYHBa76M3aDC`o$r5azN>LaW{3q87A8 zSr_}{-gK$BF3I+E)AfUT+w07%$RNG^z*?FQpgtA*U^(I;j0rbmR` zZI_Qh%r^k&TN!N*W_W(vAKE?-7CJ$@-So>&s4uylP_MNXLt_?L;z1A!t*7|n6GF6w z*aDxTj6B_QTLN7UO?{3BA}JF?g)vq4>h|wK$wv`(BkTo`&kwz|Y%|`hEmnhh*AJ7k zwfdPr095O>1)ul5K7#VQbAr!7v!7SZFUqas*83=UdtX#G4s6$6k7CH zzl)8mrgKlzG9 znG-d}zm}hkJRis2SB~`eIVDs1$>kbytWfs@A&%bKYAaH4fH1^SXTMPo% zVlJx%+%KE`5>eqlg(_%GaD)bea_V+;9i{Kpg8Dr7zW@Qha0oDG(j11$B<9~{1VRQc zgqWCrE{z;_JI6))b?9MY>Q3!&0It9S+yf6vRh*E;!q&t6n-V5nzv|Zl*KfF-Rc99= zhN?)K=+TK=Zruu)@PPLt44(qnM7~|PeBb&C7c+NJJP5pB2j)B{Ex@lpmDxyE|)@;0yeR1O1`~ zmq49F9abGoHGm}AnLtoMNz3<3n_tf0_Z|d{PZ+P>EUW`)W)K&K5H=v-DgJxDwGLrT Wdu_JRgZ}~tZTEEm diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc index 8b0fd0baefa8b4c81727e5b3ee306724cd0380fe..1f25289bb57200a672d37eadc4a56629273037ff 100644 GIT binary patch delta 1519 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 LzF9f9`tn}@c}S&_ literal 7444 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 U)wG6QGfo-}vvIER`s$_s0kH))8~^|S diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc index 84cdbb4fc165200e1ae771b3316f375ed218a8b4..683a5dac53d6ccbdb56a7076b2139e348c544e9a 100644 GIT binary patch delta 2546 zcmZ8iU2Ggz6`nh@yI#-E{&?43d;PPH|Gl<%{o5w35<4Vm(~{zrq!P+VWf<>VyStg$ zS>Ks;lQ7l_IY>n%E$O9{7J=*sL_tCV`2it_5E3suQy~}$@xTK@>I+g7A*3dpbM1zt zyP9vlbMCq4-gE9bcmBTig9|A)nN%hC-T%kOTMLVKQiJ59JF`WV*ov-Lk|o=BUM{qq zgq|Q0h>EQ_Nj)ie#7;SBJ?&)ljF6)scj;NdV|LEz*1HAouzQ@mo)XHXv$JYf$xMZGAvW)C|j^!5oMB<&GrR3CN5^f4i)>~Uv8pAbB4PdZcj zlrybQ3prz#oEd!vc$by6XPr5H&ME6Wsl2~JpE@A=)9s6r)nnyvNmibY?kReg)ob-x1=>lM3zF4OV>FJ8p4^lR(q_yW zum*2M^i$RlRp~Mj8nlWshfEmwNB4yO&5WN9h+v=ci9a#i32l21&+Oz?U%GL;!%5(|0!DT5JNEW z(~(3{ag^QcklNcNLGgxheUSXmM=)JeYmRy+J62( z+D!&YOKM5%{Xnbt!qaz6Vc+u$`~CjF0eJ_CBuMNJqW*yFrhpIm#USOQrgx9jhxg-RmKr3Dk;V#+)koRS zt%Q*0f^>Zh+>gOVes!!H1$o@N3nLTk_s6m@miG)#wvT9dhT zTJ;T-pd3k+t$_IvJOwO_pSDeB!!lQ!=nI`{(#_G!)N}0}$|_J{?jW$rY1^%uwzmr8 z$R4~Y*XWJI+0HVFvQ?PKzpC~rD{P+MP>1JwLBXCucvP_LSr9|n^}-I?*r_qM!TQjk z!2h65kp=#VI;nM|Nz8MZPc5EL%v=$k*&3=zeI05$C%4l zKN|IzmL;OK9&bCA6@HI<^K4=!COYjrZzf*gcN25D%yAcg)~6mD;W=$$A&kQ+O_Nb8 z%r_{tJi~DrHI9^~UvnF!99snE>}iCP{CRC|LLakhPR%!7ci%9ouG6&Xb!=7FZs7!@ zYBr1w%D=0XR~5J#!qo9CLM_9pK^_9#K!-v=3_3iDEl?fX4j(Z47zzWJ4Gry$o73LkFz5iu4{)1WQld4tU%8& zyysX10q;46H6*gc_JD;+!>HP(=T#|O)W&0hETJ7X0ZRf*@_X4!nWl`Xld}(mj@{%h z=T^w6!&|vuM5Cv`YMuWw)5F&bKOx`d_Y0G=7*`l+n*QtTEu_(%npg8hr2lU+_C5^# zhhOY}{*?h>rA`*Wi$xLMM0gwFHp06I?;z{~gsN5B+@y>)sa&Adh8tk zTYrDy`)Dr??mc88q^|?}E6)s^(U64^OgC#CULDvWmwt#=co;{`_2|ftW_|+(;KM6< zm{CpD2t!TjS@va|(FO=RYrG+6~{=9f1x-`y17{#i}Zjq{+r^g3fI(54Nji*^1H>Q*zvVs7IU-EGPYM~ zn$>HjSWz^2WW)3*8^rw#A>b{_iab3$*&YU}$1lGGl@6aqk>0QqKEf}-j=}#ew0sTW zTL_pN5#D2EA<}_4guBskt(Hw!@xJvg1H`2`!T&h4S_T_Vw48VY2hAcvB!hhjPfAvm aj3Tw=6;W1DTA+C#UsVN@AE-*|)BgeWqJnJz delta 2046 zcmY*a&2Jk;6yLGe-@CRG$4ML~vE$}z)7UL(+JZ>MdK~I$THld`p=I7u0nD=Jhd%OPp zM?lV+T>+2U-8^UJ0v@w_c;3thJZ|^$KC>_23A>*c%tFAE z_P{zXn#Dj!*@Jw@916H*5A%{);$^cO$htkkD`q9&X?qVJHAnfFIRC*fC4VdBrIGjZHXX#C-kD3uj-Ge~};MqtJU>7sJOwMj1?^git{kLD+*ZfiQ+J zj$p_~k?EO1pnhzzvCwhEH8F~Y$v{;X%w4fNhUTj-vlq7`mcb+o(W*Qfbs~E~7?%&D zZl)U;&c&;++^>k7kA1!F#ap?Jo=xSXa*?lTp0<(SRMvD)r^<>V=<)?mX(=1Mp0-KW z(q1~y3L5kDdS81MZLNNBoyG%s+Do?zp4KW{4vRZGx(dhx?uTG0icfcR{h%8ZUm~{F zhjz%Y*zA-x$~58Wt&zS{3ntCR=+zHv+5Rfxb1m^gT^c z?Gtq^3sJ_r>?R?Km)aQjbYu`A)tXrA3JyHEVR&8J_VdcHp`S4#q6!u9QwvVp?TCie z?zlT8mLDc2!#D2?%Wo6M)q~))^;xn?Mtrs1;LMM$GT~ZI+gEL?ec6u+)^MG+F(s<< zw^V7m7yQLxglGK{FJhvQ5k( zaz|XNcbs}-)v+*&>)0zDxC-c;I%RB0zLl=Nl(wKC5ET+p3rceYBKTqMHhmQmyJ7|- z25zNps#$8^)IeMT=IizPg57Z41qN-Y@2b^)^a~261KT4X_q>sPJ48ZHqoMA91nLBrhx4=K z(3YM5CPEI$q2dqZru@A)z8CM|t4oc}C9#e)vTC_jC%D=wei2=61@Mpy#ylhj&VWP-I9m=WJDT977cv&JfO#U*r#))y{WHua-dnAN=0 zf$3+BMe#8P30ia)S#ZBL7U!XSGI&I5<4zTeE}C1f46Ty+d+3HO2?l#teS)nkV1Pde z#l;X>QX>L2#zEo2j~}z0X47gn#c>%bT_q>vjnaKNQ!bBVBh12*wN$IaW6VUmVZ*d7 zYawmL=X5wH-9M`$tB^eT9gUV3*yY!_H&8J)WCB9J&Ooc1biWz zWqGsI*ZOaoT``2p__@@ku1qZG@^zyk`5)q*|4%6sz_29_!ntS`8@yt diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py index b206692..0f31dc9 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py @@ -1,31 +1,29 @@ -from typing import FrozenSet, Iterable, Optional, Tuple, Union +from dataclasses import dataclass +from typing import FrozenSet, Iterable, Optional, Tuple from pip._vendor.packaging.specifiers import SpecifierSet -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import LegacyVersion, Version +from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.version import Version from pip._internal.models.link import Link, links_equivalent from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.hashes import Hashes CandidateLookup = Tuple[Optional["Candidate"], Optional[InstallRequirement]] -CandidateVersion = Union[LegacyVersion, Version] -def format_name(project: str, extras: FrozenSet[str]) -> str: +def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> str: if not extras: return project - canonical_extras = sorted(canonicalize_name(e) for e in extras) - return "{}[{}]".format(project, ",".join(canonical_extras)) + extras_expr = ",".join(sorted(extras)) + return f"{project}[{extras_expr}]" +@dataclass(frozen=True) class Constraint: - def __init__( - self, specifier: SpecifierSet, hashes: Hashes, links: FrozenSet[Link] - ) -> None: - self.specifier = specifier - self.hashes = hashes - self.links = links + specifier: SpecifierSet + hashes: Hashes + links: FrozenSet[Link] @classmethod def empty(cls) -> "Constraint": @@ -116,7 +114,7 @@ class Candidate: raise NotImplementedError("Override in subclass") @property - def version(self) -> CandidateVersion: + def version(self) -> Version: raise NotImplementedError("Override in subclass") @property diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py index f5bc343..6617644 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -2,13 +2,16 @@ import logging import sys from typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Union, cast +from pip._vendor.packaging.requirements import InvalidRequirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name from pip._vendor.packaging.version import Version from pip._internal.exceptions import ( HashError, InstallationSubprocessError, + InvalidInstalledPackage, MetadataInconsistent, + MetadataInvalid, ) from pip._internal.metadata import BaseDistribution from pip._internal.models.link import Link, links_equivalent @@ -21,7 +24,7 @@ from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.direct_url_helpers import direct_url_from_link from pip._internal.utils.misc import normalize_version_info -from .base import Candidate, CandidateVersion, Requirement, format_name +from .base import Candidate, Requirement, format_name if TYPE_CHECKING: from .factory import Factory @@ -65,15 +68,13 @@ def make_install_req_from_link( use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) ireq.original_link = template.original_link ireq.link = link + ireq.extras = template.extras return ireq @@ -81,7 +82,7 @@ def make_install_req_from_editable( link: Link, template: InstallRequirement ) -> InstallRequirement: assert template.editable, "template not editable" - return install_req_from_editable( + ireq = install_req_from_editable( link.url, user_supplied=template.user_supplied, comes_from=template.comes_from, @@ -89,13 +90,12 @@ def make_install_req_from_editable( isolated=template.isolated, constraint=template.constraint, permit_editable_wheels=template.permit_editable_wheels, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) + ireq.extras = template.extras + return ireq def _make_install_req_from_dist( @@ -114,11 +114,8 @@ def _make_install_req_from_dist( use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) ireq.satisfied_by = dist @@ -151,7 +148,7 @@ class _InstallRequirementBackedCandidate(Candidate): ireq: InstallRequirement, factory: "Factory", name: Optional[NormalizedName] = None, - version: Optional[CandidateVersion] = None, + version: Optional[Version] = None, ) -> None: self._link = link self._source_link = source_link @@ -160,18 +157,20 @@ class _InstallRequirementBackedCandidate(Candidate): self._name = name self._version = version self.dist = self._prepare() + self._hash: Optional[int] = None def __str__(self) -> str: return f"{self.name} {self.version}" def __repr__(self) -> str: - return "{class_name}({link!r})".format( - class_name=self.__class__.__name__, - link=str(self._link), - ) + return f"{self.__class__.__name__}({str(self._link)!r})" def __hash__(self) -> int: - return hash((self.__class__, self._link)) + if self._hash is not None: + return self._hash + + self._hash = hash((self.__class__, self._link)) + return self._hash def __eq__(self, other: Any) -> bool: if isinstance(other, self.__class__): @@ -194,16 +193,15 @@ class _InstallRequirementBackedCandidate(Candidate): return self.project_name @property - def version(self) -> CandidateVersion: + def version(self) -> Version: if self._version is None: self._version = self.dist.version return self._version def format_for_error(self) -> str: - return "{} {} (from {})".format( - self.name, - self.version, - self._link.file_path if self._link.is_file else self._link, + return ( + f"{self.name} {self.version} " + f"(from {self._link.file_path if self._link.is_file else self._link})" ) def _prepare_distribution(self) -> BaseDistribution: @@ -225,6 +223,13 @@ class _InstallRequirementBackedCandidate(Candidate): str(self._version), str(dist.version), ) + # check dependencies are valid + # TODO performance: this means we iterate the dependencies at least twice, + # we may want to cache parsed Requires-Dist + try: + list(dist.iter_dependencies(list(dist.iter_provided_extras()))) + except InvalidRequirement as e: + raise MetadataInvalid(self._ireq, str(e)) def _prepare(self) -> BaseDistribution: try: @@ -246,7 +251,7 @@ class _InstallRequirementBackedCandidate(Candidate): def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: requires = self.dist.iter_dependencies() if with_requires else () for r in requires: - yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) yield self._factory.make_requires_python_requirement(self.dist.requires_python) def get_install_requirement(self) -> Optional[InstallRequirement]: @@ -262,10 +267,10 @@ class LinkCandidate(_InstallRequirementBackedCandidate): template: InstallRequirement, factory: "Factory", name: Optional[NormalizedName] = None, - version: Optional[CandidateVersion] = None, + version: Optional[Version] = None, ) -> None: source_link = link - cache_entry = factory.get_wheel_cache_entry(link, name) + cache_entry = factory.get_wheel_cache_entry(source_link, name) if cache_entry is not None: logger.debug("Using cached wheel link: %s", cache_entry.link) link = cache_entry.link @@ -278,18 +283,20 @@ class LinkCandidate(_InstallRequirementBackedCandidate): # Version may not be present for PEP 508 direct URLs if version is not None: wheel_version = Version(wheel.version) - assert version == wheel_version, "{!r} != {!r} for wheel {}".format( - version, wheel_version, name - ) + assert ( + version == wheel_version + ), f"{version!r} != {wheel_version!r} for wheel {name}" if cache_entry is not None: + assert ireq.link.is_wheel + assert ireq.link.is_file if cache_entry.persistent and template.link is template.original_link: - ireq.original_link_is_in_wheel_cache = True + ireq.cached_wheel_source_link = source_link if cache_entry.origin is not None: ireq.download_info = cache_entry.origin else: # Legacy cache entry that does not have origin.json. - # download_info may miss the archive_info.hash field. + # download_info may miss the archive_info.hashes field. ireq.download_info = direct_url_from_link( source_link, link_is_in_wheel_cache=cache_entry.persistent ) @@ -317,7 +324,7 @@ class EditableCandidate(_InstallRequirementBackedCandidate): template: InstallRequirement, factory: "Factory", name: Optional[NormalizedName] = None, - version: Optional[CandidateVersion] = None, + version: Optional[Version] = None, ) -> None: super().__init__( link=link, @@ -345,6 +352,7 @@ class AlreadyInstalledCandidate(Candidate): self.dist = dist self._ireq = _make_install_req_from_dist(dist, template) self._factory = factory + self._version = None # This is just logging some messages, so we can do it eagerly. # The returned dist would be exactly the same as self.dist because we @@ -357,18 +365,15 @@ class AlreadyInstalledCandidate(Candidate): return str(self.dist) def __repr__(self) -> str: - return "{class_name}({distribution!r})".format( - class_name=self.__class__.__name__, - distribution=self.dist, - ) + return f"{self.__class__.__name__}({self.dist!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, AlreadyInstalledCandidate): + return NotImplemented + return self.name == other.name and self.version == other.version def __hash__(self) -> int: - return hash((self.__class__, self.name, self.version)) - - def __eq__(self, other: Any) -> bool: - if isinstance(other, self.__class__): - return self.name == other.name and self.version == other.version - return False + return hash((self.name, self.version)) @property def project_name(self) -> NormalizedName: @@ -379,8 +384,10 @@ class AlreadyInstalledCandidate(Candidate): return self.project_name @property - def version(self) -> CandidateVersion: - return self.dist.version + def version(self) -> Version: + if self._version is None: + self._version = self.dist.version + return self._version @property def is_editable(self) -> bool: @@ -392,8 +399,12 @@ class AlreadyInstalledCandidate(Candidate): def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: if not with_requires: return - for r in self.dist.iter_dependencies(): - yield self._factory.make_requirement_from_spec(str(r), self._ireq) + + try: + for r in self.dist.iter_dependencies(): + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) + except InvalidRequirement as exc: + raise InvalidInstalledPackage(dist=self.dist, invalid_exc=exc) from None def get_install_requirement(self) -> Optional[InstallRequirement]: return None @@ -428,20 +439,27 @@ class ExtrasCandidate(Candidate): self, base: BaseCandidate, extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, ) -> None: + """ + :param comes_from: the InstallRequirement that led to this candidate if it + differs from the base's InstallRequirement. This will often be the + case in the sense that this candidate's requirement has the extras + while the base's does not. Unlike the InstallRequirement backed + candidates, this requirement is used solely for reporting purposes, + it does not do any leg work. + """ self.base = base - self.extras = extras + self.extras = frozenset(canonicalize_name(e) for e in extras) + self._comes_from = comes_from if comes_from is not None else self.base._ireq def __str__(self) -> str: name, rest = str(self.base).split(" ", 1) return "{}[{}] {}".format(name, ",".join(self.extras), rest) def __repr__(self) -> str: - return "{class_name}(base={base!r}, extras={extras!r})".format( - class_name=self.__class__.__name__, - base=self.base, - extras=self.extras, - ) + return f"{self.__class__.__name__}(base={self.base!r}, extras={self.extras!r})" def __hash__(self) -> int: return hash((self.base, self.extras)) @@ -461,7 +479,7 @@ class ExtrasCandidate(Candidate): return format_name(self.base.project_name, self.extras) @property - def version(self) -> CandidateVersion: + def version(self) -> Version: return self.base.version def format_for_error(self) -> str: @@ -503,11 +521,11 @@ class ExtrasCandidate(Candidate): ) for r in self.base.dist.iter_dependencies(valid_extras): - requirement = factory.make_requirement_from_spec( - str(r), self.base._ireq, valid_extras + yield from factory.make_requirements_from_spec( + str(r), + self._comes_from, + valid_extras, ) - if requirement: - yield requirement def get_install_requirement(self) -> Optional[InstallRequirement]: # We don't return anything here, because we always @@ -543,7 +561,7 @@ class RequiresPythonCandidate(Candidate): return REQUIRES_PYTHON_IDENTIFIER @property - def version(self) -> CandidateVersion: + def version(self) -> Version: return self._version def format_for_error(self) -> str: diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py index a4c24b5..6c273eb 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -3,6 +3,7 @@ import functools import logging from typing import ( TYPE_CHECKING, + Callable, Dict, FrozenSet, Iterable, @@ -11,6 +12,7 @@ from typing import ( Mapping, NamedTuple, Optional, + Protocol, Sequence, Set, Tuple, @@ -21,13 +23,16 @@ from typing import ( from pip._vendor.packaging.requirements import InvalidRequirement from pip._vendor.packaging.specifiers import SpecifierSet from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import InvalidVersion, Version from pip._vendor.resolvelib import ResolutionImpossible from pip._internal.cache import CacheEntry, WheelCache from pip._internal.exceptions import ( DistributionNotFound, InstallationError, + InvalidInstalledPackage, MetadataInconsistent, + MetadataInvalid, UnsupportedPythonVersion, UnsupportedWheel, ) @@ -36,7 +41,10 @@ from pip._internal.metadata import BaseDistribution, get_default_environment from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req.constructors import install_req_from_link_and_ireq +from pip._internal.req.constructors import ( + install_req_drop_extras, + install_req_from_link_and_ireq, +) from pip._internal.req.req_install import ( InstallRequirement, check_invalid_constraint_type, @@ -47,7 +55,7 @@ from pip._internal.utils.hashes import Hashes from pip._internal.utils.packaging import get_requirement from pip._internal.utils.virtualenv import running_under_virtualenv -from .base import Candidate, CandidateVersion, Constraint, Requirement +from .base import Candidate, Constraint, Requirement from .candidates import ( AlreadyInstalledCandidate, BaseCandidate, @@ -62,11 +70,11 @@ from .requirements import ( ExplicitRequirement, RequiresPythonRequirement, SpecifierRequirement, + SpecifierWithoutExtrasRequirement, UnsatisfiableRequirement, ) if TYPE_CHECKING: - from typing import Protocol class ConflictCause(Protocol): requirement: RequiresPythonRequirement @@ -112,8 +120,9 @@ class Factory: self._editable_candidate_cache: Cache[EditableCandidate] = {} self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {} self._extras_candidate_cache: Dict[ - Tuple[int, FrozenSet[str]], ExtrasCandidate + Tuple[int, FrozenSet[NormalizedName]], ExtrasCandidate ] = {} + self._supported_tags_cache = get_supported() if not ignore_installed: env = get_default_environment() @@ -132,19 +141,23 @@ class Factory: if not link.is_wheel: return wheel = Wheel(link.filename) - if wheel.supported(self._finder.target_python.get_tags()): + if wheel.supported(self._finder.target_python.get_unsorted_tags()): return msg = f"{link.filename} is not a supported wheel on this platform." raise UnsupportedWheel(msg) def _make_extras_candidate( - self, base: BaseCandidate, extras: FrozenSet[str] + self, + base: BaseCandidate, + extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, ) -> ExtrasCandidate: - cache_key = (id(base), extras) + cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras)) try: candidate = self._extras_candidate_cache[cache_key] except KeyError: - candidate = ExtrasCandidate(base, extras) + candidate = ExtrasCandidate(base, extras, comes_from=comes_from) self._extras_candidate_cache[cache_key] = candidate return candidate @@ -161,7 +174,7 @@ class Factory: self._installed_candidate_cache[dist.canonical_name] = base if not extras: return base - return self._make_extras_candidate(base, extras) + return self._make_extras_candidate(base, extras, comes_from=template) def _make_candidate_from_link( self, @@ -169,8 +182,22 @@ class Factory: extras: FrozenSet[str], template: InstallRequirement, name: Optional[NormalizedName], - version: Optional[CandidateVersion], + version: Optional[Version], ) -> Optional[Candidate]: + base: Optional[BaseCandidate] = self._make_base_candidate_from_link( + link, template, name, version + ) + if not extras or base is None: + return base + return self._make_extras_candidate(base, extras, comes_from=template) + + def _make_base_candidate_from_link( + self, + link: Link, + template: InstallRequirement, + name: Optional[NormalizedName], + version: Optional[Version], + ) -> Optional[BaseCandidate]: # TODO: Check already installed candidate, and use it if the link and # editable flag match. @@ -189,7 +216,7 @@ class Factory: name=name, version=version, ) - except MetadataInconsistent as e: + except (MetadataInconsistent, MetadataInvalid) as e: logger.info( "Discarding [blue underline]%s[/]: [yellow]%s[reset]", link, @@ -199,7 +226,7 @@ class Factory: self._build_failures[link] = e return None - base: BaseCandidate = self._editable_candidate_cache[link] + return self._editable_candidate_cache[link] else: if link not in self._link_candidate_cache: try: @@ -219,11 +246,7 @@ class Factory: ) self._build_failures[link] = e return None - base = self._link_candidate_cache[link] - - if not extras: - return base - return self._make_extras_candidate(base, extras) + return self._link_candidate_cache[link] def _iter_found_candidates( self, @@ -261,10 +284,15 @@ class Factory: installed_dist = self._installed_dists[name] except KeyError: return None - # Don't use the installed distribution if its version does not fit - # the current dependency graph. - if not specifier.contains(installed_dist.version, prereleases=True): - return None + + try: + # Don't use the installed distribution if its version + # does not fit the current dependency graph. + if not specifier.contains(installed_dist.version, prereleases=True): + return None + except InvalidVersion as e: + raise InvalidInstalledPackage(dist=installed_dist, invalid_exc=e) + candidate = self._make_candidate_from_dist( dist=installed_dist, extras=extras, @@ -281,7 +309,7 @@ class Factory: specifier=specifier, hashes=hashes, ) - icans = list(result.iter_applicable()) + icans = result.applicable_candidates # PEP 592: Yanked releases are ignored unless the specifier # explicitly pins a version (via '==' or '===') that can be @@ -357,9 +385,8 @@ class Factory: """ for link in constraint.links: self._fail_if_link_is_unsupported_wheel(link) - candidate = self._make_candidate_from_link( + candidate = self._make_base_candidate_from_link( link, - extras=frozenset(), template=install_req_from_link_and_ireq(link, template), name=canonicalize_name(identifier), version=None, @@ -374,6 +401,7 @@ class Factory: incompatibilities: Mapping[str, Iterator[Candidate]], constraint: Constraint, prefers_installed: bool, + is_satisfied_by: Callable[[Requirement, Candidate], bool], ) -> Iterable[Candidate]: # Collect basic lookup information from the requirements. explicit_candidates: Set[Candidate] = set() @@ -385,16 +413,21 @@ class Factory: if ireq is not None: ireqs.append(ireq) - # If the current identifier contains extras, add explicit candidates - # from entries from extra-less identifier. + # If the current identifier contains extras, add requires and explicit + # candidates from entries from extra-less identifier. with contextlib.suppress(InvalidRequirement): parsed_requirement = get_requirement(identifier) - explicit_candidates.update( - self._iter_explicit_candidates_from_base( - requirements.get(parsed_requirement.name, ()), - frozenset(parsed_requirement.extras), - ), - ) + if parsed_requirement.name != identifier: + explicit_candidates.update( + self._iter_explicit_candidates_from_base( + requirements.get(parsed_requirement.name, ()), + frozenset(parsed_requirement.extras), + ), + ) + for req in requirements.get(parsed_requirement.name, []): + _, ireq = req.get_candidate_lookup() + if ireq is not None: + ireqs.append(ireq) # Add explicit candidates from constraints. We only do this if there are # known ireqs, which represent requirements not already explicit. If @@ -434,40 +467,61 @@ class Factory: for c in explicit_candidates if id(c) not in incompat_ids and constraint.is_satisfied_by(c) - and all(req.is_satisfied_by(c) for req in requirements[identifier]) + and all(is_satisfied_by(req, c) for req in requirements[identifier]) ) - def _make_requirement_from_install_req( + def _make_requirements_from_install_req( self, ireq: InstallRequirement, requested_extras: Iterable[str] - ) -> Optional[Requirement]: + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given InstallRequirement. In + most cases this will be a single object but the following special cases exist: + - the InstallRequirement has markers that do not apply -> result is empty + - the InstallRequirement has both a constraint (or link) and extras + -> result is split in two requirement objects: one with the constraint + (or link) and one with the extra. This allows centralized constraint + handling for the base, resulting in fewer candidate rejections. + """ if not ireq.match_markers(requested_extras): logger.info( "Ignoring %s: markers '%s' don't match your environment", ireq.name, ireq.markers, ) - return None - if not ireq.link: - return SpecifierRequirement(ireq) - self._fail_if_link_is_unsupported_wheel(ireq.link) - cand = self._make_candidate_from_link( - ireq.link, - extras=frozenset(ireq.extras), - template=ireq, - name=canonicalize_name(ireq.name) if ireq.name else None, - version=None, - ) - if cand is None: - # There's no way we can satisfy a URL requirement if the underlying - # candidate fails to build. An unnamed URL must be user-supplied, so - # we fail eagerly. If the URL is named, an unsatisfiable requirement - # can make the resolver do the right thing, either backtrack (and - # maybe find some other requirement that's buildable) or raise a - # ResolutionImpossible eventually. - if not ireq.name: - raise self._build_failures[ireq.link] - return UnsatisfiableRequirement(canonicalize_name(ireq.name)) - return self.make_requirement_from_candidate(cand) + elif not ireq.link: + if ireq.extras and ireq.req is not None and ireq.req.specifier: + yield SpecifierWithoutExtrasRequirement(ireq) + yield SpecifierRequirement(ireq) + else: + self._fail_if_link_is_unsupported_wheel(ireq.link) + # Always make the link candidate for the base requirement to make it + # available to `find_candidates` for explicit candidate lookup for any + # set of extras. + # The extras are required separately via a second requirement. + cand = self._make_base_candidate_from_link( + ireq.link, + template=install_req_drop_extras(ireq) if ireq.extras else ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + yield UnsatisfiableRequirement(canonicalize_name(ireq.name)) + else: + # require the base from the link + yield self.make_requirement_from_candidate(cand) + if ireq.extras: + # require the extras on top of the base candidate + yield self.make_requirement_from_candidate( + self._make_extras_candidate(cand, frozenset(ireq.extras)) + ) def collect_root_requirements( self, root_ireqs: List[InstallRequirement] @@ -488,15 +542,27 @@ class Factory: else: collected.constraints[name] = Constraint.from_ireq(ireq) else: - req = self._make_requirement_from_install_req( - ireq, - requested_extras=(), + reqs = list( + self._make_requirements_from_install_req( + ireq, + requested_extras=(), + ) ) - if req is None: + if not reqs: continue - if ireq.user_supplied and req.name not in collected.user_requested: - collected.user_requested[req.name] = i - collected.requirements.append(req) + template = reqs[0] + if ireq.user_supplied and template.name not in collected.user_requested: + collected.user_requested[template.name] = i + collected.requirements.extend(reqs) + # Put requirements with extras at the end of the root requires. This does not + # affect resolvelib's picking preference but it does affect its initial criteria + # population: by putting extras at the end we enable the candidate finder to + # present resolvelib with a smaller set of candidates to resolvelib, already + # taking into account any non-transient constraints on the associated base. This + # means resolvelib will have fewer candidates to visit and reject. + # Python's list sort is stable, meaning relative order is kept for objects with + # the same key. + collected.requirements.sort(key=lambda r: r.name != r.project_name) return collected def make_requirement_from_candidate( @@ -504,14 +570,23 @@ class Factory: ) -> ExplicitRequirement: return ExplicitRequirement(candidate) - def make_requirement_from_spec( + def make_requirements_from_spec( self, specifier: str, comes_from: Optional[InstallRequirement], requested_extras: Iterable[str] = (), - ) -> Optional[Requirement]: + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given specifier. In most cases + this will be a single object but the following special cases exist: + - the specifier has markers that do not apply -> result is empty + - the specifier has both a constraint and extras -> result is split + in two requirement objects: one with the constraint and one with the + extra. This allows centralized constraint handling for the base, + resulting in fewer candidate rejections. + """ ireq = self._make_install_req_from_spec(specifier, comes_from) - return self._make_requirement_from_install_req(ireq, requested_extras) + return self._make_requirements_from_install_req(ireq, requested_extras) def make_requires_python_requirement( self, @@ -535,12 +610,12 @@ class Factory: hash mismatches. Furthermore, cached wheels at present have nondeterministic contents due to file modification times. """ - if self._wheel_cache is None or self.preparer.require_hashes: + if self._wheel_cache is None: return None return self._wheel_cache.get_cache_entry( link=link, package_name=name, - supported_tags=get_supported(), + supported_tags=self._supported_tags_cache, ) def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]: @@ -603,8 +678,26 @@ class Factory: cands = self._finder.find_all_candidates(req.project_name) skipped_by_requires_python = self._finder.requires_python_skipped_reasons() - versions = [str(v) for v in sorted({c.version for c in cands})] + versions_set: Set[Version] = set() + yanked_versions_set: Set[Version] = set() + for c in cands: + is_yanked = c.link.is_yanked if c.link else False + if is_yanked: + yanked_versions_set.add(c.version) + else: + versions_set.add(c.version) + + versions = [str(v) for v in sorted(versions_set)] + yanked_versions = [str(v) for v in sorted(yanked_versions_set)] + + if yanked_versions: + # Saying "version X is yanked" isn't entirely accurate. + # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842 + logger.critical( + "Ignored the following yanked versions: %s", + ", ".join(yanked_versions) or "none", + ) if skipped_by_requires_python: logger.critical( "Ignored the following versions that require a different python " @@ -632,7 +725,6 @@ class Factory: e: "ResolutionImpossible[Requirement, Candidate]", constraints: Dict[str, Constraint], ) -> InstallationError: - assert e.causes, "Installation error reported with no cause" # If one of the things we can't solve is "we need Python X.Y", @@ -693,8 +785,8 @@ class Factory: info = "the requested packages" msg = ( - "Cannot install {} because these package versions " - "have conflicting dependencies.".format(info) + f"Cannot install {info} because these package versions " + "have conflicting dependencies." ) logger.critical(msg) msg = "\nThe conflict is caused by:" @@ -718,7 +810,7 @@ class Factory: + "\n\n" + "To fix this you could try to:\n" + "1. loosen the range of package versions you've specified\n" - + "2. remove package versions to allow pip attempt to solve " + + "2. remove package versions to allow pip to attempt to solve " + "the dependency conflict\n" ) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py index 8663097..a1d57e0 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py @@ -9,13 +9,18 @@ something. """ import functools +import logging from collections.abc import Sequence from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Set, Tuple from pip._vendor.packaging.version import _BaseVersion +from pip._internal.exceptions import MetadataInvalid + from .base import Candidate +logger = logging.getLogger(__name__) + IndexCandidateInfo = Tuple[_BaseVersion, Callable[[], Optional[Candidate]]] if TYPE_CHECKING: @@ -44,11 +49,25 @@ def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: for version, func in infos: if version in versions_found: continue - candidate = func() - if candidate is None: - continue - yield candidate - versions_found.add(version) + try: + candidate = func() + except MetadataInvalid as e: + logger.warning( + "Ignoring version %s of %s since it has invalid metadata:\n" + "%s\n" + "Please use pip<24.1 if you need to use this version.", + version, + e.ireq.name, + e, + ) + # Mark version as found to avoid trying other candidates with the same + # version, since they most likely have invalid metadata as well. + versions_found.add(version) + else: + if candidate is None: + continue + yield candidate + versions_found.add(version) def _iter_built_with_prepended( diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py index 6300dfc..fb0dd85 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -1,5 +1,6 @@ import collections import math +from functools import lru_cache from typing import ( TYPE_CHECKING, Dict, @@ -104,7 +105,7 @@ class PipProvider(_ProviderBase): def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str: return requirement_or_candidate.name - def get_preference( # type: ignore + def get_preference( self, identifier: str, resolutions: Mapping[str, Candidate], @@ -124,14 +125,29 @@ class PipProvider(_ProviderBase): * If equal, prefer if any requirement is "pinned", i.e. contains operator ``===`` or ``==``. * If equal, calculate an approximate "depth" and resolve requirements - closer to the user-specified requirements first. + closer to the user-specified requirements first. If the depth cannot + by determined (eg: due to no matching parents), it is considered + infinite. * Order user-specified requirements by the order they are specified. * If equal, prefers "non-free" requirements, i.e. contains at least one operator, such as ``>=`` or ``<``. * If equal, order alphabetically for consistency (helps debuggability). """ - lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) - candidate, ireqs = zip(*lookups) + try: + next(iter(information[identifier])) + except StopIteration: + # There is no information for this identifier, so there's no known + # candidates. + has_information = False + else: + has_information = True + + if has_information: + lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) + candidate, ireqs = zip(*lookups) + else: + candidate, ireqs = None, () + operators = [ specifier.operator for specifier_set in (ireq.specifier for ireq in ireqs if ireq) @@ -146,11 +162,14 @@ class PipProvider(_ProviderBase): requested_order: Union[int, float] = self._user_requested[identifier] except KeyError: requested_order = math.inf - parent_depths = ( - self._known_depths[parent.name] if parent is not None else 0.0 - for _, parent in information[identifier] - ) - inferred_depth = min(d for d in parent_depths) + 1.0 + if has_information: + parent_depths = ( + self._known_depths[parent.name] if parent is not None else 0.0 + for _, parent in information[identifier] + ) + inferred_depth = min(d for d in parent_depths) + 1.0 + else: + inferred_depth = math.inf else: inferred_depth = 1.0 self._known_depths[identifier] = inferred_depth @@ -161,16 +180,6 @@ class PipProvider(_ProviderBase): # free, so we always do it first to avoid needless work if it fails. requires_python = identifier == REQUIRES_PYTHON_IDENTIFIER - # HACK: Setuptools have a very long and solid backward compatibility - # track record, and extremely few projects would request a narrow, - # non-recent version range of it since that would break a lot things. - # (Most projects specify it only to request for an installer feature, - # which does not work, but that's another topic.) Intentionally - # delaying Setuptools helps reduce branches the resolver has to check. - # This serves as a temporary fix for issues like "apache-airflow[all]" - # while we work on "proper" branch pruning techniques. - delay_this = identifier == "setuptools" - # Prefer the causes of backtracking on the assumption that the problem # resolving the dependency tree is related to the failures that caused # the backtracking @@ -178,7 +187,6 @@ class PipProvider(_ProviderBase): return ( not requires_python, - delay_this, not direct, not pinned, not backtrack_cause, @@ -227,8 +235,10 @@ class PipProvider(_ProviderBase): constraint=constraint, prefers_installed=(not _eligible_for_upgrade(identifier)), incompatibilities=incompatibilities, + is_satisfied_by=self.is_satisfied_by, ) + @lru_cache(maxsize=None) def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> bool: return requirement.is_satisfied_by(candidate) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py index 6ced532..0594569 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -11,16 +11,16 @@ logger = getLogger(__name__) class PipReporter(BaseReporter): def __init__(self) -> None: - self.backtracks_by_package: DefaultDict[str, int] = defaultdict(int) + self.reject_count_by_package: DefaultDict[str, int] = defaultdict(int) - self._messages_at_backtrack = { + self._messages_at_reject_count = { 1: ( "pip is looking at multiple versions of {package_name} to " "determine which version is compatible with other " "requirements. This could take a while." ), 8: ( - "pip is looking at multiple versions of {package_name} to " + "pip is still looking at multiple versions of {package_name} to " "determine which version is compatible with other " "requirements. This could take a while." ), @@ -32,16 +32,28 @@ class PipReporter(BaseReporter): ), } - def backtracking(self, candidate: Candidate) -> None: - self.backtracks_by_package[candidate.name] += 1 + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + self.reject_count_by_package[candidate.name] += 1 - count = self.backtracks_by_package[candidate.name] - if count not in self._messages_at_backtrack: + count = self.reject_count_by_package[candidate.name] + if count not in self._messages_at_reject_count: return - message = self._messages_at_backtrack[count] + message = self._messages_at_reject_count[count] logger.info("INFO: %s", message.format(package_name=candidate.name)) + msg = "Will try a different candidate, due to conflict:" + for req_info in criterion.information: + req, parent = req_info.requirement, req_info.parent + # Inspired by Factory.get_installation_error + msg += "\n " + if parent: + msg += f"{parent.name} {parent.version} depends on " + else: + msg += "The user requested " + msg += req.format_for_error() + logger.debug(msg) + class PipDebuggingReporter(BaseReporter): """A reporter that does an info log for every event it sees.""" @@ -54,6 +66,7 @@ class PipDebuggingReporter(BaseReporter): def ending_round(self, index: int, state: Any) -> None: logger.info("Reporter.ending_round(%r, state)", index) + logger.debug("Reporter.ending_round(%r, %r)", index, state) def ending(self, state: Any) -> None: logger.info("Reporter.ending(%r)", state) @@ -61,8 +74,8 @@ class PipDebuggingReporter(BaseReporter): def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) - def backtracking(self, candidate: Candidate) -> None: - logger.info("Reporter.backtracking(%r)", candidate) + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + logger.info("Reporter.rejecting_candidate(%r, %r)", criterion, candidate) def pinning(self, candidate: Candidate) -> None: logger.info("Reporter.pinning(%r)", candidate) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py index f561f1f..b04f41b 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -1,6 +1,9 @@ +from typing import Any, Optional + from pip._vendor.packaging.specifiers import SpecifierSet from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._internal.req.constructors import install_req_drop_extras from pip._internal.req.req_install import InstallRequirement from .base import Candidate, CandidateLookup, Requirement, format_name @@ -14,10 +17,15 @@ class ExplicitRequirement(Requirement): return str(self.candidate) def __repr__(self) -> str: - return "{class_name}({candidate!r})".format( - class_name=self.__class__.__name__, - candidate=self.candidate, - ) + return f"{self.__class__.__name__}({self.candidate!r})" + + def __hash__(self) -> int: + return hash(self.candidate) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, ExplicitRequirement): + return False + return self.candidate == other.candidate @property def project_name(self) -> NormalizedName: @@ -43,16 +51,35 @@ class SpecifierRequirement(Requirement): def __init__(self, ireq: InstallRequirement) -> None: assert ireq.link is None, "This is a link, not a specifier" self._ireq = ireq - self._extras = frozenset(ireq.extras) + self._equal_cache: Optional[str] = None + self._hash: Optional[int] = None + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) + + @property + def _equal(self) -> str: + if self._equal_cache is not None: + return self._equal_cache + + self._equal_cache = str(self._ireq) + return self._equal_cache def __str__(self) -> str: return str(self._ireq.req) def __repr__(self) -> str: - return "{class_name}({requirement!r})".format( - class_name=self.__class__.__name__, - requirement=str(self._ireq.req), - ) + return f"{self.__class__.__name__}({str(self._ireq.req)!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SpecifierRequirement): + return NotImplemented + return self._equal == other._equal + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash(self._equal) + return self._hash @property def project_name(self) -> NormalizedName: @@ -64,7 +91,6 @@ class SpecifierRequirement(Requirement): return format_name(self.project_name, self._extras) def format_for_error(self) -> str: - # Convert comma-separated specifiers into "A, B, ..., F and G" # This makes the specifier a bit more "human readable", without # risking a change in meaning. (Hopefully! Not all edge cases have @@ -93,20 +119,68 @@ class SpecifierRequirement(Requirement): return spec.contains(candidate.version, prereleases=True) +class SpecifierWithoutExtrasRequirement(SpecifierRequirement): + """ + Requirement backed by an install requirement on a base package. + Trims extras from its install requirement if there are any. + """ + + def __init__(self, ireq: InstallRequirement) -> None: + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = install_req_drop_extras(ireq) + self._equal_cache: Optional[str] = None + self._hash: Optional[int] = None + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) + + @property + def _equal(self) -> str: + if self._equal_cache is not None: + return self._equal_cache + + self._equal_cache = str(self._ireq) + return self._equal_cache + + def __eq__(self, other: object) -> bool: + if not isinstance(other, SpecifierWithoutExtrasRequirement): + return NotImplemented + return self._equal == other._equal + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash(self._equal) + return self._hash + + class RequiresPythonRequirement(Requirement): """A requirement representing Requires-Python metadata.""" def __init__(self, specifier: SpecifierSet, match: Candidate) -> None: self.specifier = specifier + self._specifier_string = str(specifier) # for faster __eq__ + self._hash: Optional[int] = None self._candidate = match def __str__(self) -> str: return f"Python {self.specifier}" def __repr__(self) -> str: - return "{class_name}({specifier!r})".format( - class_name=self.__class__.__name__, - specifier=str(self.specifier), + return f"{self.__class__.__name__}({str(self.specifier)!r})" + + def __hash__(self) -> int: + if self._hash is not None: + return self._hash + + self._hash = hash((self._specifier_string, self._candidate)) + return self._hash + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, RequiresPythonRequirement): + return False + return ( + self._specifier_string == other._specifier_string + and self._candidate == other._candidate ) @property @@ -143,10 +217,15 @@ class UnsatisfiableRequirement(Requirement): return f"{self._name} (unavailable)" def __repr__(self) -> str: - return "{class_name}({name!r})".format( - class_name=self.__class__.__name__, - name=str(self._name), - ) + return f"{self.__class__.__name__}({str(self._name)!r})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UnsatisfiableRequirement): + return NotImplemented + return self._name == other._name + + def __hash__(self) -> int: + return hash(self._name) @property def project_name(self) -> NormalizedName: diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py index a605d6c..c12beef 100644 --- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -1,3 +1,4 @@ +import contextlib import functools import logging import os @@ -11,6 +12,7 @@ from pip._vendor.resolvelib.structs import DirectedGraph from pip._internal.cache import WheelCache from pip._internal.index.package_finder import PackageFinder from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import install_req_extend_extras from pip._internal.req.req_install import InstallRequirement from pip._internal.req.req_set import RequirementSet from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider @@ -19,6 +21,7 @@ from pip._internal.resolution.resolvelib.reporter import ( PipDebuggingReporter, PipReporter, ) +from pip._internal.utils.packaging import get_requirement from .base import Candidate, Requirement from .factory import Factory @@ -88,9 +91,9 @@ class Resolver(BaseResolver): ) try: - try_to_avoid_resolution_too_deep = 2000000 + limit_how_complex_resolution_can_be = 200000 result = self._result = resolver.resolve( - collected.requirements, max_rounds=try_to_avoid_resolution_too_deep + collected.requirements, max_rounds=limit_how_complex_resolution_can_be ) except ResolutionImpossible as e: @@ -101,9 +104,24 @@ class Resolver(BaseResolver): raise error from e req_set = RequirementSet(check_supported_wheels=check_supported_wheels) - for candidate in result.mapping.values(): + # process candidates with extras last to ensure their base equivalent is + # already in the req_set if appropriate. + # Python's sort is stable so using a binary key function keeps relative order + # within both subsets. + for candidate in sorted( + result.mapping.values(), key=lambda c: c.name != c.project_name + ): ireq = candidate.get_install_requirement() if ireq is None: + if candidate.name != candidate.project_name: + # extend existing req's extras + with contextlib.suppress(KeyError): + req = req_set.get_requirement(candidate.project_name) + req_set.add_named_requirement( + install_req_extend_extras( + req, get_requirement(candidate.name).extras + ) + ) continue # Check if there is already an installation under the same name, @@ -159,6 +177,9 @@ class Resolver(BaseResolver): reqs = req_set.all_requirements self.factory.preparer.prepare_linked_requirements_more(reqs) + for req in reqs: + req.prepared = True + req.needs_more_preparation = False return req_set def get_installation_order( diff --git a/venv/Lib/site-packages/pip/_internal/self_outdated_check.py b/venv/Lib/site-packages/pip/_internal/self_outdated_check.py index 9e2149c..2e0e3df 100644 --- a/venv/Lib/site-packages/pip/_internal/self_outdated_check.py +++ b/venv/Lib/site-packages/pip/_internal/self_outdated_check.py @@ -9,6 +9,7 @@ import sys from dataclasses import dataclass from typing import Any, Callable, Dict, Optional +from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._vendor.rich.console import Group from pip._vendor.rich.markup import escape @@ -17,7 +18,6 @@ from pip._vendor.rich.text import Text from pip._internal.index.collector import LinkCollector from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import get_default_environment -from pip._internal.metadata.base import DistributionVersion from pip._internal.models.selection_prefs import SelectionPreferences from pip._internal.network.session import PipSession from pip._internal.utils.compat import WINDOWS @@ -26,10 +26,13 @@ from pip._internal.utils.entrypoints import ( get_best_invocation_for_this_python, ) from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace -from pip._internal.utils.misc import ensure_dir - -_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" +from pip._internal.utils.misc import ( + ExternallyManagedEnvironment, + check_externally_managed, + ensure_dir, +) +_WEEK = datetime.timedelta(days=7) logger = logging.getLogger(__name__) @@ -40,6 +43,15 @@ def _get_statefile_name(key: str) -> str: return name +def _convert_date(isodate: str) -> datetime.datetime: + """Convert an ISO format string to a date. + + Handles the format 2020-01-22T14:24:01Z (trailing Z) + which is not supported by older versions of fromisoformat. + """ + return datetime.datetime.fromisoformat(isodate.replace("Z", "+00:00")) + + class SelfCheckState: def __init__(self, cache_dir: str) -> None: self._state: Dict[str, Any] = {} @@ -73,12 +85,10 @@ class SelfCheckState: if "pypi_version" not in self._state: return None - seven_days_in_seconds = 7 * 24 * 60 * 60 - # Determine if we need to refresh the state - last_check = datetime.datetime.strptime(self._state["last_check"], _DATE_FMT) - seconds_since_last_check = (current_time - last_check).total_seconds() - if seconds_since_last_check > seven_days_in_seconds: + last_check = _convert_date(self._state["last_check"]) + time_since_last_check = current_time - last_check + if time_since_last_check > _WEEK: return None return self._state["pypi_version"] @@ -100,7 +110,7 @@ class SelfCheckState: # Include the key so it's easy to tell which pip wrote the # file. "key": self.key, - "last_check": current_time.strftime(_DATE_FMT), + "last_check": current_time.isoformat(), "pypi_version": pypi_version, } @@ -133,7 +143,7 @@ class UpgradePrompt: return Group( Text(), Text.from_markup( - f"{notice} A new release of pip available: " + f"{notice} A new release of pip is available: " f"[red]{self.old}[reset] -> [green]{self.new}[reset]" ), Text.from_markup( @@ -155,7 +165,7 @@ def was_installed_by_pip(pkg: str) -> bool: def _get_current_remote_pip_version( session: PipSession, options: optparse.Values -) -> str: +) -> Optional[str]: # Lets use PackageFinder to see what the latest pip version is link_collector = LinkCollector.create( session, @@ -176,7 +186,7 @@ def _get_current_remote_pip_version( ) best_candidate = finder.find_best_candidate("pip").best_candidate if best_candidate is None: - return + return None return str(best_candidate.version) @@ -185,12 +195,15 @@ def _self_version_check_logic( *, state: SelfCheckState, current_time: datetime.datetime, - local_version: DistributionVersion, - get_remote_version: Callable[[], str], + local_version: Version, + get_remote_version: Callable[[], Optional[str]], ) -> Optional[UpgradePrompt]: remote_version_str = state.get(current_time) if remote_version_str is None: remote_version_str = get_remote_version() + if remote_version_str is None: + logger.debug("No remote pip version found") + return None state.set(remote_version_str, current_time) remote_version = parse_version(remote_version_str) @@ -222,18 +235,18 @@ def pip_self_version_check(session: PipSession, options: optparse.Values) -> Non installed_dist = get_default_environment().get_distribution("pip") if not installed_dist: return - try: - upgrade_prompt = _self_version_check_logic( - state=SelfCheckState(cache_dir=options.cache_dir), - current_time=datetime.datetime.utcnow(), - local_version=installed_dist.version, - get_remote_version=functools.partial( - _get_current_remote_pip_version, session, options - ), - ) - if upgrade_prompt is not None: - logger.warning("[present-rich] %s", upgrade_prompt) - except Exception: - logger.warning("There was an error checking the latest version of pip.") - logger.debug("See below for error", exc_info=True) + check_externally_managed() + except ExternallyManagedEnvironment: + return + + upgrade_prompt = _self_version_check_logic( + state=SelfCheckState(cache_dir=options.cache_dir), + current_time=datetime.datetime.now(datetime.timezone.utc), + local_version=installed_dist.version, + get_remote_version=functools.partial( + _get_current_remote_pip_version, session, options + ), + ) + if upgrade_prompt is not None: + logger.warning("%s", upgrade_prompt, extra={"rich": True}) diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-310.pyc index fa820d55b6bf6acc29792f29986cd3d9bb6228aa..a85a551dd971dec4781200477334d9fa02c1595a 100644 GIT binary patch delta 18 YcmZ3*xQdZ0pO=@50SLZ5p2)QT04YTU2mk;8 delta 18 YcmZ3*xQdZ0pO=@50SH9JCvq(S03omgTL1t6 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2e368dbb47b76bbe9cbceb82f105276662e66f5 GIT binary patch literal 3825 zcmcgv+iu&)876hGW!lcBL7Q!Xq8%g!WC2?FK3fE<$a2iBEV+~%*IuPEMUEso6o;Lm z?3LjFZL@t3`?7D)H|PuWO1FEpFVKqsZTkJAL*;nW-My)7Qsm5k{QkrI5}TWrfzLm` z{zw1ereS(CRA`=<`a5-!^3#6iE8`^1&9jW3^;fgV)I&R_E_(5?CF{sz7+Kh-n}o9^GThOs+}yd)5jVqGal{XxRSIhU*_ z#gLu3()C0s;a?^t%W4g{;;grzcO_?$NSGSMu~6J+iC|sMM)Y_QB!eJgr*ROMIzg0h z8M)zUiA`mI(;DzFCOr#rch#RR=|3guJaW4sXXiZfg$$xTi}(eXmM7wXD<*o-_p0BK zT#1qNxH{Elh*81@?m3Y|#FUra7VSnp3latSNdVJ)9zz35S(tTjTJp>0Qn)ffnhE1cmxzBkEQTO9-z`l!<~Krh@gs0 z2ach*cw$)<5s$HjsC@1!5izI4Dnbmq%CZi)90p1ubfkR1CGU<|U%CL>FG4EkgornA zWuF(xbvGI_Ku%&rH*tfA9CG1eJhngy2Nl%!k_!qfLET;3WH%V(*Sl$`>n`w zq*PJcS!6@u2fZ=Axppfab;Cdnip&p4ba#}1QqiKuxk!F&3u!4Hh9qH@C(G7p8qxx6 zpnnFD)_XBP5iHXJX{$Gq5mZj|-4}pNYdqs#LQ;slCqjgeTtoi&fi5ouvxP0Ui}KRG zOv8!-f~gvA9RO{_G^(>LHE>}&3Tp}&^ahbdOLKQ5Ijj-{J^=QykkfM3A^mRCLnPLWlA zci>c;P1bNMd;g$jSFvW-E49NNyZ)R#17E$-Vl{i;Zb4|P!ARjulwAeiF59m$qs`+O0at+-*3l%nr&<%dQ;O$__g?bPgKLD%9^lY~8N!I?z(xuhv^7XvG?< zzQ7A>?v-mbQe~A7VZB54u}b6M*s-7Qwb)*xwo}F8vnnhrKdV)zs^CT{ zBcp;#-N)_95UW?lHI9uNbHhN(Pu1U=j|=9+Lb}LAQQ_e&jnet6A#oTOZ+}~P(nf2d zY*uYhq2G4gIB279p0{g3x2=MNe-gXiE4R;88~uHI(cia6Nf4^-&a`cJ^sy0-Cu^NZ zMBUJhUj2#;OW}6kl&koTp4dtHzw>i-9N)gi{Wz|@X%-H zZW#Dz9MQD@yNtR3>P|>BbS}w!BtFqUefku1D%lznV@I=W<@1Gt-u>d`hl#$(_k_q7 zS-$Ja{L4ARt;G*B6InYV&L7Iyjx_6I@REQ__Sh3c>cQV4X=(Gj9GM!Uy}8s*0j_pL zf8XxgZOZ&qd?7noBYYDfLN&?akO`v6CY@xRIqZ}4(2XbSOK2n0a`RoCY}4BcLM=CN z+rp)@ieff8t5j#@E zXwy1sYAFwWtaoPXTa+Q}G1DocxpZbtleUb>MGY1QB+?s|$Jx*wPY(pCwRVvAT@zCS|p+#Zht~RQRe1r+;@zZh1celd5t;u#+092-n+uw>!<$$bgxr4 zMv^AVkB!&nkrAzDj3hJ8n+E+Iz6A6E6un{j^+)!Mbs1;&(V=fEkQ z1kngbD@G`nCDIMB(ML?YS1LpVmJrrGXtH!Ylo^X9#~@39(eSeX zjmAIC>crlD|Vv7HC`5)ZfHJ8O<_&365pf4_V84qY-s4R4ae&k23l z%8!uhlT3t`Gudn=BDS%u6R41yWVJ1tW%zz&{pe1HG^lcZid*WBxsP+EWv0xZn;T}% zOue)ImCI({%3ol!us&JsbTGYlI+Hd1TZ=lj%wbD+$H_f~xP^!wI!odWbmN`mB=6&> z1kBVob^p^PtVJ%FM#r_Jt~|;88iV;L=4mnYnZ(W0|=JxH20b{RdMT BRL}qb literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-310.pyc index 11194090c3b9c636c8aba7163552da63b3833ad4..7cada1c8ae03091da4f956804f7c26ef246e10cc 100644 GIT binary patch delta 19 Zcmcb`eT$nbpO=@50SLZ5-pF-<6#zFz1DZoS(GnrWltvjtXx$SP0`Xr{=rd1cXv zTvlg|eKTlo8?5;W1+#F&+~GW%Jwk)Fmf2hnXKhZq3v9lJgGGk7jMn1YXIuF&I{30_ zB88v6IQa9eX+woAEF54$%byKVp8P^DmujF$4H!Ad!XBasPd!4h@V`FCb9lK5K4nHS zZ|BOAc{og%GCTcDa#5MQqbuWz4!{vpPL%Yy_KPx@&Oo zS%bZNJ4=(_w!Yf#XK@Vu5;IyOa!)EN-y3KP2Fqm4TwC|gT)9vrN%LYX%6rX)OtLgg(kK&m zbVTW*q~hy>PBL>f)a|}he6a$0`pS8@ld)l+Zy?a*eE@1W#DR5lU=bYbk_xH&?uv_G R8>Sf6?=o4~{p7%Q6yDiCuQ#!iHn9`u$8nv~b`ul=iL5B3RjR5WRAdTmC9qVjR-Q>>YI|32 zH)+}?G7^zEm*K#nhxP*M8HodDByK&RN=SR<2%IW`R3X88yT$pzD}A2%=DqKIZ)SFX znR!;t`?;L0;P200pKpFP{xCnqHXhEu*Xs;5hL|GQ<6&+*VU1JV6oxp>GaG72;g%TL z(0P{I2YO?a4~P+DG%-?AkR9YXWD6(QJRd@~c!C|~r;r^x!Jg(L2R*$p&PRow$|fcI zV=PkOMNBO5v7~ecnQ>l1W+JQdGkgN`&zYf=d;gzmQyC$_%+)5VVDSq?dC!WSvZs4(H`h`tod& zTtzxn$h%nh(EeniQZ`EZ8#t1;wUQ1c96Zye*I|OhG@zJew8plu}NF@8t;4E^> z#J`4czv^PR+|esNI7j4pf(rx=!5~84B@uH3^9YS$uNiH7ZMU=Cj#?fxw;BUfc}GCl z^1HA=f&Xji*ojahut@MGHnM7blQVZ$YHn>g)?2len*769GHH8ZL7p=&3?yP{AMz8k z!mh~s<}|w~zea4x@6EZM@|bb$34?N^?J1wLeSJ^Aq3kiP?_f`neuPstU#&Vu9p1tk zv6&uoLqm&>3QJVChTs^mLhE)Ic@TwnThSII#?i9^7t@HuD!r! z*^hB0r0`*8GmGgN`z4}b{f(%Z|L6?X=KIZ}mope1vnJiLP>Al~ElbYQm-np8 z7uPAq+zz-GiP#jok?3+qhsy~KBE&5sS?tdq~gK?pWFvzA@UWK~+EqkZ%0cD?*kaz5< z!al{*N6ykr+zFEnGPwTTBfFyYKB6SD?r8Bqs~ZUjKp?`A1-MB;xB8J5)M|2(uWTTNHxxe+d<$%BseVhrDMAly3MrDlY5Y(E$AnGA^rT-VLDw$ zt=ApBjz4Ew{+QqD0ln&RhQ0-@wn$&IpF%Y!za3iq7x)Tf9{>OV delta 1342 zcmZ8gO>7fK6yDjL{qfqH*pC0>#K9M`p+F&Sh!BlbN}vej9uQTP%gXXh5*PohW;bns zSXNc8l|Uo)Si!A5_tr~~z4cV7(n`Jc$f4@3Y7xA*8yu5e>D!s_z4yKM=I#8}{G%~9 zavWQMr&#`dj})KH)ydsw=Wb7k!pZY_roSLNS!QsZ=a{*xRuyLP{4QlFWPSq|6|%X6B<$J%e#6O>zE1#l^|Vw}VTro_s?R8lHy zunGi1TCgTxEX-h4R(qoFR8wm5vX!ZQHqqj7O#PkY8n>Vgn=P?r8$@bMy{EWm zdTm#YjNOqKbizpM^C4{23-60EDw2o}I|D8Xun{O5+1L8LAnc9?{#FC_f&7-P>y8IP z@>ja-WPo$cI9RO6e`qTmht}hGc}ZVr)G!K3n^2O4*Cv)}{7W;&Yf8kb92-A4w70Rj z5gCV@8{S4sUN+YatVW!b56sm>FeylWZ?2FF@)vW7wB(V^Aa6^$)4>PcIdkhqMn zj&K$sE+?r;Q9e+jqPNFGuX_-Lqk-r5J0YHL@G-asd4RZSLUrqZi%>0Y{EB>S{d{h! z163`8V???*gMjnl$qd9YSU#73r9P@$K_BD5XPuBo20sk>kU4sp z{5w@8ZTYp`AlKy!+pps&L=(Uz0&AOXL!M7pavqR@0gxeeGN+1d`C0nG&70_Y+8?;6 zJll0|7;@nY4!Dalc%3cHAQmx5hKO4~nVA)BavQZa0bDIg&xD8>gSdlEcc-3~*v9oO zgzE?>Ew&IWgcO1a;95zUs4qT2K-DM}9Qgi7gq(@iR64SIf!FmPhWn%AqkcP1C30|> z(;#0)^V``^QD1Gh;dg?^U6dEI`;*ATi_z1W5n@ diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc index 8efad5abe47e5e20ce8f4c298bedccd9e30d478f..7fa216567ae7f45b471087cad6a264e1e45602d7 100644 GIT binary patch delta 214 zcmew?d0&z@pO=@50SLZ5zLH)&k#|}>f2wdAlO#h5cPe`-Kal206;9zz6-nVsWld!R z^7(+_^kLE~y1YsmX~YnfZB>HF=ad*uxWx@-p+%Cwucu0RZ)2H}C)e diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc index 6ac3f3de028c473fcd9c8c03aa91a079f417dca4..94d9c3eac22ed3059cc232c7ac9dd7c9e9ee01fa 100644 GIT binary patch delta 495 zcmY+A%}WA77{=$F*{@bNwhuKzEk6pDNU)1`5b73PA_7l=s4Jz33!??aMv;e3U7BuE z=&f5s9s4ut(zXAg!*-~dEhGo#nTKbd-#ai@=A~&khM^A z7cfEu=(gzF5+?!?G%paB&|MeXvaR%kE*U@siDzBBgDjOz;9SguB@fn4jP_y0uG3nz zJfC&;z@=fFHffSdg`A^U( zE*7DZ@R|@=1VHD6j}9fqR-_Chp30IA5MoVvHZ;WP46k`m;8d9PU)LJ(6C!|FTB^nY%pUepN|LHrW4q2wD_X}}xl@NqfahxX2j#hmr I#@^KY51fx^rT_o{ delta 502 zcmY*U&r1S97~OAXciprN`ymTzrCEWL;iVs!qGNQZLl8s5qu(v={gF4biU zI_j;CQS@(g>E!>>#Zxm|M9tyx=FNNW`{pWq6V`2A4@&$*jE}?1XMF?UjqSqJ`J_io z(vdx>Ov(yJ)n|b&U6xv;I_-kEyIPyzl1Ie5(0$JUE_$>R{N`N%sjC0DLv7-$ZAusL zFENN)!f#TZ7&Ii2@MskG_yV%2baan)!I1oVvLmHcW{~A%Lu}bV z=-PO;+J{shX46BgLXuifJ+Sd4@3L!h1TpqW?i3Zmps`yTg>m*ocQd2>?>NjMO;HwH z6QBqIa6<6dFT~lrya0)peK`o(F)sH;&^oPIj%%4YwCW|NWLJ65Zzmeu)Q44G6=CvlwRQ4Z-KCI$B=OmWr=)r(H9kS|uOs`=fJ5;EjaOhP}I5$x|i4{8arj07HM#>G>D ULr*T)_AzGvTm4X+y$4pl07OD?!T0aWce$P)yk6;ud=6}Pz3L~8GpoLh4`#j*m*lVFNVF9atB)uvNk5RjJ z0rgPZvo~IHljY`xQkk+ryi~wU4#db6gP#EBkVf+Lm})nSo^T_IWU11xI_o&{o{o4;MW^HpmA<}zN=l#kEwreV6}L0ODxUz_FTR8JtG5Wi9=1^ah}9O=vRdLY z*n{j61K{=f{54gYN4d(Tf^inXrHhnHqaQ}An+q97R7TnG10R{lOsI(_RD-~yl$z0G zJ!hw0kAR-bSyadqnVrdh^+4j0h-IcY+gXNL)b>>s+P5`5$&`C=ZNns!v6GZT?7{X>+H8v>4?U5CaBgTTykcrpdw7O9G3o4~BEjao)8`&eUloj2S|Ggc)0 Qse@R%@ob_dob#ah8%mKP&Hw-a diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc index 20eb2bbd10acfe668f25dad6dbdf801ed5a3c448..1db8d19d1049467295be15334e5e9b5f737cee3d 100644 GIT binary patch delta 1048 zcmZ9K&ubGw6vt;~XE&Qo^P|-^wDd5AijBntf6$^QK@T3pgGH2ptZR0gY`edlnNTVl zQqY6f67V8wdlJvyJ*g)V1VPxVC;tJD)i;~^qn%~G``#Po&HKEW&$Vw;mAG8C5R9MS zzjj|0cPsPw+3xbGVW_utj9lbufe{wkh0tu9xle;)Xtk}d)GmRqyGEC^C)|Qpc1@3Z ztA`HKL9-KwtztDJUz#uO|H1Egk|m>%#+FgpPHcj#cL^{X(&br1=Cd5i~G;tg^Q-J2Vb z6vKadph<0m?9r5@+CCZ3+|yIKk2y;zK^Vc*(HeSK8f|KK@#N^ewlLJWDle-Xttu-f zj_ldK^unxsWGOTMxV#D*$5K<439W+>x7GbdoQ!IkeDFa*Bx(`BjC;=0j z#5{)Gm>eHph7DYGCNt!A;zwOhR76vedg3Qd+mGP%$O)Q3+{s_77{lnJ4~4~51(|bY v1>1Ilz_v3@NInKst>>z?|LV)%OYOZ(;gJvTR}o`Vr@;@I*A8MN`>_- zlpIB9kK$20_zS!(2#OH!2lyw{H>oSTJK=qK@0&;F``+Y7{V?!HwVF$CH8;QY-paXu z0p857Z_j`zqF8Jtq9YQ!V^=kgW#V+4#O=6PTT1k3XHD6Wr)15-V|e79 zC&;cT3t9gZ>nVZkx`KVuuKh9!?zN$m_s3a(H0;iQe%h)dmyrc1P&6k?rr0LIW6BHKm9r)2t(;K;DCN0bsi%`Yx7BJD5BVMh#XEj^ z#n5`iE@7mGm)r#(Jdi;DaC$<&(f(im1dAR) z?c{*yW)8&zYj?YWn#I6g$eiUA9q_7ha*hsma=vo#@r!kp&di5O(H)PYq0$TsEex0$ zRg=>VlbP$#XAPLiwyl*%D@8-8-axA4CNFLDW-j5hHHj_PFwzzRuM2RihrYVOsYxZ3 z$K1Aq)u|pf>oW+Y$X<^7!=9$a2YFFcGI?<*uS7y3t0`Ey8r+H diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-310.pyc deleted file mode 100644 index 2d6c31895f4e9fdb9412bd085780434eb905cb28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1283 zcmZuvOK;mo5Z>iW6eZh=W4lTE0MTBo1hx?i2!g;Zia2)BLUD>ZK>)kk3K!?io4q{ce-zO&+avq#X=b>hl3pRG@`nXcf&^1 z^AM-_1C1n4$k|rcxTKfHl+5Uq&MCh&CDNGEA1R|hSrjI)I{=w;=mY-CuF2cT6VUXN_#FH!hjhE?XQ}`7 zL=LmGb@I2C*Sj*%a_wGeQ!IX>>`+8;eB7*ae9%OBLWW$5H?bTlGl5h&46q?kw#buM zs@l=X;j<@So_rB}bEF&rA&-X28SreJ3+0q8s*V5aQJG>Q)H+2r-X+{F46%x}EG0Y( zcxzY|GS;$|FlI3=V6I^V@|bGbYFLZBz#@D#YzrBoZ2lTnAdjiYtA>S%fsrAYp-{6# zU~(v1C8OZv^K3cnY^fEQ#U;g)t=J71*(YbSM{z_6CS~R&7FAB(#qOx50kofoNq|v~ zMSziok%N(ok&lsyiRnKV6VpF7W+p};{Kxc{gM+Dohq*{+vMk3*Eft^^P3Bw7sTHY3 oT0nM@Hi+PX6TBdnDvr##+`I)*`18#w?}03!<{2O}2{ zGBNTnvi##F7$nZd e#KXwNECe)^g}F#&axCXTHf^w?$tqm_jA8)x3pIoQ diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc index 0d6c5c9a1bb0a597925afbf499b68375c1e3d807..7ccebfd0748c5af169b556007fc9ef12a79a3ed1 100644 GIT binary patch delta 1519 zcmZux-HRJl6wjSZCX>lWv)Lq@uT8em3hA!Vt;MpkZiOoNpjNF~NNwY6?w#$_NhX|` zba#swp#=pIDOV7D^g&qYi|ikue?mc@=Cx1aqu^udIX6M$+6?*S&hMP_J0JJn{Mr7o zo%6FZK;;c{RLBU9%MWKKWDca=BM(q8aw@ikRFsrlyC!kH;9s+IBPnQq-VT%K`qzt zJz`E|fCwgD2ox}bCRvtje#;(+QP>ZM(C5Ol46~sw6KaAGZG~fcoPuKn)`!ePj;>RB#DZxoI|EP#qd$8!+wv z>Ip><_V>XJ?OjjwQRGeexmjoDkAE<~VkK3*Dm=BlCr0963_G953)Wp@mRtU6eXzBH zsXE4N5@#sws|1?}kxm^(n!{&#cgR3;a1Nm--%fYfx#RuxOKfWkiB5cBrk9A&V4J)< z2uCc^!T0AKD3RBY{!Bi~bXidrvS+TS4S0tF&Js`=QGzPKogdoa;HC&>bzCO1YRhum z5m);V+(t5>i>1elEW>I{XK+jY@II}nzh2T0x~jrgh+0C3 ztbsoY#X;z~yFdext^CXKPQJk``F*}QrMdR1V|U!`yXXfa+v`q3*9*GpzX39&5f4I$ z^j+WgpoQ;1w=hbA7<+g};XF}vP~j@^an!-%EWs1p4$6Z{uM*3tpgNfA&7qtY^L$Dycoxs_ z>8Dn&CT!B3{;+sl7qfgu6nWu}k(`)cNO(4%=L=|QPJHvCCEA{W7K_(-9W5`7E$d<)RSmv~sw*#WUgFDWxjM0s zZCoslc| zodciVr@ascu5=>*i8!wtNycVW%PiYP95Uq8TjsUK42n8E0`bTX4RbEfm78eX{*@u_;TJzY-szY+1p-_@651l(>JR%_`*~5F^ds&AG|*XF zLw6vch9cC}->IdSV^;Ra1uXTy9;Aq*^B8>T?gqlaB%5k8U1zK3`{~bECGNOMS*Om+V-Qs zAAY1$xL>qOXKYOU(&&+$gR3AVAC6yVjwU;3xPs~5k*D!I_=LXZ4Re<*Rm zg3y)YBYZ%nm^CrDFwXc`o2b+2wL!=a0_{g20tyBg;W@>*h?+22RW#>_7np*Eh%O;6x1=_un_CMwq7+kVftHB{%2tlb zo$o_xe zym36qi4a932CxM~S44Qc{^xtRhKa3lU}ZMG_x5=6|6aqu(bUOlnnKDduUQqQl&xx2)~0U3qv0)ws*ho4};g}6K|S!%*jeXvhJsr|ETx1 zp>LTVTTw8>6dy=>DGgy6C@MMSHI~jAuBm_mN1$;C4k%X%<=ye3WzOkcP=%AqGcB=W zy6nbL9T;2jg@c4!=8`)oP0sBz4JDAWN@`vGx)0ScsF Z-y?k6b32GvrYBU$4U942#7#E$yMH(7Kal_c diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-310.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-310.pyc index 34a219d6ce5f05b39994ece0dde9e87f9d97a880..c2f145b73dd33a84808211a8e20cf42c9de252d6 100644 GIT binary patch delta 2505 zcmZ`*OKcQJ5S^Zxo&B%9AB=5&i*3LQ%JK`Kz{cTYg9*ZXY*3g$Cgbh)?!xTOx@QcS z7+DIIBB5NIk#gbyIRz=ng`BxZIV4h|96ARMIVFeOk{n4@&)PVS7^!QztE;PCRae!_ zx5F>?WZZN*p}_O^Z$HA+Mii=0&51V?W}=xilg*Twl04l> zH#262C`{#Lkcl`-v&-y)J;Us-DKz>8F|%hB8l&+gg~lJKW)4;fnuJx7a5Pn4n}J$3Ekn00D=?9{ol%RdbiL~O#n%=|gt60r+yzu~rQXZf%3lrX%yec;gH zlEyQ^6*9CK1qH`pcq&m8rkI2(rb>ya(VbLdI*TxaMVZm3%&2`zpF(x2&ge8kjirbg zqq`(T-HfvY)md^zl_2#8#7xl?GiVxy&eAgm&CsqT-OSK#*2TJ4^<)=m4%k_mM?