From 431e93578df4a5a33623823bff974d33ecf2b88b Mon Sep 17 00:00:00 2001 From: Tejaspatil06 Date: Sat, 21 Sep 2024 00:35:01 +0530 Subject: [PATCH] solve --- client/__pycache__/split_lib.cpython-312.pyc | Bin 0 -> 6396 bytes client/examples/https_client.py | 2 +- client/solution.py | 104 +- client/split_lib.py | 110 +- client/{mem => tmp}/test.txt | 0 https_server/server.py | 2 +- venv/bin/Activate.ps1 | 247 + venv/bin/activate | 70 + venv/bin/activate.csh | 27 + venv/bin/activate.fish | 69 + venv/bin/flask | 8 + venv/bin/normalizer | 8 + venv/bin/pip | 8 + venv/bin/pip3 | 8 + venv/bin/pip3.12 | 8 + venv/bin/python | 1 + venv/bin/python3 | 1 + venv/bin/python3.12 | 1 + .../MarkupSafe-2.1.5.dist-info/INSTALLER | 1 + .../MarkupSafe-2.1.5.dist-info/LICENSE.rst | 28 + .../MarkupSafe-2.1.5.dist-info/METADATA | 93 + .../MarkupSafe-2.1.5.dist-info/RECORD | 14 + .../MarkupSafe-2.1.5.dist-info/WHEEL | 5 + .../MarkupSafe-2.1.5.dist-info/top_level.txt | 1 + .../blinker-1.8.2.dist-info/INSTALLER | 1 + .../blinker-1.8.2.dist-info/LICENSE.txt | 20 + .../blinker-1.8.2.dist-info/METADATA | 60 + .../blinker-1.8.2.dist-info/RECORD | 12 + .../blinker-1.8.2.dist-info/WHEEL | 4 + .../site-packages/blinker/__init__.py | 60 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1814 bytes .../__pycache__/_utilities.cpython-312.pyc | Bin 0 -> 2736 bytes .../blinker/__pycache__/base.cpython-312.pyc | Bin 0 -> 25428 bytes .../site-packages/blinker/_utilities.py | 64 + .../python3.12/site-packages/blinker/base.py | 621 ++ .../python3.12/site-packages/blinker/py.typed | 0 .../certifi-2024.8.30.dist-info/INSTALLER | 1 + .../certifi-2024.8.30.dist-info/LICENSE | 20 + .../certifi-2024.8.30.dist-info/METADATA | 67 + .../certifi-2024.8.30.dist-info/RECORD | 14 + .../certifi-2024.8.30.dist-info/WHEEL | 5 + .../certifi-2024.8.30.dist-info/top_level.txt | 1 + .../site-packages/certifi/__init__.py | 4 + .../site-packages/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 324 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 639 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 3205 bytes .../site-packages/certifi/cacert.pem | 4929 ++++++++++ .../python3.12/site-packages/certifi/core.py | 114 + .../python3.12/site-packages/certifi/py.typed | 0 .../INSTALLER | 1 + .../LICENSE | 21 + .../METADATA | 683 ++ .../charset_normalizer-3.3.2.dist-info/RECORD | 35 + .../charset_normalizer-3.3.2.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../top_level.txt | 1 + .../charset_normalizer/__init__.py | 46 + .../charset_normalizer/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1743 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 313 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 17323 bytes .../__pycache__/cd.cpython-312.pyc | Bin 0 -> 13452 bytes .../__pycache__/constant.cpython-312.pyc | Bin 0 -> 38770 bytes .../__pycache__/legacy.cpython-312.pyc | Bin 0 -> 2514 bytes .../__pycache__/md.cpython-312.pyc | Bin 0 -> 24517 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 16617 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 14330 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 340 bytes .../site-packages/charset_normalizer/api.py | 626 ++ .../site-packages/charset_normalizer/cd.py | 395 + .../charset_normalizer/cli/__init__.py | 6 + .../charset_normalizer/cli/__main__.py | 296 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 301 bytes .../cli/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 10402 bytes .../charset_normalizer/constant.py | 1995 ++++ .../charset_normalizer/legacy.py | 54 + .../md.cpython-312-darwin.so | Bin 0 -> 50117 bytes .../site-packages/charset_normalizer/md.py | 615 ++ .../md__mypyc.cpython-312-darwin.so | Bin 0 -> 232652 bytes .../charset_normalizer/models.py | 340 + .../site-packages/charset_normalizer/py.typed | 0 .../site-packages/charset_normalizer/utils.py | 421 + .../charset_normalizer/version.py | 6 + .../click-8.1.7.dist-info/INSTALLER | 1 + .../click-8.1.7.dist-info/LICENSE.rst | 28 + .../click-8.1.7.dist-info/METADATA | 103 + .../click-8.1.7.dist-info/RECORD | 39 + .../site-packages/click-8.1.7.dist-info/WHEEL | 5 + .../click-8.1.7.dist-info/top_level.txt | 1 + .../site-packages/click/__init__.py | 73 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2714 bytes .../click/__pycache__/_compat.cpython-312.pyc | Bin 0 -> 27459 bytes .../__pycache__/_termui_impl.cpython-312.pyc | Bin 0 -> 30542 bytes .../__pycache__/_textwrap.cpython-312.pyc | Bin 0 -> 2455 bytes .../__pycache__/_winconsole.cpython-312.pyc | Bin 0 -> 11994 bytes .../click/__pycache__/core.cpython-312.pyc | Bin 0 -> 135539 bytes .../__pycache__/decorators.cpython-312.pyc | Bin 0 -> 23987 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 14750 bytes .../__pycache__/formatting.cpython-312.pyc | Bin 0 -> 14069 bytes .../click/__pycache__/globals.cpython-312.pyc | Bin 0 -> 3134 bytes .../click/__pycache__/parser.cpython-312.pyc | Bin 0 -> 21499 bytes .../shell_completion.cpython-312.pyc | Bin 0 -> 22771 bytes .../click/__pycache__/termui.cpython-312.pyc | Bin 0 -> 32804 bytes .../click/__pycache__/testing.cpython-312.pyc | Bin 0 -> 24576 bytes .../click/__pycache__/types.cpython-312.pyc | Bin 0 -> 49456 bytes .../click/__pycache__/utils.cpython-312.pyc | Bin 0 -> 26306 bytes .../python3.12/site-packages/click/_compat.py | 623 ++ .../site-packages/click/_termui_impl.py | 739 ++ .../site-packages/click/_textwrap.py | 49 + .../site-packages/click/_winconsole.py | 279 + .../python3.12/site-packages/click/core.py | 3042 ++++++ .../site-packages/click/decorators.py | 561 ++ .../site-packages/click/exceptions.py | 288 + .../site-packages/click/formatting.py | 301 + .../python3.12/site-packages/click/globals.py | 68 + .../python3.12/site-packages/click/parser.py | 529 + .../python3.12/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 596 ++ .../python3.12/site-packages/click/termui.py | 784 ++ .../python3.12/site-packages/click/testing.py | 479 + .../python3.12/site-packages/click/types.py | 1089 +++ .../python3.12/site-packages/click/utils.py | 624 ++ .../flask-3.0.3.dist-info/INSTALLER | 1 + .../flask-3.0.3.dist-info/LICENSE.txt | 28 + .../flask-3.0.3.dist-info/METADATA | 101 + .../flask-3.0.3.dist-info/RECORD | 58 + .../flask-3.0.3.dist-info/REQUESTED | 0 .../site-packages/flask-3.0.3.dist-info/WHEEL | 4 + .../flask-3.0.3.dist-info/entry_points.txt | 3 + .../site-packages/flask/__init__.py | 60 + .../site-packages/flask/__main__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2488 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 249 bytes .../flask/__pycache__/app.cpython-312.pyc | Bin 0 -> 61114 bytes .../__pycache__/blueprints.cpython-312.pyc | Bin 0 -> 4903 bytes .../flask/__pycache__/cli.cpython-312.pyc | Bin 0 -> 42264 bytes .../flask/__pycache__/config.cpython-312.pyc | Bin 0 -> 16226 bytes .../flask/__pycache__/ctx.cpython-312.pyc | Bin 0 -> 19840 bytes .../__pycache__/debughelpers.cpython-312.pyc | Bin 0 -> 9140 bytes .../flask/__pycache__/globals.cpython-312.pyc | Bin 0 -> 1873 bytes .../flask/__pycache__/helpers.cpython-312.pyc | Bin 0 -> 24817 bytes .../flask/__pycache__/logging.cpython-312.pyc | Bin 0 -> 3278 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 16322 bytes .../flask/__pycache__/signals.cpython-312.pyc | Bin 0 -> 1230 bytes .../__pycache__/templating.cpython-312.pyc | Bin 0 -> 9915 bytes .../flask/__pycache__/testing.cpython-312.pyc | Bin 0 -> 13688 bytes .../flask/__pycache__/typing.cpython-312.pyc | Bin 0 -> 4285 bytes .../flask/__pycache__/views.cpython-312.pyc | Bin 0 -> 7010 bytes .../__pycache__/wrappers.cpython-312.pyc | Bin 0 -> 6131 bytes .../lib/python3.12/site-packages/flask/app.py | 1498 +++ .../site-packages/flask/blueprints.py | 129 + .../lib/python3.12/site-packages/flask/cli.py | 1109 +++ .../python3.12/site-packages/flask/config.py | 370 + .../lib/python3.12/site-packages/flask/ctx.py | 449 + .../site-packages/flask/debughelpers.py | 178 + .../python3.12/site-packages/flask/globals.py | 51 + .../python3.12/site-packages/flask/helpers.py | 621 ++ .../site-packages/flask/json/__init__.py | 170 + .../json/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6701 bytes .../json/__pycache__/provider.cpython-312.pyc | Bin 0 -> 9268 bytes .../json/__pycache__/tag.cpython-312.pyc | Bin 0 -> 13963 bytes .../site-packages/flask/json/provider.py | 215 + .../site-packages/flask/json/tag.py | 327 + .../python3.12/site-packages/flask/logging.py | 79 + .../python3.12/site-packages/flask/py.typed | 0 .../site-packages/flask/sansio/README.md | 6 + .../sansio/__pycache__/app.cpython-312.pyc | Bin 0 -> 33595 bytes .../__pycache__/blueprints.cpython-312.pyc | Bin 0 -> 31192 bytes .../__pycache__/scaffold.cpython-312.pyc | Bin 0 -> 30497 bytes .../site-packages/flask/sansio/app.py | 964 ++ .../site-packages/flask/sansio/blueprints.py | 632 ++ .../site-packages/flask/sansio/scaffold.py | 801 ++ .../site-packages/flask/sessions.py | 379 + .../python3.12/site-packages/flask/signals.py | 17 + .../site-packages/flask/templating.py | 219 + .../python3.12/site-packages/flask/testing.py | 298 + .../python3.12/site-packages/flask/typing.py | 90 + .../python3.12/site-packages/flask/views.py | 191 + .../site-packages/flask/wrappers.py | 174 + .../idna-3.10.dist-info/INSTALLER | 1 + .../idna-3.10.dist-info/LICENSE.md | 31 + .../idna-3.10.dist-info/METADATA | 250 + .../site-packages/idna-3.10.dist-info/RECORD | 22 + .../site-packages/idna-3.10.dist-info/WHEEL | 4 + .../python3.12/site-packages/idna/__init__.py | 45 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 892 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4982 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 896 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 16127 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99482 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2639 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 223 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158852 bytes .../python3.12/site-packages/idna/codec.py | 122 + .../python3.12/site-packages/idna/compat.py | 15 + .../lib/python3.12/site-packages/idna/core.py | 437 + .../python3.12/site-packages/idna/idnadata.py | 4243 ++++++++ .../site-packages/idna/intranges.py | 57 + .../site-packages/idna/package_data.py | 1 + .../python3.12/site-packages/idna/py.typed | 0 .../site-packages/idna/uts46data.py | 8681 +++++++++++++++++ .../itsdangerous-2.2.0.dist-info/INSTALLER | 1 + .../itsdangerous-2.2.0.dist-info/LICENSE.txt | 28 + .../itsdangerous-2.2.0.dist-info/METADATA | 60 + .../itsdangerous-2.2.0.dist-info/RECORD | 22 + .../itsdangerous-2.2.0.dist-info/WHEEL | 4 + .../site-packages/itsdangerous/__init__.py | 38 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1640 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 1194 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2694 bytes .../__pycache__/exc.cpython-312.pyc | Bin 0 -> 3954 bytes .../__pycache__/serializer.cpython-312.pyc | Bin 0 -> 15422 bytes .../__pycache__/signer.cpython-312.pyc | Bin 0 -> 11299 bytes .../__pycache__/timed.cpython-312.pyc | Bin 0 -> 8743 bytes .../__pycache__/url_safe.cpython-312.pyc | Bin 0 -> 3544 bytes .../site-packages/itsdangerous/_json.py | 18 + .../site-packages/itsdangerous/encoding.py | 54 + .../site-packages/itsdangerous/exc.py | 106 + .../site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 406 + .../site-packages/itsdangerous/signer.py | 266 + .../site-packages/itsdangerous/timed.py | 228 + .../site-packages/itsdangerous/url_safe.py | 83 + .../jinja2-3.1.4.dist-info/INSTALLER | 1 + .../jinja2-3.1.4.dist-info/LICENSE.txt | 28 + .../jinja2-3.1.4.dist-info/METADATA | 76 + .../jinja2-3.1.4.dist-info/RECORD | 57 + .../jinja2-3.1.4.dist-info/WHEEL | 4 + .../jinja2-3.1.4.dist-info/entry_points.txt | 3 + .../site-packages/jinja2/__init__.py | 38 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1665 bytes .../__pycache__/_identifier.cpython-312.pyc | Bin 0 -> 2146 bytes .../__pycache__/async_utils.cpython-312.pyc | Bin 0 -> 4090 bytes .../__pycache__/bccache.cpython-312.pyc | Bin 0 -> 19337 bytes .../__pycache__/compiler.cpython-312.pyc | Bin 0 -> 102270 bytes .../__pycache__/constants.cpython-312.pyc | Bin 0 -> 1568 bytes .../jinja2/__pycache__/debug.cpython-312.pyc | Bin 0 -> 6578 bytes .../__pycache__/defaults.cpython-312.pyc | Bin 0 -> 1618 bytes .../__pycache__/environment.cpython-312.pyc | Bin 0 -> 76714 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7727 bytes .../jinja2/__pycache__/ext.cpython-312.pyc | Bin 0 -> 41880 bytes .../__pycache__/filters.cpython-312.pyc | Bin 0 -> 72032 bytes .../__pycache__/idtracking.cpython-312.pyc | Bin 0 -> 19161 bytes .../jinja2/__pycache__/lexer.cpython-312.pyc | Bin 0 -> 32049 bytes .../__pycache__/loaders.cpython-312.pyc | Bin 0 -> 30975 bytes .../jinja2/__pycache__/meta.cpython-312.pyc | Bin 0 -> 5482 bytes .../__pycache__/nativetypes.cpython-312.pyc | Bin 0 -> 7031 bytes .../jinja2/__pycache__/nodes.cpython-312.pyc | Bin 0 -> 58231 bytes .../__pycache__/optimizer.cpython-312.pyc | Bin 0 -> 2701 bytes .../jinja2/__pycache__/parser.cpython-312.pyc | Bin 0 -> 60823 bytes .../__pycache__/runtime.cpython-312.pyc | Bin 0 -> 48504 bytes .../__pycache__/sandbox.cpython-312.pyc | Bin 0 -> 17902 bytes .../jinja2/__pycache__/tests.cpython-312.pyc | Bin 0 -> 9062 bytes .../jinja2/__pycache__/utils.cpython-312.pyc | Bin 0 -> 34483 bytes .../__pycache__/visitor.cpython-312.pyc | Bin 0 -> 5365 bytes .../site-packages/jinja2/_identifier.py | 6 + .../site-packages/jinja2/async_utils.py | 84 + .../site-packages/jinja2/bccache.py | 408 + .../site-packages/jinja2/compiler.py | 1960 ++++ .../site-packages/jinja2/constants.py | 20 + .../python3.12/site-packages/jinja2/debug.py | 191 + .../site-packages/jinja2/defaults.py | 48 + .../site-packages/jinja2/environment.py | 1675 ++++ .../site-packages/jinja2/exceptions.py | 166 + .../python3.12/site-packages/jinja2/ext.py | 870 ++ .../site-packages/jinja2/filters.py | 1866 ++++ .../site-packages/jinja2/idtracking.py | 318 + .../python3.12/site-packages/jinja2/lexer.py | 868 ++ .../site-packages/jinja2/loaders.py | 667 ++ .../python3.12/site-packages/jinja2/meta.py | 112 + .../site-packages/jinja2/nativetypes.py | 130 + .../python3.12/site-packages/jinja2/nodes.py | 1206 +++ .../site-packages/jinja2/optimizer.py | 48 + .../python3.12/site-packages/jinja2/parser.py | 1041 ++ .../python3.12/site-packages/jinja2/py.typed | 0 .../site-packages/jinja2/runtime.py | 1056 ++ .../site-packages/jinja2/sandbox.py | 429 + .../python3.12/site-packages/jinja2/tests.py | 256 + .../python3.12/site-packages/jinja2/utils.py | 755 ++ .../site-packages/jinja2/visitor.py | 92 + .../site-packages/markupsafe/__init__.py | 332 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 17468 bytes .../__pycache__/_native.cpython-312.pyc | Bin 0 -> 2557 bytes .../site-packages/markupsafe/_native.py | 63 + .../site-packages/markupsafe/_speedups.c | 320 + .../_speedups.cpython-312-darwin.so | Bin 0 -> 117420 bytes .../site-packages/markupsafe/_speedups.pyi | 9 + .../site-packages/markupsafe/py.typed | 0 .../pip-24.2.dist-info/AUTHORS.txt | 796 ++ .../pip-24.2.dist-info/INSTALLER | 1 + .../pip-24.2.dist-info/LICENSE.txt | 20 + .../site-packages/pip-24.2.dist-info/METADATA | 89 + .../site-packages/pip-24.2.dist-info/RECORD | 853 ++ .../pip-24.2.dist-info/REQUESTED | 0 .../site-packages/pip-24.2.dist-info/WHEEL | 5 + .../pip-24.2.dist-info/entry_points.txt | 3 + .../pip-24.2.dist-info/top_level.txt | 1 + .../python3.12/site-packages/pip/__init__.py | 13 + .../python3.12/site-packages/pip/__main__.py | 24 + .../site-packages/pip/__pip-runner__.py | 50 + .../pip/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 702 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 858 bytes .../__pip-runner__.cpython-312.pyc | Bin 0 -> 2222 bytes .../site-packages/pip/_internal/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 804 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 0 -> 14489 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 12684 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 17649 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 35570 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 687 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 0 -> 5135 bytes .../self_outdated_check.cpython-312.pyc | Bin 0 -> 10225 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 0 -> 13636 bytes .../site-packages/pip/_internal/build_env.py | 315 + .../site-packages/pip/_internal/cache.py | 290 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 295 bytes .../autocompletion.cpython-312.pyc | Bin 0 -> 8623 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 0 -> 10213 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 0 -> 30412 bytes .../command_context.cpython-312.pyc | Bin 0 -> 1791 bytes .../__pycache__/index_command.cpython-312.pyc | Bin 0 -> 7141 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 0 -> 2317 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 0 -> 4923 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 0 -> 15030 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 0 -> 3851 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 0 -> 12258 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 0 -> 7850 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 392 bytes .../pip/_internal/cli/autocompletion.py | 176 + .../pip/_internal/cli/base_command.py | 231 + .../pip/_internal/cli/cmdoptions.py | 1075 ++ .../pip/_internal/cli/command_context.py | 27 + .../pip/_internal/cli/index_command.py | 170 + .../site-packages/pip/_internal/cli/main.py | 80 + .../pip/_internal/cli/main_parser.py | 134 + .../site-packages/pip/_internal/cli/parser.py | 294 + .../pip/_internal/cli/progress_bars.py | 94 + .../pip/_internal/cli/req_command.py | 329 + .../pip/_internal/cli/spinners.py | 159 + .../pip/_internal/cli/status_codes.py | 6 + .../pip/_internal/commands/__init__.py | 132 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4019 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 9718 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 2609 bytes .../__pycache__/completion.cpython-312.pyc | Bin 0 -> 5210 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 13180 bytes .../__pycache__/debug.cpython-312.pyc | Bin 0 -> 10085 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 7520 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 4402 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 0 -> 2985 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 0 -> 1690 bytes .../__pycache__/index.cpython-312.pyc | Bin 0 -> 6688 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 0 -> 3997 bytes .../__pycache__/install.cpython-312.pyc | Bin 0 -> 29131 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 0 -> 15774 bytes .../__pycache__/search.cpython-312.pyc | Bin 0 -> 7535 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 0 -> 10494 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 0 -> 4726 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 8882 bytes .../pip/_internal/commands/cache.py | 225 + .../pip/_internal/commands/check.py | 67 + .../pip/_internal/commands/completion.py | 130 + .../pip/_internal/commands/configuration.py | 280 + .../pip/_internal/commands/debug.py | 201 + .../pip/_internal/commands/download.py | 146 + .../pip/_internal/commands/freeze.py | 109 + .../pip/_internal/commands/hash.py | 59 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/index.py | 139 + .../pip/_internal/commands/inspect.py | 92 + .../pip/_internal/commands/install.py | 783 ++ .../pip/_internal/commands/list.py | 375 + .../pip/_internal/commands/search.py | 172 + .../pip/_internal/commands/show.py | 217 + .../pip/_internal/commands/uninstall.py | 114 + .../pip/_internal/commands/wheel.py | 182 + .../pip/_internal/configuration.py | 383 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 958 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 2910 bytes .../__pycache__/installed.cpython-312.pyc | Bin 0 -> 1717 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 0 -> 8456 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 2298 bytes .../pip/_internal/distributions/base.py | 53 + .../pip/_internal/distributions/installed.py | 29 + .../pip/_internal/distributions/sdist.py | 158 + .../pip/_internal/distributions/wheel.py | 42 + .../site-packages/pip/_internal/exceptions.py | 777 ++ .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 249 bytes .../__pycache__/collector.cpython-312.pyc | Bin 0 -> 21634 bytes .../package_finder.cpython-312.pyc | Bin 0 -> 40665 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 0 -> 12605 bytes .../pip/_internal/index/collector.py | 494 + .../pip/_internal/index/package_finder.py | 1020 ++ .../pip/_internal/index/sources.py | 285 + .../pip/_internal/locations/__init__.py | 456 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 16457 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 0 -> 6869 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 0 -> 8045 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3798 bytes .../pip/_internal/locations/_distutils.py | 172 + .../pip/_internal/locations/_sysconfig.py | 214 + .../pip/_internal/locations/base.py | 81 + .../site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 128 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5893 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 2943 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 0 -> 35215 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 0 -> 16101 bytes .../pip/_internal/metadata/_json.py | 84 + .../pip/_internal/metadata/base.py | 688 ++ .../_internal/metadata/importlib/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 375 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 4508 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 0 -> 12582 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 0 -> 11096 bytes .../_internal/metadata/importlib/_compat.py | 85 + .../_internal/metadata/importlib/_dists.py | 221 + .../pip/_internal/metadata/importlib/_envs.py | 189 + .../pip/_internal/metadata/pkg_resources.py | 301 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 283 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 0 -> 1621 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 0 -> 10861 bytes .../format_control.cpython-312.pyc | Bin 0 -> 4240 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 0 -> 1711 bytes .../installation_report.cpython-312.pyc | Bin 0 -> 2294 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 0 -> 26634 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 0 -> 1040 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 0 -> 5004 bytes .../selection_prefs.cpython-312.pyc | Bin 0 -> 1868 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 0 -> 4970 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5777 bytes .../pip/_internal/models/candidate.py | 25 + .../pip/_internal/models/direct_url.py | 224 + .../pip/_internal/models/format_control.py | 78 + .../pip/_internal/models/index.py | 28 + .../_internal/models/installation_report.py | 56 + .../pip/_internal/models/link.py | 590 ++ .../pip/_internal/models/scheme.py | 25 + .../pip/_internal/models/search_scope.py | 127 + .../pip/_internal/models/selection_prefs.py | 53 + .../pip/_internal/models/target_python.py | 121 + .../pip/_internal/models/wheel.py | 93 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 271 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 0 -> 22116 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 0 -> 6477 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 8496 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 0 -> 11634 bytes .../__pycache__/session.cpython-312.pyc | Bin 0 -> 18891 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2272 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 0 -> 2966 bytes .../pip/_internal/network/auth.py | 566 ++ .../pip/_internal/network/cache.py | 106 + .../pip/_internal/network/download.py | 187 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 522 + .../pip/_internal/network/utils.py | 98 + .../pip/_internal/network/xmlrpc.py | 62 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 214 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 7121 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 10145 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 0 -> 25808 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 220 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 0 -> 7684 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 1874 bytes .../metadata_editable.cpython-312.pyc | Bin 0 -> 1908 bytes .../metadata_legacy.cpython-312.pyc | Bin 0 -> 3028 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1694 bytes .../wheel_editable.cpython-312.pyc | Bin 0 -> 2035 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 0 -> 3867 bytes .../operations/build/build_tracker.py | 138 + .../_internal/operations/build/metadata.py | 39 + .../operations/build/metadata_editable.py | 41 + .../operations/build/metadata_legacy.py | 74 + .../pip/_internal/operations/build/wheel.py | 37 + .../operations/build/wheel_editable.py | 46 + .../operations/build/wheel_legacy.py | 102 + .../pip/_internal/operations/check.py | 181 + .../pip/_internal/operations/freeze.py | 258 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 283 bytes .../editable_legacy.cpython-312.pyc | Bin 0 -> 1815 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 34122 bytes .../operations/install/editable_legacy.py | 47 + .../pip/_internal/operations/install/wheel.py | 741 ++ .../pip/_internal/operations/prepare.py | 732 ++ .../site-packages/pip/_internal/pyproject.py | 185 + .../pip/_internal/req/__init__.py | 90 + .../req/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3462 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 0 -> 21237 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 0 -> 21449 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 0 -> 38501 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 0 -> 5500 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 0 -> 32111 bytes .../pip/_internal/req/constructors.py | 560 ++ .../pip/_internal/req/req_file.py | 551 ++ .../pip/_internal/req/req_install.py | 934 ++ .../pip/_internal/req/req_set.py | 82 + .../pip/_internal/req/req_uninstall.py | 633 ++ .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 214 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 1202 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 221 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 22596 bytes .../_internal/resolution/legacy/resolver.py | 597 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 225 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 8166 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 0 -> 29189 bytes .../__pycache__/factory.cpython-312.pyc | Bin 0 -> 32303 bytes .../found_candidates.cpython-312.pyc | Bin 0 -> 6810 bytes .../__pycache__/provider.cpython-312.pyc | Bin 0 -> 10540 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 0 -> 5057 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 15373 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 12331 bytes .../_internal/resolution/resolvelib/base.py | 139 + .../resolution/resolvelib/candidates.py | 569 ++ .../resolution/resolvelib/factory.py | 817 ++ .../resolution/resolvelib/found_candidates.py | 174 + .../resolution/resolvelib/provider.py | 258 + .../resolution/resolvelib/reporter.py | 81 + .../resolution/resolvelib/requirements.py | 245 + .../resolution/resolvelib/resolver.py | 317 + .../pip/_internal/self_outdated_check.py | 244 + .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 209 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 0 -> 4544 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 0 -> 1880 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 0 -> 2424 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 0 -> 2921 bytes .../compatibility_tags.cpython-312.pyc | Bin 0 -> 5577 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 698 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 0 -> 4205 bytes .../direct_url_helpers.cpython-312.pyc | Bin 0 -> 3550 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 0 -> 3220 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2162 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 0 -> 4007 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 0 -> 7343 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 0 -> 1178 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 0 -> 2433 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 0 -> 7622 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13572 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 0 -> 33565 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 0 -> 2597 bytes .../utils/__pycache__/retry.cpython-312.pyc | Bin 0 -> 2122 bytes .../setuptools_build.cpython-312.pyc | Bin 0 -> 4564 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 0 -> 8653 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 0 -> 12038 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 0 -> 13512 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 0 -> 2091 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 0 -> 4485 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5917 bytes .../pip/_internal/utils/_jaraco_text.py | 109 + .../site-packages/pip/_internal/utils/_log.py | 38 + .../pip/_internal/utils/appdirs.py | 52 + .../pip/_internal/utils/compat.py | 79 + .../pip/_internal/utils/compatibility_tags.py | 165 + .../pip/_internal/utils/datetime.py | 11 + .../pip/_internal/utils/deprecation.py | 124 + .../pip/_internal/utils/direct_url_helpers.py | 87 + .../pip/_internal/utils/egg_link.py | 80 + .../pip/_internal/utils/encoding.py | 36 + .../pip/_internal/utils/entrypoints.py | 84 + .../pip/_internal/utils/filesystem.py | 149 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 101 + .../pip/_internal/utils/hashes.py | 147 + .../pip/_internal/utils/logging.py | 347 + .../site-packages/pip/_internal/utils/misc.py | 777 ++ .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/retry.py | 42 + .../pip/_internal/utils/setuptools_build.py | 146 + .../pip/_internal/utils/subprocess.py | 245 + .../pip/_internal/utils/temp_dir.py | 296 + .../pip/_internal/utils/unpacking.py | 337 + .../site-packages/pip/_internal/utils/urls.py | 55 + .../pip/_internal/utils/virtualenv.py | 104 + .../pip/_internal/utils/wheel.py | 134 + .../pip/_internal/vcs/__init__.py | 15 + .../vcs/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 548 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 0 -> 5069 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 0 -> 19034 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 0 -> 7622 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 0 -> 12541 bytes .../versioncontrol.cpython-312.pyc | Bin 0 -> 29014 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../site-packages/pip/_internal/vcs/git.py | 527 + .../pip/_internal/vcs/mercurial.py | 163 + .../pip/_internal/vcs/subversion.py | 324 + .../pip/_internal/vcs/versioncontrol.py | 688 ++ .../pip/_internal/wheel_builder.py | 354 + .../site-packages/pip/_vendor/__init__.py | 116 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4567 bytes .../typing_extensions.cpython-312.pyc | Bin 0 -> 139469 bytes .../pip/_vendor/cachecontrol/__init__.py | 28 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 920 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 0 -> 2664 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 0 -> 6482 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 3805 bytes .../__pycache__/controller.cpython-312.pyc | Bin 0 -> 16242 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 0 -> 4365 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 0 -> 6712 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 0 -> 5279 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 0 -> 1692 bytes .../pip/_vendor/cachecontrol/_cmd.py | 70 + .../pip/_vendor/cachecontrol/adapter.py | 161 + .../pip/_vendor/cachecontrol/cache.py | 74 + .../_vendor/cachecontrol/caches/__init__.py | 8 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 453 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 0 -> 7786 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 0 -> 2751 bytes .../_vendor/cachecontrol/caches/file_cache.py | 182 + .../cachecontrol/caches/redis_cache.py | 48 + .../pip/_vendor/cachecontrol/controller.py | 499 + .../pip/_vendor/cachecontrol/filewrapper.py | 119 + .../pip/_vendor/cachecontrol/heuristics.py | 154 + .../pip/_vendor/cachecontrol/py.typed | 0 .../pip/_vendor/cachecontrol/serialize.py | 146 + .../pip/_vendor/cachecontrol/wrapper.py | 43 + .../pip/_vendor/certifi/__init__.py | 4 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 336 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 663 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 3234 bytes .../pip/_vendor/certifi/cacert.pem | 4798 +++++++++ .../site-packages/pip/_vendor/certifi/core.py | 114 + .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/distlib/__init__.py | 33 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1287 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 45549 bytes .../__pycache__/database.cpython-312.pyc | Bin 0 -> 65703 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 0 -> 24334 bytes .../__pycache__/locators.cpython-312.pyc | Bin 0 -> 59948 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 0 -> 15094 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 7696 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 41684 bytes .../__pycache__/resources.cpython-312.pyc | Bin 0 -> 17335 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 0 -> 19792 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 0 -> 88035 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 30363 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 51472 bytes .../pip/_vendor/distlib/compat.py | 1138 +++ .../pip/_vendor/distlib/database.py | 1359 +++ .../pip/_vendor/distlib/index.py | 508 + .../pip/_vendor/distlib/locators.py | 1303 +++ .../pip/_vendor/distlib/manifest.py | 384 + .../pip/_vendor/distlib/markers.py | 167 + .../pip/_vendor/distlib/metadata.py | 1068 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 466 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 97792 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 182784 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 108032 bytes .../site-packages/pip/_vendor/distlib/util.py | 2025 ++++ .../pip/_vendor/distlib/version.py | 751 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 91648 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 168448 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 101888 bytes .../pip/_vendor/distlib/wheel.py | 1099 +++ .../pip/_vendor/distro/__init__.py | 54 + .../pip/_vendor/distro/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 978 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 310 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 0 -> 53826 bytes .../pip/_vendor/distro/distro.py | 1403 +++ .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 899 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4994 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 905 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 15809 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99494 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2651 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 234 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158866 bytes .../site-packages/pip/_vendor/idna/codec.py | 118 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 395 + .../pip/_vendor/idna/idnadata.py | 4245 ++++++++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 8598 ++++++++++++++++ .../pip/_vendor/msgpack/__init__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1759 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 2043 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 0 -> 8188 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 0 -> 42061 bytes .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 168 + .../pip/_vendor/msgpack/fallback.py | 951 ++ .../pip/_vendor/packaging/__init__.py | 15 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 576 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 0 -> 4985 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 9713 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 4572 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 14003 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3259 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 0 -> 7933 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 11029 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 24971 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 4428 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 38757 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 21362 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 7359 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19525 bytes .../pip/_vendor/packaging/_elffile.py | 110 + .../pip/_vendor/packaging/_manylinux.py | 262 + .../pip/_vendor/packaging/_musllinux.py | 85 + .../pip/_vendor/packaging/_parser.py | 354 + .../pip/_vendor/packaging/_structures.py | 61 + .../pip/_vendor/packaging/_tokenizer.py | 194 + .../pip/_vendor/packaging/markers.py | 325 + .../pip/_vendor/packaging/metadata.py | 804 ++ .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 91 + .../pip/_vendor/packaging/specifiers.py | 1009 ++ .../pip/_vendor/packaging/tags.py | 568 ++ .../pip/_vendor/packaging/utils.py | 174 + .../pip/_vendor/packaging/version.py | 563 ++ .../pip/_vendor/pkg_resources/__init__.py | 3676 +++++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 161299 bytes .../pip/_vendor/platformdirs/__init__.py | 627 ++ .../pip/_vendor/platformdirs/__main__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19847 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 1966 bytes .../__pycache__/android.cpython-312.pyc | Bin 0 -> 10715 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 12929 bytes .../__pycache__/macos.cpython-312.pyc | Bin 0 -> 8025 bytes .../__pycache__/unix.cpython-312.pyc | Bin 0 -> 15055 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 615 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 13692 bytes .../pip/_vendor/platformdirs/android.py | 249 + .../pip/_vendor/platformdirs/api.py | 292 + .../pip/_vendor/platformdirs/macos.py | 130 + .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 275 + .../pip/_vendor/platformdirs/version.py | 16 + .../pip/_vendor/platformdirs/windows.py | 272 + .../pip/_vendor/pygments/__init__.py | 82 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3507 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 753 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 0 -> 26603 bytes .../__pycache__/console.cpython-312.pyc | Bin 0 -> 2647 bytes .../__pycache__/filter.cpython-312.pyc | Bin 0 -> 3240 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 0 -> 4739 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 38380 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 0 -> 1578 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 0 -> 2627 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 0 -> 4096 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 0 -> 4775 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 0 -> 12117 bytes .../__pycache__/style.cpython-312.pyc | Bin 0 -> 6712 bytes .../__pycache__/token.cpython-312.pyc | Bin 0 -> 8208 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 0 -> 32991 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 0 -> 14088 bytes .../pip/_vendor/pygments/cmdline.py | 668 ++ .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 70 + .../pip/_vendor/pygments/filters/__init__.py | 940 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 37930 bytes .../pip/_vendor/pygments/formatter.py | 129 + .../_vendor/pygments/formatters/__init__.py | 157 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6921 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 4234 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 0 -> 4241 bytes .../__pycache__/groff.cpython-312.pyc | Bin 0 -> 7312 bytes .../__pycache__/html.cpython-312.pyc | Bin 0 -> 41045 bytes .../__pycache__/img.cpython-312.pyc | Bin 0 -> 28567 bytes .../__pycache__/irc.cpython-312.pyc | Bin 0 -> 6074 bytes .../__pycache__/latex.cpython-312.pyc | Bin 0 -> 20144 bytes .../__pycache__/other.cpython-312.pyc | Bin 0 -> 6896 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 0 -> 2977 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 0 -> 13792 bytes .../__pycache__/svg.cpython-312.pyc | Bin 0 -> 9158 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 0 -> 5838 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 0 -> 15137 bytes .../_vendor/pygments/formatters/_mapping.py | 23 + .../pip/_vendor/pygments/formatters/bbcode.py | 108 + .../pip/_vendor/pygments/formatters/groff.py | 170 + .../pip/_vendor/pygments/formatters/html.py | 987 ++ .../pip/_vendor/pygments/formatters/img.py | 685 ++ .../pip/_vendor/pygments/formatters/irc.py | 154 + .../pip/_vendor/pygments/formatters/latex.py | 518 + .../pip/_vendor/pygments/formatters/other.py | 160 + .../pygments/formatters/pangomarkup.py | 83 + .../pip/_vendor/pygments/formatters/rtf.py | 349 + .../pip/_vendor/pygments/formatters/svg.py | 185 + .../_vendor/pygments/formatters/terminal.py | 127 + .../pygments/formatters/terminal256.py | 338 + .../pip/_vendor/pygments/lexer.py | 963 ++ .../pip/_vendor/pygments/lexers/__init__.py | 362 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 14640 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 68282 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 0 -> 42986 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 589 ++ .../pip/_vendor/pygments/lexers/python.py | 1198 +++ .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 72 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 247 + .../pip/_vendor/pygments/style.py | 203 + .../pip/_vendor/pygments/styles/__init__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2683 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 3667 bytes .../pip/_vendor/pygments/styles/_mapping.py | 54 + .../pip/_vendor/pygments/token.py | 214 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 324 + .../pip/_vendor/pyproject_hooks/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 632 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 393 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 0 -> 14719 bytes .../pip/_vendor/pyproject_hooks/_compat.py | 8 + .../pip/_vendor/pyproject_hooks/_impl.py | 330 + .../pyproject_hooks/_in_process/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1099 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 0 -> 14377 bytes .../_in_process/_in_process.py | 353 + .../pip/_vendor/requests/__init__.py | 179 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5272 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 603 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2043 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 28450 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7217 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13940 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 941 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 1696 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25217 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7617 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4247 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1070 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35447 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1285 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27865 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6042 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5642 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36385 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 50 + .../pip/_vendor/requests/adapters.py | 719 ++ .../site-packages/pip/_vendor/requests/api.py | 157 + .../pip/_vendor/requests/auth.py | 314 + .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/compat.py | 78 + .../pip/_vendor/requests/cookies.py | 561 ++ .../pip/_vendor/requests/exceptions.py | 151 + .../pip/_vendor/requests/help.py | 127 + .../pip/_vendor/requests/hooks.py | 33 + .../pip/_vendor/requests/models.py | 1037 ++ .../pip/_vendor/requests/packages.py | 25 + .../pip/_vendor/requests/sessions.py | 831 ++ .../pip/_vendor/requests/status_codes.py | 128 + .../pip/_vendor/requests/structures.py | 99 + .../pip/_vendor/requests/utils.py | 1096 +++ .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 653 bytes .../__pycache__/providers.cpython-312.pyc | Bin 0 -> 6870 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 0 -> 2673 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 0 -> 25899 bytes .../__pycache__/structs.cpython-312.pyc | Bin 0 -> 10519 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 219 bytes .../collections_abc.cpython-312.pyc | Bin 0 -> 439 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/py.typed | 0 .../pip/_vendor/resolvelib/reporters.py | 43 + .../pip/_vendor/resolvelib/resolvers.py | 547 ++ .../pip/_vendor/resolvelib/structs.py | 170 + .../pip/_vendor/rich/__init__.py | 177 + .../pip/_vendor/rich/__main__.py | 273 + .../rich/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7034 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 10311 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 0 -> 7891 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 0 -> 205995 bytes .../_emoji_replace.cpython-312.pyc | Bin 0 -> 1748 bytes .../_export_format.cpython-312.pyc | Bin 0 -> 2368 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 0 -> 556 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 0 -> 874 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 0 -> 12092 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 0 -> 4166 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 0 -> 1889 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 0 -> 3639 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 0 -> 5179 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 0 -> 740 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 0 -> 6589 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 0 -> 13198 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 0 -> 984 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 0 -> 884 bytes .../_win32_console.cpython-312.pyc | Bin 0 -> 28995 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 0 -> 2509 bytes .../_windows_renderer.cpython-312.pyc | Bin 0 -> 3582 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 0 -> 3345 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 0 -> 1627 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 0 -> 12306 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 9085 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 0 -> 4291 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 0 -> 11857 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 0 -> 5829 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 0 -> 26588 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 0 -> 1720 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 0 -> 8603 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 0 -> 113460 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 0 -> 2277 bytes .../__pycache__/containers.cpython-312.pyc | Bin 0 -> 9229 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 0 -> 10960 bytes .../default_styles.cpython-312.pyc | Bin 0 -> 10385 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 0 -> 1507 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 0 -> 4231 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1864 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 0 -> 3590 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 0 -> 3091 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 0 -> 9906 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 0 -> 6054 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 0 -> 5227 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 0 -> 20177 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 0 -> 19034 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 0 -> 4908 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13573 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 0 -> 9586 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 0 -> 6397 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 0 -> 7143 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 0 -> 1830 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 0 -> 5316 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 0 -> 12202 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 0 -> 40166 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 0 -> 74992 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 0 -> 10396 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 0 -> 14806 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1811 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 0 -> 586 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 0 -> 6632 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 0 -> 6587 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 0 -> 3844 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 0 -> 2498 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 0 -> 28134 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 0 -> 6083 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 0 -> 6080 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 0 -> 33519 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 0 -> 2158 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 0 -> 39967 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 0 -> 43558 bytes .../terminal_theme.cpython-312.pyc | Bin 0 -> 3367 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 0 -> 60868 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 0 -> 6361 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 0 -> 333 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 0 -> 31530 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 0 -> 11455 bytes .../pip/_vendor/rich/_cell_widths.py | 454 + .../pip/_vendor/rich/_emoji_codes.py | 3610 +++++++ .../pip/_vendor/rich/_emoji_replace.py | 32 + .../pip/_vendor/rich/_export_format.py | 76 + .../pip/_vendor/rich/_extension.py | 10 + .../site-packages/pip/_vendor/rich/_fileno.py | 24 + .../pip/_vendor/rich/_inspect.py | 270 + .../pip/_vendor/rich/_log_render.py | 94 + .../site-packages/pip/_vendor/rich/_loop.py | 43 + .../pip/_vendor/rich/_null_file.py | 69 + .../pip/_vendor/rich/_palettes.py | 309 + .../site-packages/pip/_vendor/rich/_pick.py | 17 + .../site-packages/pip/_vendor/rich/_ratio.py | 159 + .../pip/_vendor/rich/_spinners.py | 482 + .../site-packages/pip/_vendor/rich/_stack.py | 16 + .../site-packages/pip/_vendor/rich/_timer.py | 19 + .../pip/_vendor/rich/_win32_console.py | 662 ++ .../pip/_vendor/rich/_windows.py | 71 + .../pip/_vendor/rich/_windows_renderer.py | 56 + .../site-packages/pip/_vendor/rich/_wrap.py | 93 + .../site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 311 + .../site-packages/pip/_vendor/rich/ansi.py | 240 + .../site-packages/pip/_vendor/rich/bar.py | 93 + .../site-packages/pip/_vendor/rich/box.py | 480 + .../site-packages/pip/_vendor/rich/cells.py | 167 + .../site-packages/pip/_vendor/rich/color.py | 621 ++ .../pip/_vendor/rich/color_triplet.py | 38 + .../site-packages/pip/_vendor/rich/columns.py | 187 + .../site-packages/pip/_vendor/rich/console.py | 2633 +++++ .../pip/_vendor/rich/constrain.py | 37 + .../pip/_vendor/rich/containers.py | 167 + .../site-packages/pip/_vendor/rich/control.py | 225 + .../pip/_vendor/rich/default_styles.py | 190 + .../pip/_vendor/rich/diagnose.py | 37 + .../site-packages/pip/_vendor/rich/emoji.py | 96 + .../site-packages/pip/_vendor/rich/errors.py | 34 + .../pip/_vendor/rich/file_proxy.py | 57 + .../pip/_vendor/rich/filesize.py | 89 + .../pip/_vendor/rich/highlighter.py | 232 + .../site-packages/pip/_vendor/rich/json.py | 139 + .../site-packages/pip/_vendor/rich/jupyter.py | 101 + .../site-packages/pip/_vendor/rich/layout.py | 442 + .../site-packages/pip/_vendor/rich/live.py | 375 + .../pip/_vendor/rich/live_render.py | 112 + .../site-packages/pip/_vendor/rich/logging.py | 289 + .../site-packages/pip/_vendor/rich/markup.py | 251 + .../site-packages/pip/_vendor/rich/measure.py | 151 + .../site-packages/pip/_vendor/rich/padding.py | 141 + .../site-packages/pip/_vendor/rich/pager.py | 34 + .../site-packages/pip/_vendor/rich/palette.py | 100 + .../site-packages/pip/_vendor/rich/panel.py | 312 + .../site-packages/pip/_vendor/rich/pretty.py | 995 ++ .../pip/_vendor/rich/progress.py | 1699 ++++ .../pip/_vendor/rich/progress_bar.py | 223 + .../site-packages/pip/_vendor/rich/prompt.py | 375 + .../pip/_vendor/rich/protocol.py | 42 + .../site-packages/pip/_vendor/rich/py.typed | 0 .../site-packages/pip/_vendor/rich/region.py | 10 + .../site-packages/pip/_vendor/rich/repr.py | 149 + .../site-packages/pip/_vendor/rich/rule.py | 130 + .../site-packages/pip/_vendor/rich/scope.py | 86 + .../site-packages/pip/_vendor/rich/screen.py | 54 + .../site-packages/pip/_vendor/rich/segment.py | 738 ++ .../site-packages/pip/_vendor/rich/spinner.py | 137 + .../site-packages/pip/_vendor/rich/status.py | 131 + .../site-packages/pip/_vendor/rich/style.py | 796 ++ .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 958 ++ .../site-packages/pip/_vendor/rich/table.py | 1000 ++ .../pip/_vendor/rich/terminal_theme.py | 153 + .../site-packages/pip/_vendor/rich/text.py | 1357 +++ .../site-packages/pip/_vendor/rich/theme.py | 115 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 753 ++ .../site-packages/pip/_vendor/rich/tree.py | 249 + .../pip/_vendor/tomli/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 403 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 0 -> 26918 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 0 -> 3927 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 0 -> 385 bytes .../pip/_vendor/tomli/_parser.py | 691 ++ .../site-packages/pip/_vendor/tomli/_re.py | 107 + .../site-packages/pip/_vendor/tomli/_types.py | 10 + .../site-packages/pip/_vendor/tomli/py.typed | 1 + .../pip/_vendor/truststore/__init__.py | 13 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 637 bytes .../__pycache__/_api.cpython-312.pyc | Bin 0 -> 16559 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 0 -> 16591 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 0 -> 2224 bytes .../_ssl_constants.cpython-312.pyc | Bin 0 -> 1118 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 0 -> 15759 bytes .../pip/_vendor/truststore/_api.py | 313 + .../pip/_vendor/truststore/_macos.py | 499 + .../pip/_vendor/truststore/_openssl.py | 66 + .../pip/_vendor/truststore/_ssl_constants.py | 31 + .../pip/_vendor/truststore/_windows.py | 564 ++ .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/typing_extensions.py | 3641 +++++++ .../pip/_vendor/urllib3/__init__.py | 102 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3424 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 16398 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 237 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 20422 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 36456 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 13512 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 10421 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 4031 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 20451 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 7313 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 33966 bytes .../pip/_vendor/urllib3/_collections.py | 355 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 572 ++ .../pip/_vendor/urllib3/connectionpool.py | 1137 +++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 217 bytes .../_appengine_environ.cpython-312.pyc | Bin 0 -> 1867 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 0 -> 11583 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 0 -> 5733 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 24467 bytes .../securetransport.cpython-312.pyc | Bin 0 -> 35524 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 7530 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 234 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 0 -> 17446 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 0 -> 14782 bytes .../contrib/_securetransport/bindings.py | 519 + .../contrib/_securetransport/low_level.py | 397 + .../pip/_vendor/urllib3/contrib/appengine.py | 314 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 518 + .../urllib3/contrib/securetransport.py | 920 ++ .../pip/_vendor/urllib3/contrib/socks.py | 216 + .../pip/_vendor/urllib3/exceptions.py | 323 + .../pip/_vendor/urllib3/fields.py | 274 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 218 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 0 -> 41274 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 228 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 0 -> 1844 bytes .../weakref_finalize.cpython-312.pyc | Bin 0 -> 7355 bytes .../urllib3/packages/backports/makefile.py | 51 + .../packages/backports/weakref_finalize.py | 155 + .../pip/_vendor/urllib3/packages/six.py | 1076 ++ .../pip/_vendor/urllib3/poolmanager.py | 540 + .../pip/_vendor/urllib3/request.py | 191 + .../pip/_vendor/urllib3/response.py | 879 ++ .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1165 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4766 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1571 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 0 -> 1371 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 4202 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 3011 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 21720 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 15105 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5070 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 10772 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11158 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 15804 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 4422 bytes .../pip/_vendor/urllib3/util/connection.py | 149 + .../pip/_vendor/urllib3/util/proxy.py | 57 + .../pip/_vendor/urllib3/util/queue.py | 22 + .../pip/_vendor/urllib3/util/request.py | 137 + .../pip/_vendor/urllib3/util/response.py | 107 + .../pip/_vendor/urllib3/util/retry.py | 620 ++ .../pip/_vendor/urllib3/util/ssl_.py | 495 + .../urllib3/util/ssl_match_hostname.py | 159 + .../pip/_vendor/urllib3/util/ssltransport.py | 221 + .../pip/_vendor/urllib3/util/timeout.py | 271 + .../pip/_vendor/urllib3/util/url.py | 435 + .../pip/_vendor/urllib3/util/wait.py | 152 + .../site-packages/pip/_vendor/vendor.txt | 18 + .../lib/python3.12/site-packages/pip/py.typed | 4 + .../requests-2.32.3.dist-info/INSTALLER | 1 + .../requests-2.32.3.dist-info/LICENSE | 175 + .../requests-2.32.3.dist-info/METADATA | 119 + .../requests-2.32.3.dist-info/RECORD | 43 + .../requests-2.32.3.dist-info/REQUESTED | 0 .../requests-2.32.3.dist-info/WHEEL | 5 + .../requests-2.32.3.dist-info/top_level.txt | 1 + .../site-packages/requests/__init__.py | 184 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5427 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 591 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2031 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 28365 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7205 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13928 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 673 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 2087 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25205 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7592 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4334 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1058 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35363 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1125 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27853 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6030 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5630 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36361 bytes .../site-packages/requests/__version__.py | 14 + .../site-packages/requests/_internal_utils.py | 50 + .../site-packages/requests/adapters.py | 719 ++ .../python3.12/site-packages/requests/api.py | 157 + .../python3.12/site-packages/requests/auth.py | 314 + .../site-packages/requests/certs.py | 17 + .../site-packages/requests/compat.py | 94 + .../site-packages/requests/cookies.py | 561 ++ .../site-packages/requests/exceptions.py | 151 + .../python3.12/site-packages/requests/help.py | 134 + .../site-packages/requests/hooks.py | 33 + .../site-packages/requests/models.py | 1037 ++ .../site-packages/requests/packages.py | 23 + .../site-packages/requests/sessions.py | 831 ++ .../site-packages/requests/status_codes.py | 128 + .../site-packages/requests/structures.py | 99 + .../site-packages/requests/utils.py | 1096 +++ .../urllib3-2.2.3.dist-info/INSTALLER | 1 + .../urllib3-2.2.3.dist-info/METADATA | 155 + .../urllib3-2.2.3.dist-info/RECORD | 79 + .../urllib3-2.2.3.dist-info/WHEEL | 4 + .../licenses/LICENSE.txt | 21 + .../site-packages/urllib3/__init__.py | 211 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7322 bytes .../_base_connection.cpython-312.pyc | Bin 0 -> 6869 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 22626 bytes .../_request_methods.cpython-312.pyc | Bin 0 -> 10638 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 599 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 35752 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 39750 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 15844 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 12066 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 3515 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 24046 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 50459 bytes .../site-packages/urllib3/_base_connection.py | 172 + .../site-packages/urllib3/_collections.py | 483 + .../site-packages/urllib3/_request_methods.py | 278 + .../site-packages/urllib3/_version.py | 16 + .../site-packages/urllib3/connection.py | 1033 ++ .../site-packages/urllib3/connectionpool.py | 1182 +++ .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 205 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 27286 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 8183 bytes .../urllib3/contrib/emscripten/__init__.py | 16 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 913 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 10247 bytes .../__pycache__/fetch.cpython-312.pyc | Bin 0 -> 18383 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 1433 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 12717 bytes .../urllib3/contrib/emscripten/connection.py | 254 + .../emscripten/emscripten_fetch_worker.js | 110 + .../urllib3/contrib/emscripten/fetch.py | 418 + .../urllib3/contrib/emscripten/request.py | 22 + .../urllib3/contrib/emscripten/response.py | 285 + .../urllib3/contrib/pyopenssl.py | 552 ++ .../site-packages/urllib3/contrib/socks.py | 228 + .../site-packages/urllib3/exceptions.py | 321 + .../site-packages/urllib3/fields.py | 341 + .../site-packages/urllib3/filepost.py | 89 + .../site-packages/urllib3/http2/__init__.py | 53 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1758 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 16982 bytes .../http2/__pycache__/probe.cpython-312.pyc | Bin 0 -> 3677 bytes .../site-packages/urllib3/http2/connection.py | 356 + .../site-packages/urllib3/http2/probe.py | 87 + .../site-packages/urllib3/poolmanager.py | 637 ++ .../python3.12/site-packages/urllib3/py.typed | 2 + .../site-packages/urllib3/response.py | 1265 +++ .../site-packages/urllib3/util/__init__.py | 42 + .../util/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1018 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4747 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1230 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 8044 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 2889 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 20304 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 16721 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5550 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 13320 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11702 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 16236 bytes .../util/__pycache__/util.cpython-312.pyc | Bin 0 -> 2007 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 3453 bytes .../site-packages/urllib3/util/connection.py | 137 + .../site-packages/urllib3/util/proxy.py | 43 + .../site-packages/urllib3/util/request.py | 256 + .../site-packages/urllib3/util/response.py | 101 + .../site-packages/urllib3/util/retry.py | 533 + .../site-packages/urllib3/util/ssl_.py | 513 + .../urllib3/util/ssl_match_hostname.py | 159 + .../urllib3/util/ssltransport.py | 276 + .../site-packages/urllib3/util/timeout.py | 275 + .../site-packages/urllib3/util/url.py | 471 + .../site-packages/urllib3/util/util.py | 42 + .../site-packages/urllib3/util/wait.py | 124 + .../werkzeug-3.0.4.dist-info/INSTALLER | 1 + .../werkzeug-3.0.4.dist-info/LICENSE.txt | 28 + .../werkzeug-3.0.4.dist-info/METADATA | 99 + .../werkzeug-3.0.4.dist-info/RECORD | 125 + .../werkzeug-3.0.4.dist-info/WHEEL | 4 + .../site-packages/werkzeug/__init__.py | 25 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1099 bytes .../__pycache__/_internal.cpython-312.pyc | Bin 0 -> 9775 bytes .../__pycache__/_reloader.cpython-312.pyc | Bin 0 -> 20233 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 32953 bytes .../__pycache__/formparser.cpython-312.pyc | Bin 0 -> 16814 bytes .../werkzeug/__pycache__/http.cpython-312.pyc | Bin 0 -> 49605 bytes .../__pycache__/local.cpython-312.pyc | Bin 0 -> 28476 bytes .../__pycache__/security.cpython-312.pyc | Bin 0 -> 6990 bytes .../__pycache__/serving.cpython-312.pyc | Bin 0 -> 46043 bytes .../werkzeug/__pycache__/test.cpython-312.pyc | Bin 0 -> 59854 bytes .../__pycache__/testapp.cpython-312.pyc | Bin 0 -> 8875 bytes .../werkzeug/__pycache__/urls.cpython-312.pyc | Bin 0 -> 8276 bytes .../__pycache__/user_agent.cpython-312.pyc | Bin 0 -> 2165 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 28144 bytes .../werkzeug/__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 25221 bytes .../site-packages/werkzeug/_internal.py | 211 + .../site-packages/werkzeug/_reloader.py | 460 + .../werkzeug/datastructures/__init__.py | 34 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1614 bytes .../__pycache__/accept.cpython-312.pyc | Bin 0 -> 13804 bytes .../__pycache__/auth.cpython-312.pyc | Bin 0 -> 14419 bytes .../__pycache__/cache_control.cpython-312.pyc | Bin 0 -> 7898 bytes .../__pycache__/csp.cpython-312.pyc | Bin 0 -> 5271 bytes .../__pycache__/etag.cpython-312.pyc | Bin 0 -> 5064 bytes .../__pycache__/file_storage.cpython-312.pyc | Bin 0 -> 7932 bytes .../__pycache__/headers.cpython-312.pyc | Bin 0 -> 23207 bytes .../__pycache__/mixins.cpython-312.pyc | Bin 0 -> 11405 bytes .../__pycache__/range.cpython-312.pyc | Bin 0 -> 8250 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 48378 bytes .../werkzeug/datastructures/accept.py | 326 + .../werkzeug/datastructures/accept.pyi | 54 + .../werkzeug/datastructures/auth.py | 316 + .../werkzeug/datastructures/cache_control.py | 175 + .../werkzeug/datastructures/cache_control.pyi | 115 + .../werkzeug/datastructures/csp.py | 94 + .../werkzeug/datastructures/csp.pyi | 169 + .../werkzeug/datastructures/etag.py | 95 + .../werkzeug/datastructures/etag.pyi | 30 + .../werkzeug/datastructures/file_storage.py | 196 + .../werkzeug/datastructures/file_storage.pyi | 49 + .../werkzeug/datastructures/headers.py | 515 + .../werkzeug/datastructures/headers.pyi | 109 + .../werkzeug/datastructures/mixins.py | 242 + .../werkzeug/datastructures/mixins.pyi | 97 + .../werkzeug/datastructures/range.py | 180 + .../werkzeug/datastructures/range.pyi | 57 + .../werkzeug/datastructures/structures.py | 1010 ++ .../werkzeug/datastructures/structures.pyi | 206 + .../site-packages/werkzeug/debug/__init__.py | 564 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 23409 bytes .../debug/__pycache__/console.cpython-312.pyc | Bin 0 -> 11644 bytes .../debug/__pycache__/repr.cpython-312.pyc | Bin 0 -> 13786 bytes .../debug/__pycache__/tbtools.cpython-312.pyc | Bin 0 -> 16961 bytes .../site-packages/werkzeug/debug/console.py | 219 + .../site-packages/werkzeug/debug/repr.py | 282 + .../werkzeug/debug/shared/ICON_LICENSE.md | 6 + .../werkzeug/debug/shared/console.png | Bin 0 -> 507 bytes .../werkzeug/debug/shared/debugger.js | 344 + .../werkzeug/debug/shared/less.png | Bin 0 -> 191 bytes .../werkzeug/debug/shared/more.png | Bin 0 -> 200 bytes .../werkzeug/debug/shared/style.css | 150 + .../site-packages/werkzeug/debug/tbtools.py | 450 + .../site-packages/werkzeug/exceptions.py | 881 ++ .../site-packages/werkzeug/formparser.py | 419 + .../python3.12/site-packages/werkzeug/http.py | 1387 +++ .../site-packages/werkzeug/local.py | 653 ++ .../werkzeug/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 209 bytes .../__pycache__/dispatcher.cpython-312.pyc | Bin 0 -> 3327 bytes .../__pycache__/http_proxy.cpython-312.pyc | Bin 0 -> 9423 bytes .../__pycache__/lint.cpython-312.pyc | Bin 0 -> 17795 bytes .../__pycache__/profiler.cpython-312.pyc | Bin 0 -> 7213 bytes .../__pycache__/proxy_fix.cpython-312.pyc | Bin 0 -> 7210 bytes .../__pycache__/shared_data.cpython-312.pyc | Bin 0 -> 12712 bytes .../werkzeug/middleware/dispatcher.py | 81 + .../werkzeug/middleware/http_proxy.py | 236 + .../site-packages/werkzeug/middleware/lint.py | 439 + .../werkzeug/middleware/profiler.py | 155 + .../werkzeug/middleware/proxy_fix.py | 183 + .../werkzeug/middleware/shared_data.py | 282 + .../site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 134 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4682 bytes .../__pycache__/converters.cpython-312.pyc | Bin 0 -> 10929 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7925 bytes .../routing/__pycache__/map.cpython-312.pyc | Bin 0 -> 39812 bytes .../__pycache__/matcher.cpython-312.pyc | Bin 0 -> 8248 bytes .../routing/__pycache__/rules.cpython-312.pyc | Bin 0 -> 39094 bytes .../werkzeug/routing/converters.py | 261 + .../werkzeug/routing/exceptions.py | 152 + .../site-packages/werkzeug/routing/map.py | 951 ++ .../site-packages/werkzeug/routing/matcher.py | 202 + .../site-packages/werkzeug/routing/rules.py | 928 ++ .../site-packages/werkzeug/sansio/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 205 bytes .../sansio/__pycache__/http.cpython-312.pyc | Bin 0 -> 5729 bytes .../__pycache__/multipart.cpython-312.pyc | Bin 0 -> 14052 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 21898 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 31410 bytes .../sansio/__pycache__/utils.cpython-312.pyc | Bin 0 -> 6024 bytes .../site-packages/werkzeug/sansio/http.py | 171 + .../werkzeug/sansio/multipart.py | 321 + .../site-packages/werkzeug/sansio/request.py | 536 + .../site-packages/werkzeug/sansio/response.py | 754 ++ .../site-packages/werkzeug/sansio/utils.py | 159 + .../site-packages/werkzeug/security.py | 161 + .../site-packages/werkzeug/serving.py | 1123 +++ .../python3.12/site-packages/werkzeug/test.py | 1464 +++ .../site-packages/werkzeug/testapp.py | 194 + .../python3.12/site-packages/werkzeug/urls.py | 203 + .../site-packages/werkzeug/user_agent.py | 47 + .../site-packages/werkzeug/utils.py | 691 ++ .../werkzeug/wrappers/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 329 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 26136 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 34570 bytes .../werkzeug/wrappers/request.py | 647 ++ .../werkzeug/wrappers/response.py | 831 ++ .../python3.12/site-packages/werkzeug/wsgi.py | 595 ++ venv/pyvenv.cfg | 5 + 1387 files changed, 239822 insertions(+), 12 deletions(-) create mode 100644 client/__pycache__/split_lib.cpython-312.pyc rename client/{mem => tmp}/test.txt (100%) create mode 100644 venv/bin/Activate.ps1 create mode 100644 venv/bin/activate create mode 100644 venv/bin/activate.csh create mode 100644 venv/bin/activate.fish create mode 100755 venv/bin/flask create mode 100755 venv/bin/normalizer create mode 100755 venv/bin/pip create mode 100755 venv/bin/pip3 create mode 100755 venv/bin/pip3.12 create mode 120000 venv/bin/python create mode 120000 venv/bin/python3 create mode 120000 venv/bin/python3.12 create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/blinker/__init__.py create mode 100644 venv/lib/python3.12/site-packages/blinker/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/blinker/__pycache__/_utilities.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/blinker/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/blinker/_utilities.py create mode 100644 venv/lib/python3.12/site-packages/blinker/base.py create mode 100644 venv/lib/python3.12/site-packages/blinker/py.typed create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/LICENSE create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/certifi/__init__.py create mode 100644 venv/lib/python3.12/site-packages/certifi/__main__.py create mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/core.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/certifi/cacert.pem create mode 100644 venv/lib/python3.12/site-packages/certifi/core.py create mode 100644 venv/lib/python3.12/site-packages/certifi/py.typed create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/LICENSE create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/entry_points.txt create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__init__.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__main__.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/api.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cd.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/constant.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/legacy.py create mode 100755 venv/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-darwin.so create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/md.py create mode 100755 venv/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-darwin.so create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/models.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/py.typed create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/utils.py create mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/version.py create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/LICENSE.rst create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/click-8.1.7.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/click/__init__.py create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/_compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/_textwrap.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/_winconsole.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/core.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/decorators.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/formatting.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/globals.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/shell_completion.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/termui.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/testing.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/types.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/click/_compat.py create mode 100644 venv/lib/python3.12/site-packages/click/_termui_impl.py create mode 100644 venv/lib/python3.12/site-packages/click/_textwrap.py create mode 100644 venv/lib/python3.12/site-packages/click/_winconsole.py create mode 100644 venv/lib/python3.12/site-packages/click/core.py create mode 100644 venv/lib/python3.12/site-packages/click/decorators.py create mode 100644 venv/lib/python3.12/site-packages/click/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/click/formatting.py create mode 100644 venv/lib/python3.12/site-packages/click/globals.py create mode 100644 venv/lib/python3.12/site-packages/click/parser.py create mode 100644 venv/lib/python3.12/site-packages/click/py.typed create mode 100644 venv/lib/python3.12/site-packages/click/shell_completion.py create mode 100644 venv/lib/python3.12/site-packages/click/termui.py create mode 100644 venv/lib/python3.12/site-packages/click/testing.py create mode 100644 venv/lib/python3.12/site-packages/click/types.py create mode 100644 venv/lib/python3.12/site-packages/click/utils.py create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/REQUESTED create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/entry_points.txt create mode 100644 venv/lib/python3.12/site-packages/flask/__init__.py create mode 100644 venv/lib/python3.12/site-packages/flask/__main__.py create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/app.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/blueprints.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/cli.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/config.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/ctx.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/debughelpers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/globals.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/helpers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/logging.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/sessions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/signals.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/templating.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/testing.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/typing.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/views.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/__pycache__/wrappers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/app.py create mode 100644 venv/lib/python3.12/site-packages/flask/blueprints.py create mode 100644 venv/lib/python3.12/site-packages/flask/cli.py create mode 100644 venv/lib/python3.12/site-packages/flask/config.py create mode 100644 venv/lib/python3.12/site-packages/flask/ctx.py create mode 100644 venv/lib/python3.12/site-packages/flask/debughelpers.py create mode 100644 venv/lib/python3.12/site-packages/flask/globals.py create mode 100644 venv/lib/python3.12/site-packages/flask/helpers.py create mode 100644 venv/lib/python3.12/site-packages/flask/json/__init__.py create mode 100644 venv/lib/python3.12/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/json/__pycache__/provider.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/json/__pycache__/tag.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/json/provider.py create mode 100644 venv/lib/python3.12/site-packages/flask/json/tag.py create mode 100644 venv/lib/python3.12/site-packages/flask/logging.py create mode 100644 venv/lib/python3.12/site-packages/flask/py.typed create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/README.md create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/__pycache__/scaffold.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/app.py create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/blueprints.py create mode 100644 venv/lib/python3.12/site-packages/flask/sansio/scaffold.py create mode 100644 venv/lib/python3.12/site-packages/flask/sessions.py create mode 100644 venv/lib/python3.12/site-packages/flask/signals.py create mode 100644 venv/lib/python3.12/site-packages/flask/templating.py create mode 100644 venv/lib/python3.12/site-packages/flask/testing.py create mode 100644 venv/lib/python3.12/site-packages/flask/typing.py create mode 100644 venv/lib/python3.12/site-packages/flask/views.py create mode 100644 venv/lib/python3.12/site-packages/flask/wrappers.py create mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md create mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/idna/__init__.py create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/uts46data.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/idna/codec.py create mode 100644 venv/lib/python3.12/site-packages/idna/compat.py create mode 100644 venv/lib/python3.12/site-packages/idna/core.py create mode 100644 venv/lib/python3.12/site-packages/idna/idnadata.py create mode 100644 venv/lib/python3.12/site-packages/idna/intranges.py create mode 100644 venv/lib/python3.12/site-packages/idna/package_data.py create mode 100644 venv/lib/python3.12/site-packages/idna/py.typed create mode 100644 venv/lib/python3.12/site-packages/idna/uts46data.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__init__.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/encoding.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/serializer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/signer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/timed.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/__pycache__/url_safe.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/_json.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/encoding.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/exc.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/py.typed create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/serializer.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/signer.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/timed.py create mode 100644 venv/lib/python3.12/site-packages/itsdangerous/url_safe.py create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/entry_points.txt create mode 100644 venv/lib/python3.12/site-packages/jinja2/__init__.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/_identifier.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/async_utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/bccache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/constants.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/debug.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/environment.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/ext.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/filters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/lexer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/meta.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/optimizer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/sandbox.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/tests.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/__pycache__/visitor.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/jinja2/_identifier.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/async_utils.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/bccache.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/compiler.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/constants.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/debug.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/defaults.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/environment.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/ext.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/filters.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/idtracking.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/lexer.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/loaders.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/meta.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/nativetypes.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/nodes.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/optimizer.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/parser.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/py.typed create mode 100644 venv/lib/python3.12/site-packages/jinja2/runtime.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/sandbox.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/tests.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/utils.py create mode 100644 venv/lib/python3.12/site-packages/jinja2/visitor.py create mode 100644 venv/lib/python3.12/site-packages/markupsafe/__init__.py create mode 100644 venv/lib/python3.12/site-packages/markupsafe/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/markupsafe/__pycache__/_native.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/markupsafe/_native.py create mode 100644 venv/lib/python3.12/site-packages/markupsafe/_speedups.c create mode 100755 venv/lib/python3.12/site-packages/markupsafe/_speedups.cpython-312-darwin.so create mode 100644 venv/lib/python3.12/site-packages/markupsafe/_speedups.pyi create mode 100644 venv/lib/python3.12/site-packages/markupsafe/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/AUTHORS.txt create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/REQUESTED create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/entry_points.txt create mode 100644 venv/lib/python3.12/site-packages/pip-24.2.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/pip/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/__pip-runner__.py create mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/build_env.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/base_command.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/command_context.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/index_command.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/main.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/parser.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/req_command.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/spinners.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/check.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/completion.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/configuration.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/debug.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/download.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/freeze.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/hash.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/help.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/index.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/inspect.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/install.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/list.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/search.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/show.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/configuration.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/base.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/installed.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/collector.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/package_finder.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/sources.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/base.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/main.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/_json.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/base.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/candidate.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/direct_url.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/format_control.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/index.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/installation_report.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/link.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/scheme.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/search_scope.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/target_python.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/auth.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/download.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/session.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/utils.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/check.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/freeze.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/prepare.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/pyproject.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/constructors.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_file.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_install.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_set.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/base.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/retry.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/_log.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/datetime.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/encoding.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/glibc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/hashes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/logging.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/misc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/packaging.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/retry.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/urls.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/git.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 venv/lib/python3.12/site-packages/pip/_internal/wheel_builder.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/core.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/database.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/index.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/util.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/version.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/distro.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/codec.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/core.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_elffile.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_parser.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_tokenizer.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/metadata.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/version.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/console.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/style.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/_mapping.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/token.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/util.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/api.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/auth.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/certs.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/compat.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/help.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/models.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/packages.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/structures.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/utils.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/abc.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/align.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/bar.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/box.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/cells.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/color.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/console.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/containers.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/control.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/errors.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/json.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/layout.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/live.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/logging.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/markup.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/measure.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/padding.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/pager.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/palette.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/panel.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/progress.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/region.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/repr.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/rule.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/scope.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/screen.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/segment.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/status.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/style.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/styled.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/table.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/text.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/theme.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/themes.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/tree.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/py.typed create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/vendor.txt create mode 100644 venv/lib/python3.12/site-packages/pip/py.typed create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/REQUESTED create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/top_level.txt create mode 100644 venv/lib/python3.12/site-packages/requests/__init__.py create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/api.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/auth.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/certs.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/compat.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/help.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/models.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/packages.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/structures.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/requests/__version__.py create mode 100644 venv/lib/python3.12/site-packages/requests/_internal_utils.py create mode 100644 venv/lib/python3.12/site-packages/requests/adapters.py create mode 100644 venv/lib/python3.12/site-packages/requests/api.py create mode 100644 venv/lib/python3.12/site-packages/requests/auth.py create mode 100644 venv/lib/python3.12/site-packages/requests/certs.py create mode 100644 venv/lib/python3.12/site-packages/requests/compat.py create mode 100644 venv/lib/python3.12/site-packages/requests/cookies.py create mode 100644 venv/lib/python3.12/site-packages/requests/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/requests/help.py create mode 100644 venv/lib/python3.12/site-packages/requests/hooks.py create mode 100644 venv/lib/python3.12/site-packages/requests/models.py create mode 100644 venv/lib/python3.12/site-packages/requests/packages.py create mode 100644 venv/lib/python3.12/site-packages/requests/sessions.py create mode 100644 venv/lib/python3.12/site-packages/requests/status_codes.py create mode 100644 venv/lib/python3.12/site-packages/requests/structures.py create mode 100644 venv/lib/python3.12/site-packages/requests/utils.py create mode 100644 venv/lib/python3.12/site-packages/urllib3-2.2.3.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/urllib3-2.2.3.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/urllib3-2.2.3.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/urllib3-2.2.3.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/urllib3-2.2.3.dist-info/licenses/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/urllib3/__init__.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_base_connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_request_methods.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/_base_connection.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/_collections.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/_request_methods.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/_version.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/connection.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/connectionpool.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__init__.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__init__.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/fetch.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/connection.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/fetch.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/request.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/response.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/pyopenssl.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/socks.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/fields.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/filepost.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__init__.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/probe.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/connection.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/probe.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/poolmanager.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/py.typed create mode 100644 venv/lib/python3.12/site-packages/urllib3/response.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__init__.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/util.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/connection.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/proxy.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/request.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/response.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/retry.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssl_.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssl_match_hostname.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssltransport.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/timeout.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/url.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/util.py create mode 100644 venv/lib/python3.12/site-packages/urllib3/util/wait.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug-3.0.4.dist-info/INSTALLER create mode 100644 venv/lib/python3.12/site-packages/werkzeug-3.0.4.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.12/site-packages/werkzeug-3.0.4.dist-info/METADATA create mode 100644 venv/lib/python3.12/site-packages/werkzeug-3.0.4.dist-info/RECORD create mode 100644 venv/lib/python3.12/site-packages/werkzeug-3.0.4.dist-info/WHEEL create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/_internal.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/_reloader.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/formparser.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/http.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/local.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/security.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/serving.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/test.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/testapp.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/urls.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/user_agent.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/__pycache__/wsgi.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/_internal.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/_reloader.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/range.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/accept.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/accept.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/auth.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/cache_control.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/cache_control.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/csp.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/csp.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/etag.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/etag.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/file_storage.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/file_storage.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/headers.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/headers.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/mixins.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/mixins.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/range.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/range.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/structures.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/datastructures/structures.pyi create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/__pycache__/console.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/__pycache__/repr.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/console.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/repr.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/ICON_LICENSE.md create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/console.png create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/debugger.js create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/less.png create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/more.png create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/shared/style.css create mode 100644 venv/lib/python3.12/site-packages/werkzeug/debug/tbtools.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/formparser.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/http.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/local.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/lint.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/dispatcher.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/http_proxy.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/lint.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/profiler.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/proxy_fix.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/middleware/shared_data.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/py.typed create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/converters.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/map.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/matcher.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/__pycache__/rules.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/converters.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/exceptions.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/map.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/matcher.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/routing/rules.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/http.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/__pycache__/utils.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/http.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/multipart.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/request.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/response.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/sansio/utils.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/security.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/serving.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/test.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/testapp.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/urls.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/user_agent.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/utils.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/__init__.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/__pycache__/request.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/__pycache__/response.cpython-312.pyc create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/request.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wrappers/response.py create mode 100644 venv/lib/python3.12/site-packages/werkzeug/wsgi.py create mode 100644 venv/pyvenv.cfg diff --git a/client/__pycache__/split_lib.cpython-312.pyc b/client/__pycache__/split_lib.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf861570e568faa92614e4cb80a3d775ef9bd1e1 GIT binary patch literal 6396 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 F{sRnmE++s0 literal 0 HcmV?d00001 diff --git a/client/examples/https_client.py b/client/examples/https_client.py index dd04e4c..a0c91fd 100644 --- a/client/examples/https_client.py +++ b/client/examples/https_client.py @@ -1,7 +1,7 @@ import requests # The URL of the Flask server -url = 'http://localhost:5000/' +url = 'http://localhost:5001/' url_upload = url + 'upload' url_download = url + 'download/' diff --git a/client/solution.py b/client/solution.py index 94c5e6e..46aa9c2 100644 --- a/client/solution.py +++ b/client/solution.py @@ -1,5 +1,5 @@ -from Networks_Hackathon.client.split_lib import * +from split_lib import * import os import filecmp @@ -7,7 +7,28 @@ tmp_folder = "tmp" addr = "./client" debug = False -#split_store(test_file) + +CHUNK_SIZE = 1024 +HTTPS_SERVER_URL = "http://127.0.0.1:5001" +TCP_SERVER_IP = "'127.0.0.1'" +TCP_SERVER_PORT = 65432 + +def split_store(file): + with open(file, 'rb') as f: + chunk_num = 0 + while True: + chunk = f.read(CHUNK_SIZE) + if not chunk: + break + + if chunk_num % 2 == 0: + chunk = f"HTTPS{chunk_num}".encode() + chunk + f"{chunk_num}SPTTH".encode() + upload_helper1_https(chunk, f"{file}_chunk_{chunk_num}") + else: + chunk = f"TCP{chunk_num}".encode() + chunk + f"{chunk_num}PCT".encode() + upload_helper2_tcp(chunk, f"{file}_chunk_{chunk_num}") + + chunk_num += 1 if not os.path.exists(os.path.join(addr,tmp_folder)): os.makedirs(os.path.join(addr,tmp_folder)) @@ -21,7 +42,84 @@ if(debug): print(os.path.join(addr,"mem",test_file)) -#split_fetch(test_file) +def split_fetch(file): + chunk_num = 0 + with open(file, 'wb') as f: + while True: + try: + if chunk_num % 2 == 0: + chunk = fetch_https_helper3(f"{file}_chunk_{chunk_num}") + else: + chunk = fetch_tcp_helper4(f"{file}_chunk_{chunk_num}") + + if not chunk: + break + # cleaned_chunk = clean_chunk(chunk, chunk_num) + # f.write(cleaned_chunk) + chunk_num += 1 + except Exception as e: + print(f"Error fetching chunk {chunk_num}: {e}") + break + +def upload_helper1_https(chunk, chunk_filename): + url = f"{HTTPS_SERVER_URL}/upload" + files = {'file': (chunk_filename, chunk)} + + try: + response = requests.post(url, files=files) + response.raise_for_status() + print(f"Chunk {chunk_filename} uploaded to HTTPS server.") + except requests.exceptions.RequestException as e: + print(f"Failed to upload chunk {chunk_filename} to HTTPS server: {e}") + +def upload_helper2_tcp(chunk, chunk_filename): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((TCP_SERVER_IP, TCP_SERVER_PORT)) + s.sendall("upload".encode().ljust(1024)) + s.sendall(chunk_filename.encode().ljust(1024)) + s.sendall(str(len(chunk)).encode().ljust(1024)) + s.sendall(chunk) + print(f"Chunk {chunk_filename} uploaded to TCP server.") + except Exception as e: + print(f"Failed to upload chunk {chunk_filename} to TCP server: {e}") + +def fetch_https_helper3(chunk_filename): + url = f"{HTTPS_SERVER_URL}/download/{chunk_filename}" + try: + response = requests.get(url) + response.raise_for_status() + print(f"Chunk {chunk_filename} fetched from HTTPS server.") + return response.content + except requests.exceptions.RequestException as err: + print(f"Failed to fetch chunk {chunk_filename} from HTTPS server: {err}") + return None + +def fetch_tcp_helper4(chunk_filename): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((TCP_SERVER_IP, TCP_SERVER_PORT)) + s.sendall("download".encode().ljust(1024)) + s.sendall(chunk_filename.encode().ljust(1024)) + + file_size = int(s.recv(1024).decode().strip()) + chunk_data = s.recv(file_size) + print(f"Chunk {chunk_filename} fetched from TCP server.") + return chunk_data + except Exception as err: + print(f"Failed to fetch chunk {chunk_filename} from TCP server: {err}") + return None + +def clean_chunk(chunk, chunk_num): + if chunk_num % 2 == 0: + header = f"HTTPS{chunk_num}".encode() + footer = f"{chunk_num}SPTTH".encode() + else: + header = f"TCP{chunk_num}".encode() + footer = f"{chunk_num}PCT".encode() + + return chunk[len(header):-len(footer)] + diff --git a/client/split_lib.py b/client/split_lib.py index 25c10fc..1ec3b10 100644 --- a/client/split_lib.py +++ b/client/split_lib.py @@ -1,9 +1,105 @@ -# Library file for both the functions -def split_store(file_name) : - # Split store code - pass +import os +import requests +import socket -def split_fetch(file_name) : - # Split fetch code' - pass \ No newline at end of file + +CHUNK_SIZE = 1024 +HTTPS_SERVER_URL = "http://127.0.0.1:5001" +TCP_SERVER_IP = "'127.0.0.1'" +TCP_SERVER_PORT = 65432 + +def split_store(file): + with open(file, 'rb') as f: + chunk_num = 0 + while True: + chunk = f.read(CHUNK_SIZE) + if not chunk: + break + + if chunk_num % 2 == 0: + chunk = f"HTTPS{chunk_num}".encode() + chunk + f"{chunk_num}SPTTH".encode() + upload_helper1_https(chunk, f"{file}_chunk_{chunk_num}") + else: + chunk = f"TCP{chunk_num}".encode() + chunk + f"{chunk_num}PCT".encode() + upload_helper2_tcp(chunk, f"{file}_chunk_{chunk_num}") + + chunk_num += 1 + +def split_fetch(file): + chunk_num = 0 + with open(file, 'wb') as f: + while True: + try: + if chunk_num % 2 == 0: + chunk = fetch_https_helper3(f"{file}_chunk_{chunk_num}") + else: + chunk = fetch_tcp_helper4(f"{file}_chunk_{chunk_num}") + + if not chunk: + break + cleaned_chunk = clean_chunk(chunk, chunk_num) + f.write(cleaned_chunk) + chunk_num += 1 + except Exception as e: + print(f"Error fetching chunk {chunk_num}: {e}") + break + +def upload_helper1_https(chunk, chunk_filename): + url = f"{HTTPS_SERVER_URL}/upload" + files = {'file': (chunk_filename, chunk)} + + try: + response = requests.post(url, files=files) + response.raise_for_status() + print(f"Chunk {chunk_filename} uploaded to HTTPS server.") + except requests.exceptions.RequestException as e: + print(f"Failed to upload chunk {chunk_filename} to HTTPS server: {e}") + +def upload_helper2_tcp(chunk, chunk_filename): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((TCP_SERVER_IP, TCP_SERVER_PORT)) + s.sendall("upload".encode().ljust(1024)) + s.sendall(chunk_filename.encode().ljust(1024)) + s.sendall(str(len(chunk)).encode().ljust(1024)) + s.sendall(chunk) + print(f"Chunk {chunk_filename} uploaded to TCP server.") + except Exception as e: + print(f"Failed to upload chunk {chunk_filename} to TCP server: {e}") + +def fetch_https_helper3(chunk_filename): + url = f"{HTTPS_SERVER_URL}/download/{chunk_filename}" + try: + response = requests.get(url) + response.raise_for_status() + print(f"Chunk {chunk_filename} fetched from HTTPS server.") + return response.content + except requests.exceptions.RequestException as err: + print(f"Failed to fetch chunk {chunk_filename} from HTTPS server: {err}") + return None + +def fetch_tcp_helper4(chunk_filename): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((TCP_SERVER_IP, TCP_SERVER_PORT)) + s.sendall("download".encode().ljust(1024)) + s.sendall(chunk_filename.encode().ljust(1024)) + + file_size = int(s.recv(1024).decode().strip()) + chunk_data = s.recv(file_size) + print(f"Chunk {chunk_filename} fetched from TCP server.") + return chunk_data + except Exception as err: + print(f"Failed to fetch chunk {chunk_filename} from TCP server: {err}") + return None + +def clean_chunk(chunk, chunk_num): + if chunk_num % 2 == 0: + header = f"HTTPS{chunk_num}".encode() + footer = f"{chunk_num}SPTTH".encode() + else: + header = f"TCP{chunk_num}".encode() + footer = f"{chunk_num}PCT".encode() + + return chunk[len(header):-len(footer)] diff --git a/client/mem/test.txt b/client/tmp/test.txt similarity index 100% rename from client/mem/test.txt rename to client/tmp/test.txt diff --git a/https_server/server.py b/https_server/server.py index 80c6715..231595e 100644 --- a/https_server/server.py +++ b/https_server/server.py @@ -46,4 +46,4 @@ def download_file(filename): if __name__ == "__main__": - app.run(host='0.0.0.0',debug=True, port=5000) + app.run(host='0.0.0.0',debug=True, port=5001) diff --git a/venv/bin/Activate.ps1 b/venv/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/venv/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/venv/bin/activate b/venv/bin/activate new file mode 100644 index 0000000..70ae24b --- /dev/null +++ b/venv/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath "/Users/tejaspatil/Documents/Networks_Hackathon/venv") +else + # use the path as-is + export VIRTUAL_ENV="/Users/tejaspatil/Documents/Networks_Hackathon/venv" +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(venv) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(venv) " + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh new file mode 100644 index 0000000..2c7e923 --- /dev/null +++ b/venv/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/tejaspatil/Documents/Networks_Hackathon/venv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(venv) $prompt" + setenv VIRTUAL_ENV_PROMPT "(venv) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish new file mode 100644 index 0000000..87696a9 --- /dev/null +++ b/venv/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/tejaspatil/Documents/Networks_Hackathon/venv" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(venv) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(venv) " +end diff --git a/venv/bin/flask b/venv/bin/flask new file mode 100755 index 0000000..259d845 --- /dev/null +++ b/venv/bin/flask @@ -0,0 +1,8 @@ +#!/Users/tejaspatil/Documents/Networks_Hackathon/venv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from flask.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/normalizer b/venv/bin/normalizer new file mode 100755 index 0000000..1b91b64 --- /dev/null +++ b/venv/bin/normalizer @@ -0,0 +1,8 @@ +#!/Users/tejaspatil/Documents/Networks_Hackathon/venv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/venv/bin/pip b/venv/bin/pip new file mode 100755 index 0000000..429005a --- /dev/null +++ b/venv/bin/pip @@ -0,0 +1,8 @@ +#!/Users/tejaspatil/Documents/Networks_Hackathon/venv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 new file mode 100755 index 0000000..429005a --- /dev/null +++ b/venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/tejaspatil/Documents/Networks_Hackathon/venv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3.12 b/venv/bin/pip3.12 new file mode 100755 index 0000000..429005a --- /dev/null +++ b/venv/bin/pip3.12 @@ -0,0 +1,8 @@ +#!/Users/tejaspatil/Documents/Networks_Hackathon/venv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/venv/bin/python @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/venv/bin/python3 b/venv/bin/python3 new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/venv/bin/python3 @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/venv/bin/python3.12 b/venv/bin/python3.12 new file mode 120000 index 0000000..a3f0508 --- /dev/null +++ b/venv/bin/python3.12 @@ -0,0 +1 @@ +/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/METADATA b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/METADATA new file mode 100644 index 0000000..dfe37d5 --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/METADATA @@ -0,0 +1,93 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 2.1.5 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/markupsafe/ +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + + >>> # escape replaces special characters and wraps in Markup + >>> escape("") + Markup('<script>alert(document.cookie);</script>') + + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup("Hello") + Markup('hello') + + >>> escape(Markup("Hello")) + Markup('hello') + + >>> # Markup is a str subclass + >>> # methods and operators escape their arguments + >>> template = Markup("Hello {name}") + >>> template.format(name='"World"') + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Chat: https://discord.gg/pallets diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/RECORD b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/RECORD new file mode 100644 index 0000000..a3c723f --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/RECORD @@ -0,0 +1,14 @@ +MarkupSafe-2.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-2.1.5.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-2.1.5.dist-info/METADATA,sha256=2dRDPam6OZLfpX0wg1JN5P3u9arqACxVSfdGmsJU7o8,3003 +MarkupSafe-2.1.5.dist-info/RECORD,, +MarkupSafe-2.1.5.dist-info/WHEEL,sha256=bHkOfcOgXU5awVnxyry7eA7JVWWmfbKWXXd9KfWMgQ4,115 +MarkupSafe-2.1.5.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=r7VOTjUq7EMQ4v3p4R1LoVOGJg6ysfYRncLr34laRBs,10958 +markupsafe/__pycache__/__init__.cpython-312.pyc,, +markupsafe/__pycache__/_native.cpython-312.pyc,, +markupsafe/_native.py,sha256=GR86Qvo_GcgKmKreA1WmYN9ud17OFwkww8E-fiW-57s,1713 +markupsafe/_speedups.c,sha256=X2XvQVtIdcK4Usz70BvkzoOfjTCmQlDkkjYSn-swE0g,7083 +markupsafe/_speedups.cpython-312-darwin.so,sha256=QZ4y0TxBZ1nWWVnGp2flNgNQXga0dR3_Vca8D8bpXxM,117420 +markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL new file mode 100644 index 0000000..de8e77d --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: false +Tag: cp312-cp312-macosx_10_9_universal2 + diff --git a/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt new file mode 100644 index 0000000..75bf729 --- /dev/null +++ b/venv/lib/python3.12/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/LICENSE.txt b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/LICENSE.txt new file mode 100644 index 0000000..79c9825 --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2010 Jason Kirtland + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/METADATA b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/METADATA new file mode 100644 index 0000000..efa45f5 --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: blinker +Version: 1.8.2 +Summary: Fast, simple object-to-object and broadcast signaling +Author: Jason Kirtland +Maintainer-email: Pallets Ecosystem +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://blinker.readthedocs.io +Project-URL: Source, https://github.com/pallets-eco/blinker/ + +# Blinker + +Blinker provides a fast dispatching system that allows any number of +interested parties to subscribe to events, or "signals". + + +## Pallets Community Ecosystem + +> [!IMPORTANT]\ +> This project is part of the Pallets Community Ecosystem. Pallets is the open +> source organization that maintains Flask; Pallets-Eco enables community +> maintenance of related projects. If you are interested in helping maintain +> this project, please reach out on [the Pallets Discord server][discord]. +> +> [discord]: https://discord.gg/pallets + + +## Example + +Signal receivers can subscribe to specific senders or receive signals +sent by any sender. + +```pycon +>>> from blinker import signal +>>> started = signal('round-started') +>>> def each(round): +... print(f"Round {round}") +... +>>> started.connect(each) + +>>> def round_two(round): +... print("This is round two.") +... +>>> started.connect(round_two, sender=2) + +>>> for round in range(1, 4): +... started.send(round) +... +Round 1! +Round 2! +This is round two. +Round 3! +``` + diff --git a/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/RECORD b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/RECORD new file mode 100644 index 0000000..46b35c6 --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/RECORD @@ -0,0 +1,12 @@ +blinker-1.8.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +blinker-1.8.2.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 +blinker-1.8.2.dist-info/METADATA,sha256=3tEx40hm9IEofyFqDPJsDPE9MAIEhtifapoSp7FqzuA,1633 +blinker-1.8.2.dist-info/RECORD,, +blinker-1.8.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +blinker/__init__.py,sha256=ymyJY_PoTgBzaPgdr4dq-RRsGh7D-sYQIGMNp8Rx4qc,1577 +blinker/__pycache__/__init__.cpython-312.pyc,, +blinker/__pycache__/_utilities.cpython-312.pyc,, +blinker/__pycache__/base.cpython-312.pyc,, +blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675 +blinker/base.py,sha256=nIZJEtXQ8LLZZJrwVp2wQcdfCzDixvAHR9VpSWiyVcQ,22574 +blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/WHEEL b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker-1.8.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/blinker/__init__.py b/venv/lib/python3.12/site-packages/blinker/__init__.py new file mode 100644 index 0000000..c93527e --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker/__init__.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import typing as t + +from .base import ANY +from .base import default_namespace +from .base import NamedSignal +from .base import Namespace +from .base import Signal +from .base import signal + +__all__ = [ + "ANY", + "default_namespace", + "NamedSignal", + "Namespace", + "Signal", + "signal", +] + + +def __getattr__(name: str) -> t.Any: + import warnings + + if name == "__version__": + import importlib.metadata + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Blinker 1.9.0. Use feature detection or" + " 'importlib.metadata.version(\"blinker\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("blinker") + + if name == "receiver_connected": + from .base import _receiver_connected + + warnings.warn( + "The global 'receiver_connected' signal is deprecated and will be" + " removed in Blinker 1.9. Use 'Signal.receiver_connected' and" + " 'Signal.receiver_disconnected' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _receiver_connected + + if name == "WeakNamespace": + from .base import _WeakNamespace + + warnings.warn( + "'WeakNamespace' is deprecated and will be removed in Blinker 1.9." + " Use 'Namespace' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _WeakNamespace + + raise AttributeError(name) diff --git a/venv/lib/python3.12/site-packages/blinker/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/blinker/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..accc8972b1300fb7604ba82e6a8bf0a7b85fca73 GIT binary patch literal 1814 zcmb7E&2Jk;6rZuzyX&<#PLogqw9Y1x>TE@A3Y97(gp{gCoO}tWVlS()XX0+W-nC}O zjvU3JLLA`45x61_pmOAI;KIdC4@Fy9s?>7G0VyIm^~9U?N78&C^~s)n@6Ej5@6Eh7 z^QUPV2;}-7|7_YSLeHf!k<>`Rhiy>4M-)-)qZW2BmU_xhIcb`vim$XXP6m8wngLyP z)I?W7*BmX;HPCfOPjnshtdmXjEa-+~VAMd=_z62Xny0z16(`?I+2+2aw{e^!K@bWe zyfBEW`*`F`uUEf-xl5F7l8!IjfV5cDCUqtQs$kF!uMrR*%&asgbL!NsMxzBP&j2Kc z%_FYKL6<{T4)SQ~l5iq&Wf~!T_%3+iL@-4@>f>EFjpiBz+)g~WpW4M+a_uRhX(4G6 zp~`QWhkzvoqutb&q&+2Dxl;}>srqo7(FOuuE#bAOPP4w+()ww@I-lFPkUO0q<)%n^ zK+^llg-GUwNXiBh^OKx+(InHausu`dvYq0b>vkEBpq8$?^W$gtnN>RBDOp4a?$tVi zSzcsO*5<5E1fv!SsI~3+zExuuXRWXcJ}4-x`aELRCL^N583YSf zmrY}Z+$wpkcF2YA)ygd<2ql7)$9b%+)J7mHb_pOO!3Zty%VeQV`^ehDhVWi!Sz>yxJXg!7QwnOF(nN#F}|GCO5Ej)>&l zwWPeH73e7*RRr52@P-J_uiOpmofZp3RH-tt9r9-6ehN)O#QiX+bXm}?K$}(CJ!yYX zzWIJ7@&vm9Z&Q;rSX3EzQN?w=z!R=pZujJ^Xh2&+ny$;2fc!H2qu*h8fSxMz&$Qe( z{XOl#+h7+&fhwL;qQ*~c8-V|ZBM7;P91(ir0*T6vD< h{zh*M(drOg9in%JXc2z@Dq1e}Ks#EvhL;kk{{ZiV>23f3 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/blinker/__pycache__/_utilities.cpython-312.pyc b/venv/lib/python3.12/site-packages/blinker/__pycache__/_utilities.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19d2a3190062adbc57367e91dfda8795bac726ef GIT binary patch literal 2736 zcmb6bU27Cq^xmD>o!O7<#zc+QsN)AUE9tJO4}~geML`7{XrnD`8YYvOyK$1)+3me| zqq}TNN>kh**7#782OnA}6tTabz5`?lImp2tD&Ydg0*`o+l2TAxc(f3ev{*rd zUGel%ybzZ>74SqMfl&kzZF*~4`ODpj-o)Xlkcyy_$cfD(N4ptm(Yl<3qtB~_w3BpF zPJBLE$kZa)uD=93i-V-)`(3zJL-I@5Od;A6b#Y8pcw2r7^J}-Z=#F1 zkQhbTR1h1jl_twx{g-2g4F++`=LVCcLBn@#LJfZ2@{Ng!^5itJ`9OAJB4>O;D#YT% zF>K58m_Z4zQXd3K!hprB5;0t<%O<&mqzw-b8{wM<4iwAf16jjm8wpbEEUkt*{v|Kj za8vH}ojiBkvl#o-qGOJ0^D)NhU`yZlc%X$}!0c8?r2m8$;lXQP0rEXwLJizN(~`9j z%p#h3J*R=UgXk#Y>v|WI2D%bQsDW;_QsT=Q3D2TFZh0s7V zO`lva&8!+Iw#Ne12PXy!I6a7)rY*kJG?~b6aPZuVV*VT>l;t^@wpayn$;+Q8+tm{B zIm?d_exXcfn0d;wXDmo4KR-+S*}UgY<|{REKAanRH_u#7-l+(YDZ=uTp6kyLnm4PU z%;hd&xk`<8!3*o@FmSn+iQ9n2J^=814&6;=77s5Sxpw4sa@XD7tpZ!-w|n=mr1n2d z_byB=l$Y(*^xmd&w|{q2xtd%^E}popZ@-)AX(rY{1=!t0xOwc?R6o;&8(28~=UH=a$32#M@A z%^+c#rLt4?1fDX@FRGT;;y^t(W!p5vBFUI$N7DqV$V=KMfQS?-1y`ylhMoqsm|;SPW!DPfkFmGG<6k$hp2yNO(>XvwEPxe5k-Y33Qj0 z!l4&&9g!Nvst<7&n5b`&BraS!h3g*WE=Fk%z z>6zcOzS~;gvT{f3e-cC8J&XI62CogSW_JJ7^TY9<&-{31bc!e0Sd?e&D6J7ux+B2_~3V$u*QlA0a@ zP~T(cj)PG`Vr&d-7&|*YK4^%JF>W;E9%_OXBY4?v(H4qT_@#ihK*6yn$k=7igKQDM zOgU@P4io{fEjT$|_fYyC>Un_r9-v*nt6g))E}j1RbkqK3WDY-z W?ZEwy5rDO$8QlAHzlwKB-Twds7iDY! literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/blinker/__pycache__/base.cpython-312.pyc b/venv/lib/python3.12/site-packages/blinker/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80598bae1d0e13bbeb68cf1203d645e511a278fb GIT binary patch literal 25428 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 Xlm~b2+!A)LIGmzu&0j7yFfjZ-0~vwY literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/blinker/_utilities.py b/venv/lib/python3.12/site-packages/blinker/_utilities.py new file mode 100644 index 0000000..000c902 --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker/_utilities.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import collections.abc as c +import inspect +import typing as t +from weakref import ref +from weakref import WeakMethod + +T = t.TypeVar("T") + + +class Symbol: + """A constant symbol, nicer than ``object()``. Repeated calls return the + same instance. + + >>> Symbol('foo') is Symbol('foo') + True + >>> Symbol('foo') + foo + """ + + symbols: t.ClassVar[dict[str, Symbol]] = {} + + def __new__(cls, name: str) -> Symbol: + if name in cls.symbols: + return cls.symbols[name] + + obj = super().__new__(cls) + cls.symbols[name] = obj + return obj + + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return self.name + + def __getnewargs__(self) -> tuple[t.Any, ...]: + return (self.name,) + + +def make_id(obj: object) -> c.Hashable: + """Get a stable identifier for a receiver or sender, to be used as a dict + key or in a set. + """ + if inspect.ismethod(obj): + # The id of a bound method is not stable, but the id of the unbound + # function and instance are. + return id(obj.__func__), id(obj.__self__) + + if isinstance(obj, (str, int)): + # Instances with the same value always compare equal and have the same + # hash, even if the id may change. + return obj + + # Assume other types are not hashable but will always be the same instance. + return id(obj) + + +def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: + if inspect.ismethod(obj): + return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] + + return ref(obj, callback) diff --git a/venv/lib/python3.12/site-packages/blinker/base.py b/venv/lib/python3.12/site-packages/blinker/base.py new file mode 100644 index 0000000..ec494b1 --- /dev/null +++ b/venv/lib/python3.12/site-packages/blinker/base.py @@ -0,0 +1,621 @@ +from __future__ import annotations + +import collections.abc as c +import typing as t +import warnings +import weakref +from collections import defaultdict +from contextlib import AbstractContextManager +from contextlib import contextmanager +from functools import cached_property +from inspect import iscoroutinefunction +from weakref import WeakValueDictionary + +from ._utilities import make_id +from ._utilities import make_ref +from ._utilities import Symbol + +if t.TYPE_CHECKING: + F = t.TypeVar("F", bound=c.Callable[..., t.Any]) + +ANY = Symbol("ANY") +"""Symbol for "any sender".""" + +ANY_ID = 0 + + +class Signal: + """A notification emitter. + + :param doc: The docstring for the signal. + """ + + ANY = ANY + """An alias for the :data:`~blinker.ANY` sender symbol.""" + + set_class: type[set[t.Any]] = set + """The set class to use for tracking connected receivers and senders. + Python's ``set`` is unordered. If receivers must be dispatched in the order + they were connected, an ordered set implementation can be used. + + .. versionadded:: 1.7 + """ + + @cached_property + def receiver_connected(self) -> Signal: + """Emitted at the end of each :meth:`connect` call. + + The signal sender is the signal instance, and the :meth:`connect` + arguments are passed through: ``receiver``, ``sender``, and ``weak``. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver connects.") + + @cached_property + def receiver_disconnected(self) -> Signal: + """Emitted at the end of each :meth:`disconnect` call. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: ``receiver`` and ``sender``. + + This signal is emitted **only** when :meth:`disconnect` is called + explicitly. This signal cannot be emitted by an automatic disconnect + when a weakly referenced receiver or sender goes out of scope, as the + instance is no longer be available to be used as the sender for this + signal. + + An alternative approach is available by subscribing to + :attr:`receiver_connected` and setting up a custom weakref cleanup + callback on weak receivers and senders. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver disconnects.") + + def __init__(self, doc: str | None = None) -> None: + if doc: + self.__doc__ = doc + + self.receivers: dict[ + t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] + ] = {} + """The map of connected receivers. Useful to quickly check if any + receivers are connected to the signal: ``if s.receivers:``. The + structure and data is not part of the public API, but checking its + boolean value is. + """ + + self.is_muted: bool = False + self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} + + def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: + """Connect ``receiver`` to be called when the signal is sent by + ``sender``. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends. + """ + receiver_id = make_id(receiver) + sender_id = ANY_ID if sender is ANY else make_id(sender) + + if weak: + self.receivers[receiver_id] = make_ref( + receiver, self._make_cleanup_receiver(receiver_id) + ) + else: + self.receivers[receiver_id] = receiver + + self._by_sender[sender_id].add(receiver_id) + self._by_receiver[receiver_id].add(sender_id) + + if sender is not ANY and sender_id not in self._weak_senders: + # store a cleanup for weakref-able senders + try: + self._weak_senders[sender_id] = make_ref( + sender, self._make_cleanup_sender(sender_id) + ) + except TypeError: + pass + + if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: + try: + self.receiver_connected.send( + self, receiver=receiver, sender=sender, weak=weak + ) + except TypeError: + # TODO no explanation or test for this + self.disconnect(receiver, sender) + raise + + if _receiver_connected.receivers and self is not _receiver_connected: + try: + _receiver_connected.send( + self, receiver_arg=receiver, sender_arg=sender, weak_arg=weak + ) + except TypeError: + self.disconnect(receiver, sender) + raise + + return receiver + + def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: + """Connect the decorated function to be called when the signal is sent + by ``sender``. + + The decorated function will be called when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument along + with any extra keyword arguments. + + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends.= + + .. versionadded:: 1.1 + """ + + def decorator(fn: F) -> F: + self.connect(fn, sender, weak) + return fn + + return decorator + + @contextmanager + def connected_to( + self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY + ) -> c.Generator[None, None, None]: + """A context manager that temporarily connects ``receiver`` to the + signal while a ``with`` block executes. When the block exits, the + receiver is disconnected. Useful for tests. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. + + .. versionadded:: 1.1 + """ + self.connect(receiver, sender=sender, weak=False) + + try: + yield None + finally: + self.disconnect(receiver) + + @contextmanager + def muted(self) -> c.Generator[None, None, None]: + """A context manager that temporarily disables the signal. No receivers + will be called if the signal is sent, until the ``with`` block exits. + Useful for tests. + """ + self.is_muted = True + + try: + yield None + finally: + self.is_muted = False + + def temporarily_connected_to( + self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY + ) -> AbstractContextManager[None]: + """Deprecated alias for :meth:`connected_to`. + + .. deprecated:: 1.1 + Renamed to ``connected_to``. Will be removed in Blinker 1.9. + + .. versionadded:: 0.9 + """ + warnings.warn( + "'temporarily_connected_to' is renamed to 'connected_to'. The old name is" + " deprecated and will be removed in Blinker 1.9.", + DeprecationWarning, + stacklevel=2, + ) + return self.connected_to(receiver, sender) + + def send( + self, + sender: t.Any | None = None, + /, + *, + _async_wrapper: c.Callable[ + [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Call all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _async_wrapper: Will be called on any receivers that are async + coroutines to turn them into sync callables. For example, could run + the receiver with an event loop. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionchanged:: 1.7 + Added the ``_async_wrapper`` argument. + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if iscoroutinefunction(receiver): + if _async_wrapper is None: + raise RuntimeError("Cannot send to a coroutine function.") + + result = _async_wrapper(receiver)(sender, **kwargs) + else: + result = receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + async def send_async( + self, + sender: t.Any | None = None, + /, + *, + _sync_wrapper: c.Callable[ + [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Await all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _sync_wrapper: Will be called on any receivers that are sync + callables to turn them into async coroutines. For example, + could call the receiver in a thread. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionadded:: 1.7 + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if not iscoroutinefunction(receiver): + if _sync_wrapper is None: + raise RuntimeError("Cannot send to a non-coroutine function.") + + result = await _sync_wrapper(receiver)(sender, **kwargs) + else: + result = await receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + def has_receivers_for(self, sender: t.Any) -> bool: + """Check if there is at least one receiver that will be called with the + given ``sender``. A receiver connected to :data:`ANY` will always be + called, regardless of sender. Does not check if weakly referenced + receivers are still live. See :meth:`receivers_for` for a stronger + search. + + :param sender: Check for receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + if not self.receivers: + return False + + if self._by_sender[ANY_ID]: + return True + + if sender is ANY: + return False + + return make_id(sender) in self._by_sender + + def receivers_for( + self, sender: t.Any + ) -> c.Generator[c.Callable[..., t.Any], None, None]: + """Yield each receiver to be called for ``sender``, in addition to those + to be called for :data:`ANY`. Weakly referenced receivers that are not + live will be disconnected and skipped. + + :param sender: Yield receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + # TODO: test receivers_for(ANY) + if not self.receivers: + return + + sender_id = make_id(sender) + + if sender_id in self._by_sender: + ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] + else: + ids = self._by_sender[ANY_ID].copy() + + for receiver_id in ids: + receiver = self.receivers.get(receiver_id) + + if receiver is None: + continue + + if isinstance(receiver, weakref.ref): + strong = receiver() + + if strong is None: + self._disconnect(receiver_id, ANY_ID) + continue + + yield strong + else: + yield receiver + + def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: + """Disconnect ``receiver`` from being called when the signal is sent by + ``sender``. + + :param receiver: A connected receiver callable. + :param sender: Disconnect from only this sender. By default, disconnect + from all senders. + """ + sender_id: c.Hashable + + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = make_id(sender) + + receiver_id = make_id(receiver) + self._disconnect(receiver_id, sender_id) + + if ( + "receiver_disconnected" in self.__dict__ + and self.receiver_disconnected.receivers + ): + self.receiver_disconnected.send(self, receiver=receiver, sender=sender) + + def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: + if sender_id == ANY_ID: + if self._by_receiver.pop(receiver_id, None) is not None: + for bucket in self._by_sender.values(): + bucket.discard(receiver_id) + + self.receivers.pop(receiver_id, None) + else: + self._by_sender[sender_id].discard(receiver_id) + self._by_receiver[receiver_id].discard(sender_id) + + def _make_cleanup_receiver( + self, receiver_id: c.Hashable + ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: + """Create a callback function to disconnect a weakly referenced + receiver when it is garbage collected. + """ + + def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: + self._disconnect(receiver_id, ANY_ID) + + return cleanup + + def _make_cleanup_sender( + self, sender_id: c.Hashable + ) -> c.Callable[[weakref.ref[t.Any]], None]: + """Create a callback function to disconnect all receivers for a weakly + referenced sender when it is garbage collected. + """ + assert sender_id != ANY_ID + + def cleanup(ref: weakref.ref[t.Any]) -> None: + self._weak_senders.pop(sender_id, None) + + for receiver_id in self._by_sender.pop(sender_id, ()): + self._by_receiver[receiver_id].discard(sender_id) + + return cleanup + + def _cleanup_bookkeeping(self) -> None: + """Prune unused sender/receiver bookkeeping. Not threadsafe. + + Connecting & disconnecting leaves behind a small amount of bookkeeping + data. Typical workloads using Blinker, for example in most web apps, + Flask, CLI scripts, etc., are not adversely affected by this + bookkeeping. + + With a long-running process performing dynamic signal routing with high + volume, e.g. connecting to function closures, senders are all unique + object instances. Doing all of this over and over may cause memory usage + to grow due to extraneous bookkeeping. (An empty ``set`` for each stale + sender/receiver pair.) + + This method will prune that bookkeeping away, with the caveat that such + pruning is not threadsafe. The risk is that cleanup of a fully + disconnected receiver/sender pair occurs while another thread is + connecting that same pair. If you are in the highly dynamic, unique + receiver/sender situation that has lead you to this method, that failure + mode is perhaps not a big deal for you. + """ + for mapping in (self._by_sender, self._by_receiver): + for ident, bucket in list(mapping.items()): + if not bucket: + mapping.pop(ident, None) + + def _clear_state(self) -> None: + """Disconnect all receivers and senders. Useful for tests.""" + self._weak_senders.clear() + self.receivers.clear() + self._by_sender.clear() + self._by_receiver.clear() + + +_receiver_connected = Signal( + """\ +Sent by a :class:`Signal` after a receiver connects. + +:argument: the Signal that was connected to +:keyword receiver_arg: the connected receiver +:keyword sender_arg: the sender to connect to +:keyword weak_arg: true if the connection to receiver_arg is a weak reference + +.. deprecated:: 1.2 + Individual signals have their own :attr:`~Signal.receiver_connected` and + :attr:`~Signal.receiver_disconnected` signals with a slightly simplified + call signature. This global signal will be removed in Blinker 1.9. +""" +) + + +class NamedSignal(Signal): + """A named generic notification emitter. The name is not used by the signal + itself, but matches the key in the :class:`Namespace` that it belongs to. + + :param name: The name of the signal within the namespace. + :param doc: The docstring for the signal. + """ + + def __init__(self, name: str, doc: str | None = None) -> None: + super().__init__(doc) + + #: The name of this signal. + self.name: str = name + + def __repr__(self) -> str: + base = super().__repr__() + return f"{base[:-1]}; {self.name!r}>" # noqa: E702 + + +if t.TYPE_CHECKING: + + class PNamespaceSignal(t.Protocol): + def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... + + # Python < 3.9 + _NamespaceBase = dict[str, NamedSignal] # type: ignore[misc] +else: + _NamespaceBase = dict + + +class Namespace(_NamespaceBase): + """A dict mapping names to signals.""" + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` for the given ``name``, creating it + if required. Repeated calls with the same name return the same signal. + + :param name: The name of the signal. + :param doc: The docstring of the signal. + """ + if name not in self: + self[name] = NamedSignal(name, doc) + + return self[name] + + +class _WeakNamespace(WeakValueDictionary): # type: ignore[type-arg] + """A weak mapping of names to signals. + + Automatically cleans up unused signals when the last reference goes out + of scope. This namespace implementation provides similar behavior to Blinker + <= 1.2. + + .. deprecated:: 1.3 + Will be removed in Blinker 1.9. + + .. versionadded:: 1.3 + """ + + def __init__(self) -> None: + warnings.warn( + "'WeakNamespace' is deprecated and will be removed in Blinker 1.9." + " Use 'Namespace' instead.", + DeprecationWarning, + stacklevel=2, + ) + super().__init__() + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` for the given ``name``, creating it + if required. Repeated calls with the same name return the same signal. + + :param name: The name of the signal. + :param doc: The docstring of the signal. + """ + if name not in self: + self[name] = NamedSignal(name, doc) + + return self[name] # type: ignore[no-any-return] + + +default_namespace: Namespace = Namespace() +"""A default :class:`Namespace` for creating named signals. :func:`signal` +creates a :class:`NamedSignal` in this namespace. +""" + +signal: PNamespaceSignal = default_namespace.signal +"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given +``name``, creating it if required. Repeated calls with the same name return the +same signal. +""" + + +def __getattr__(name: str) -> t.Any: + if name == "receiver_connected": + warnings.warn( + "The global 'receiver_connected' signal is deprecated and will be" + " removed in Blinker 1.9. Use 'Signal.receiver_connected' and" + " 'Signal.receiver_disconnected' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _receiver_connected + + if name == "WeakNamespace": + warnings.warn( + "'WeakNamespace' is deprecated and will be removed in Blinker 1.9." + " Use 'Namespace' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _WeakNamespace + + raise AttributeError(name) diff --git a/venv/lib/python3.12/site-packages/blinker/py.typed b/venv/lib/python3.12/site-packages/blinker/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/LICENSE b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/LICENSE new file mode 100644 index 0000000..62b076c --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/LICENSE @@ -0,0 +1,20 @@ +This package contains a modified version of ca-bundle.crt: + +ca-bundle.crt -- Bundle of CA Root Certificates + +This is a bundle of X.509 certificates of public Certificate Authorities +(CA). These were automatically extracted from Mozilla's root certificates +file (certdata.txt). This file can be found in the mozilla source tree: +https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt +It contains the certificates in PEM format and therefore +can be directly used with curl / libcurl / php_curl, or with +an Apache+mod_ssl webserver for SSL client authentication. +Just configure this file as the SSLCACertificateFile.# + +***** BEGIN LICENSE BLOCK ***** +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +***** END LICENSE BLOCK ***** +@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/METADATA b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/METADATA new file mode 100644 index 0000000..0a3a772 --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/METADATA @@ -0,0 +1,67 @@ +Metadata-Version: 2.1 +Name: certifi +Version: 2024.8.30 +Summary: Python package for providing Mozilla's CA Bundle. +Home-page: https://github.com/certifi/python-certifi +Author: Kenneth Reitz +Author-email: me@kennethreitz.com +License: MPL-2.0 +Project-URL: Source, https://github.com/certifi/python-certifi +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) +Classifier: Natural Language :: English +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.6 +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 +Requires-Python: >=3.6 +License-File: LICENSE + +Certifi: Python SSL Certificates +================================ + +Certifi provides Mozilla's carefully curated collection of Root Certificates for +validating the trustworthiness of SSL certificates while verifying the identity +of TLS hosts. It has been extracted from the `Requests`_ project. + +Installation +------------ + +``certifi`` is available on PyPI. Simply install it with ``pip``:: + + $ pip install certifi + +Usage +----- + +To reference the installed certificate authority (CA) bundle, you can use the +built-in function:: + + >>> import certifi + + >>> certifi.where() + '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' + +Or from the command line:: + + $ python -m certifi + /usr/local/lib/python3.7/site-packages/certifi/cacert.pem + +Enjoy! + +.. _`Requests`: https://requests.readthedocs.io/en/master/ + +Addition/Removal of Certificates +-------------------------------- + +Certifi does not support any addition/removal or other modification of the +CA trust store content. This project is intended to provide a reliable and +highly portable root of trust to python deployments. Look to upstream projects +for methods to use alternate trust. diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/RECORD b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/RECORD new file mode 100644 index 0000000..12374b0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/RECORD @@ -0,0 +1,14 @@ +certifi-2024.8.30.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +certifi-2024.8.30.dist-info/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989 +certifi-2024.8.30.dist-info/METADATA,sha256=GhBHRVUN6a4ZdUgE_N5wmukJfyuoE-QyIl8Y3ifNQBM,2222 +certifi-2024.8.30.dist-info/RECORD,, +certifi-2024.8.30.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91 +certifi-2024.8.30.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi/__init__.py,sha256=p_GYZrjUwPBUhpLlCZoGb0miKBKSqDAyZC5DvIuqbHQ,94 +certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 +certifi/__pycache__/__init__.cpython-312.pyc,, +certifi/__pycache__/__main__.cpython-312.pyc,, +certifi/__pycache__/core.cpython-312.pyc,, +certifi/cacert.pem,sha256=lO3rZukXdPyuk6BWUJFOKQliWaXH6HGh9l1GGrUgG0c,299427 +certifi/core.py,sha256=qRDDFyXVJwTB_EmoGppaXU_R9qCZvhl-EzxPMuV3nTA,4426 +certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/WHEEL b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/WHEEL new file mode 100644 index 0000000..57e56b7 --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (74.0.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/top_level.txt new file mode 100644 index 0000000..963eac5 --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi-2024.8.30.dist-info/top_level.txt @@ -0,0 +1 @@ +certifi diff --git a/venv/lib/python3.12/site-packages/certifi/__init__.py b/venv/lib/python3.12/site-packages/certifi/__init__.py new file mode 100644 index 0000000..f61d77f --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi/__init__.py @@ -0,0 +1,4 @@ +from .core import contents, where + +__all__ = ["contents", "where"] +__version__ = "2024.08.30" diff --git a/venv/lib/python3.12/site-packages/certifi/__main__.py b/venv/lib/python3.12/site-packages/certifi/__main__.py new file mode 100644 index 0000000..8945b5d --- /dev/null +++ b/venv/lib/python3.12/site-packages/certifi/__main__.py @@ -0,0 +1,12 @@ +import argparse + +from certifi import contents, where + +parser = argparse.ArgumentParser() +parser.add_argument("-c", "--contents", action="store_true") +args = parser.parse_args() + +if args.contents: + print(contents()) +else: + print(where()) diff --git a/venv/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5e373b7bebb612d6b8df5e6cdb8bed74fa09473 GIT binary patch literal 324 zcmX@j%ge<81Y*bEro{p2#~=<2FhLog6@ZNC3@HpLj5!Rsj8TlaOi@gX3@J=0%;`)~ z%qc8UES0R9Y%dvs$~2j7aU|#Gm89mC6yIVk&qyswEn)_W7qI||DlQ`fBNIIX3q4~4 zKTXzKEXn!E(zn>-;}dgo;^S{|$H$kY78Pga=f%gbWcUo!%J3^iKeQMqreBhpl~`Pm zSdy8e?~MIXkf=BR@~SEH$r8KPNLuzn~JtH`X&W(l5>| zN!2X?DM?Q))=y3?D#=XC)Q^wP%*!l^kJl@x{Ka9Do1apelWJGQ4YU;GqhfI&@qw9< ck?}r*;sb8c3FQ~KEn7U4f~fT3 zP5%VT`hR%v;?m02c&T_04}#EJPbSly?!`dzzW06KdwDbYT&o2@t;J7&HqTZ3sgr8i zQ*eHwz&k(yfeGm9Xe2N-x<+btO$ZD?LEo#2W^puyU7Ond+KjIdF^NU&kIu-vWFSz! z`AVI|t3Dp}`qqrE5SvpI_-Y%Ka|ACn2!?Q~ng7#T?r&}Ev<&G*c_wHkxU_e-D5HBu zJK77{?JGLqB4;!dY(QI3Iye$>p0xt$Vb&`!<5ap4Wg^~;nf@N82bFVctT#wi+b7z= zq*FSXyoL!0Rbi>gpk#HY30lvivX-L`6}vgx z=HUj8wz1gCGqgjq9hAh+Q8Co{^3uach{uAq3vKC9j;52MFidfrh2c^$yzo}ioD35B zm|a(w>OaVzspGE+A^Z;Je}UU)e)Dx>;y1^B^Vq+&@00_tN>f4lzv!G{-LK>Y-) toVvA%+ZelzWB2C1b!NJ+Ru5LcS^k@Qhxfl)H-0E|=kV^!4qH&o{{gqH+Y2*A?zs|qMEynZ0Dwp^QY`BuY zB966=<0=O^SbB)C2*7{CVdQ9f>I85Y_B$@;Avn>iU{(Hh;Htb zie{j72L-Md$wjvoE!cg@V% zdgg2+^JZi8t-CW%V?+0^-n;tI)z4$6ztTr*+Nk%YJrTqxVQc>a6hzRE4}mHcAafw) zyRj;FqYDf8V#*&Y!EC@%on=rq2}8_XwZskEenef(sv3@IS8wEG4?u>bbR*0vnMHs~ z?1x4R5|?FR-~=@OT~I({J-Kzgp=X-<$+~{>;gN>^W>ddV*Dw6-L`}cY(C2E}oKI|q zbb5}M1F;n^SQ+@U2N4B2JVgEs&K^$xWS7%eBOgmJ0Hh>|E}I3;_N0vQ+$RUH6gT8a zITm=kRv@uF3DDfjQijaVX)FQ8)oxg#*ySHX`mhwL5maeZnEU%+^{D2lx8WiGA*dd{ zrOD`PJLeu&8i&vS-wf;4h@-IfUWS>H#}q^xWS+25Fpnt1nC#zY7W+`mL2DzQF!Jf` zLpw8{zV*32Rnw+AL8h+yUKOr^JADqHxCZ$+W8bvguwNxH|G2ZtAh&TpZU_?5Vch7( z4LU>6JOE{XAXrkzedgwPS+$#t`iEs zb#hz2PS$8nnq}XC_vd6+aaOFV7b91}^vJ0!2T#~3RCo&ZIw)5$OQOUP?ktK|P&!Z| zo+W7fG$;sfjPwuv@%V=)cBa3GkAISUk{Ee#?hofaJpUh=Mlvr5sAhb;79W4bvFQG3 z;Cu2X>bda2S#lRf^kzxfKO1y+y#H|}k0U)2H?R|CRI%OWC(l{1gg&c%#fY%g>gq+ z6^r9>=t}#KvER#>Z0Q&?Bx}Q3HX?p2(p3i z-elhW<<*o<5%GY@;@c5Wb_|u5p=ZEzRk6NeaW@18YB@WJebJwLUuX;P#0_8Te4e=4 zT#$Hs@4Q#q4>})oKVlbQGDd_)K(}N{=?h7vN;^hq-rGkL6@Jho%hlDT^Ssm;qz;O?2<9 None: + _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] + + +if sys.version_info >= (3, 11): + + from importlib.resources import as_file, files + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the file + # in cases where we're inside of a zipimport situation until someone + # actually calls where(), but we don't want to re-extract the file + # on every call of where(), so we'll do it once then store it in a + # global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you to + # manage the cleanup of this file, so it doesn't actually return a + # path, it returns a context manager that will give you the path + # when you enter it and will do any cleanup when you leave it. In + # the common case of not needing a temporary file, it will just + # return the file system location and the __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") + +elif sys.version_info >= (3, 7): + + from importlib.resources import path as get_path, read_text + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the + # file in cases where we're inside of a zipimport situation until + # someone actually calls where(), but we don't want to re-extract + # the file on every call of where(), so we'll do it once then store + # it in a global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you + # to manage the cleanup of this file, so it doesn't actually + # return a path, it returns a context manager that will give + # you the path when you enter it and will do any cleanup when + # you leave it. In the common case of not needing a temporary + # file, it will just return the file system location and the + # __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = get_path("certifi", "cacert.pem") + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return read_text("certifi", "cacert.pem", encoding="ascii") + +else: + import os + import types + from typing import Union + + Package = Union[types.ModuleType, str] + Resource = Union[str, "os.PathLike"] + + # This fallback will work for Python versions prior to 3.7 that lack the + # importlib.resources module but relies on the existing `where` function + # so won't address issues with environments like PyOxidizer that don't set + # __file__ on modules. + def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict' + ) -> str: + with open(where(), encoding=encoding) as data: + return data.read() + + # If we don't have importlib.resources, then we will just do the old logic + # of assuming we're on the filesystem and munge the path directly. + def where() -> str: + f = os.path.dirname(__file__) + + return os.path.join(f, "cacert.pem") + + def contents() -> str: + return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/venv/lib/python3.12/site-packages/certifi/py.typed b/venv/lib/python3.12/site-packages/certifi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/LICENSE b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/LICENSE new file mode 100644 index 0000000..ad82355 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 TAHRI Ahmed R. + +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. \ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/METADATA b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/METADATA new file mode 100644 index 0000000..822550e --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/METADATA @@ -0,0 +1,683 @@ +Metadata-Version: 2.1 +Name: charset-normalizer +Version: 3.3.2 +Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. +Home-page: https://github.com/Ousret/charset_normalizer +Author: Ahmed TAHRI +Author-email: ahmed.tahri@cloudnursery.dev +License: MIT +Project-URL: Bug Reports, https://github.com/Ousret/charset_normalizer/issues +Project-URL: Documentation, https://charset-normalizer.readthedocs.io/en/latest +Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: MIT License +Classifier: Intended Audience :: Developers +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +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 :: Implementation :: PyPy +Classifier: Topic :: Text Processing :: Linguistic +Classifier: Topic :: Utilities +Classifier: Typing :: Typed +Requires-Python: >=3.7.0 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: unicode_backport + +

Charset Detection, for Everyone 👋

+ +

+ The Real First Universal Charset Detector
+ + + + + Download Count Total + + + + +

+

+ Featured Packages
+ + Static Badge + + + Static Badge + +

+

+ In other language (unofficial port - by the community)
+ + Static Badge + +

+ +> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`, +> I'm trying to resolve the issue by taking a new approach. +> All IANA character set names for which the Python core library provides codecs are supported. + +

+ >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< +

+ +This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. + +| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | +|--------------------------------------------------|:---------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:-----------------------------------------------:| +| `Fast` | ❌ | ✅ | ✅ | +| `Universal**` | ❌ | ✅ | ❌ | +| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ | +| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | +| `License` | LGPL-2.1
_restrictive_ | MIT | MPL-1.1
_restrictive_ | +| `Native Python` | ✅ | ✅ | ❌ | +| `Detect spoken language` | ❌ | ✅ | N/A | +| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ | +| `Whl Size (min)` | 193.6 kB | 42 kB | ~200 kB | +| `Supported Encoding` | 33 | 🎉 [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 | + +

+Reading Normalized TextCat Reading Text +

+ +*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
+Did you got there because of the logs? See [https://charset-normalizer.readthedocs.io/en/latest/user/miscellaneous.html](https://charset-normalizer.readthedocs.io/en/latest/user/miscellaneous.html) + +## ⚡ Performance + +This package offer better performance than its counterpart Chardet. Here are some numbers. + +| Package | Accuracy | Mean per file (ms) | File per sec (est) | +|-----------------------------------------------|:--------:|:------------------:|:------------------:| +| [chardet](https://github.com/chardet/chardet) | 86 % | 200 ms | 5 file/sec | +| charset-normalizer | **98 %** | **10 ms** | 100 file/sec | + +| Package | 99th percentile | 95th percentile | 50th percentile | +|-----------------------------------------------|:---------------:|:---------------:|:---------------:| +| [chardet](https://github.com/chardet/chardet) | 1200 ms | 287 ms | 23 ms | +| charset-normalizer | 100 ms | 50 ms | 5 ms | + +Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload. + +> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. +> And yes, these results might change at any time. The dataset can be updated to include more files. +> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. +> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability +> (eg. Supported Encoding) Challenge-them if you want. + +## ✨ Installation + +Using pip: + +```sh +pip install charset-normalizer -U +``` + +## 🚀 Basic Usage + +### CLI +This package comes with a CLI. + +``` +usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] + file [file ...] + +The Real First Universal Charset Detector. Discover originating encoding used +on text file. Normalize text to unicode. + +positional arguments: + files File(s) to be analysed + +optional arguments: + -h, --help show this help message and exit + -v, --verbose Display complementary information about file if any. + Stdout will contain logs about the detection process. + -a, --with-alternative + Output complementary possibilities if any. Top-level + JSON WILL be a list. + -n, --normalize Permit to normalize input file. If not set, program + does not write anything. + -m, --minimal Only output the charset detected to STDOUT. Disabling + JSON output. + -r, --replace Replace file when trying to normalize it instead of + creating a new one. + -f, --force Replace file without asking if you are sure, use this + flag with caution. + -t THRESHOLD, --threshold THRESHOLD + Define a custom maximum amount of chaos allowed in + decoded content. 0. <= chaos <= 1. + --version Show version information and exit. +``` + +```bash +normalizer ./data/sample.1.fr.srt +``` + +or + +```bash +python -m charset_normalizer ./data/sample.1.fr.srt +``` + +🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. + +```json +{ + "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", + "encoding": "cp1252", + "encoding_aliases": [ + "1252", + "windows_1252" + ], + "alternative_encodings": [ + "cp1254", + "cp1256", + "cp1258", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + "mbcs" + ], + "language": "French", + "alphabets": [ + "Basic Latin", + "Latin-1 Supplement" + ], + "has_sig_or_bom": false, + "chaos": 0.149, + "coherence": 97.152, + "unicode_path": null, + "is_preferred": true +} +``` + +### Python +*Just print out normalized text* +```python +from charset_normalizer import from_path + +results = from_path('./my_subtitle.srt') + +print(str(results.best())) +``` + +*Upgrade your code without effort* +```python +from charset_normalizer import detect +``` + +The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. + +See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) + +## 😇 Why + +When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a +reliable alternative using a completely different method. Also! I never back down on a good challenge! + +I **don't care** about the **originating charset** encoding, because **two different tables** can +produce **two identical rendered string.** +What I want is to get readable text, the best I can. + +In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 + +Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. + +## 🍰 How + + - Discard all charset encoding table that could not fit the binary content. + - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding. + - Extract matches with the lowest mess detected. + - Additionally, we measure coherence / probe for a language. + +**Wait a minute**, what is noise/mess and coherence according to **YOU ?** + +*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then +**I established** some ground rules about **what is obvious** when **it seems like** a mess. + I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to + improve or rewrite it. + +*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought +that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. + +## ⚡ Known limitations + + - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) + - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. + +## ⚠️ About Python EOLs + +**If you are running:** + +- Python >=2.7,<3.5: Unsupported +- Python 3.5: charset-normalizer < 2.1 +- Python 3.6: charset-normalizer < 3.1 +- Python 3.7: charset-normalizer < 4.0 + +Upgrade your Python interpreter as soon as possible. + +## 👤 Contributing + +Contributions, issues and feature requests are very much welcome.
+Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. + +## 📝 License + +Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
+This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. + +Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) + +## 💼 For Enterprise + +Professional support for charset-normalizer is available as part of the [Tidelift +Subscription][1]. Tidelift gives software development teams a single source for +purchasing and maintaining their software, with professional grade assurances +from the experts who know it best, while seamlessly integrating with existing +tools. + +[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme + +# Changelog +All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31) + +### Fixed +- Unintentional memory usage regression when using large payload that match several encoding (#376) +- Regression on some detection case showcased in the documentation (#371) + +### Added +- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife) + +## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22) + +### Changed +- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8 +- Improved the general detection reliability based on reports from the community + +## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30) + +### Added +- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer` +- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323) + +### Removed +- (internal) Redundant utils.is_ascii function and unused function is_private_use_only +- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant + +### Changed +- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection +- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8 + +### Fixed +- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350) + +## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07) + +### Changed +- Typehint for function `from_path` no longer enforce `PathLike` as its first argument +- Minor improvement over the global detection reliability + +### Added +- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries +- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True) +- Explicit support for Python 3.12 + +### Fixed +- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289) + +## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06) + +### Added +- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262) + +### Removed +- Support for Python 3.6 (PR #260) + +### Changed +- Optional speedup provided by mypy/c 1.0.1 + +## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18) + +### Fixed +- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233) + +### Changed +- Speedup provided by mypy/c 0.990 on Python >= 3.7 + +## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20) + +### Added +- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results +- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES +- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio +- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) + +### Changed +- Build with static metadata using 'build' frontend +- Make the language detection stricter +- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 + +### Fixed +- CLI with opt --normalize fail when using full path for files +- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it +- Sphinx warnings when generating the documentation + +### Removed +- Coherence detector no longer return 'Simple English' instead return 'English' +- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' +- Breaking: Method `first()` and `best()` from CharsetMatch +- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) +- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches +- Breaking: Top-level function `normalize` +- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch +- Support for the backport `unicodedata2` + +## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18) + +### Added +- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results +- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES +- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio + +### Changed +- Build with static metadata using 'build' frontend +- Make the language detection stricter + +### Fixed +- CLI with opt --normalize fail when using full path for files +- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it + +### Removed +- Coherence detector no longer return 'Simple English' instead return 'English' +- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' + +## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21) + +### Added +- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) + +### Removed +- Breaking: Method `first()` and `best()` from CharsetMatch +- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) + +### Fixed +- Sphinx warnings when generating the documentation + +## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15) + +### Changed +- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 + +### Removed +- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches +- Breaking: Top-level function `normalize` +- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch +- Support for the backport `unicodedata2` + +## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19) + +### Deprecated +- Function `normalize` scheduled for removal in 3.0 + +### Changed +- Removed useless call to decode in fn is_unprintable (#206) + +### Fixed +- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204) + +## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19) + +### Added +- Output the Unicode table version when running the CLI with `--version` (PR #194) + +### Changed +- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175) +- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183) + +### Fixed +- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175) +- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181) + +### Removed +- Support for Python 3.5 (PR #192) + +### Deprecated +- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194) + +## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12) + +### Fixed +- ASCII miss-detection on rare cases (PR #170) + +## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30) + +### Added +- Explicit support for Python 3.11 (PR #164) + +### Changed +- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165) + +## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04) + +### Fixed +- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154) + +### Changed +- Skipping the language-detection (CD) on ASCII (PR #155) + +## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03) + +### Changed +- Moderating the logging impact (since 2.0.8) for specific environments (PR #147) + +### Fixed +- Wrong logging level applied when setting kwarg `explain` to True (PR #146) + +## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24) +### Changed +- Improvement over Vietnamese detection (PR #126) +- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124) +- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122) +- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129) +- Code style as refactored by Sourcery-AI (PR #131) +- Minor adjustment on the MD around european words (PR #133) +- Remove and replace SRTs from assets / tests (PR #139) +- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135) +- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135) + +### Fixed +- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137) +- Avoid using too insignificant chunk (PR #137) + +### Added +- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135) +- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141) + +## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11) +### Added +- Add support for Kazakh (Cyrillic) language detection (PR #109) + +### Changed +- Further, improve inferring the language from a given single-byte code page (PR #112) +- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116) +- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113) +- Various detection improvement (MD+CD) (PR #117) + +### Removed +- Remove redundant logging entry about detected language(s) (PR #115) + +### Fixed +- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102) + +## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18) +### Fixed +- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100) +- Fix CLI crash when using --minimal output in certain cases (PR #103) + +### Changed +- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101) + +## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14) +### Changed +- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81) +- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82) +- The Unicode detection is slightly improved (PR #93) +- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91) + +### Removed +- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92) + +### Fixed +- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95) +- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96) +- The MANIFEST.in was not exhaustive (PR #78) + +## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30) +### Fixed +- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70) +- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68) +- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72) +- Submatch factoring could be wrong in rare edge cases (PR #72) +- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72) +- Fix line endings from CRLF to LF for certain project files (PR #67) + +### Changed +- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76) +- Allow fallback on specified encoding if any (PR #71) + +## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16) +### Changed +- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63) +- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64) + +## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15) +### Fixed +- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59) + +### Changed +- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57) + +## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13) +### Fixed +- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55) +- Using explain=False permanently disable the verbose output in the current runtime (PR #47) +- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47) +- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52) + +### Changed +- Public function normalize default args values were not aligned with from_bytes (PR #53) + +### Added +- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47) + +## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02) +### Changed +- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet. +- Accent has been made on UTF-8 detection, should perform rather instantaneous. +- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible. +- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time) +- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+ +- utf_7 detection has been reinstated. + +### Removed +- This package no longer require anything when used with Python 3.5 (Dropped cached_property) +- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian. +- The exception hook on UnicodeDecodeError has been removed. + +### Deprecated +- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0 + +### Fixed +- The CLI output used the relative path of the file(s). Should be absolute. + +## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28) +### Fixed +- Logger configuration/usage no longer conflict with others (PR #44) + +## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21) +### Removed +- Using standard logging instead of using the package loguru. +- Dropping nose test framework in favor of the maintained pytest. +- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text. +- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version. +- Stop support for UTF-7 that does not contain a SIG. +- Dropping PrettyTable, replaced with pure JSON output in CLI. + +### Fixed +- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process. +- Not searching properly for the BOM when trying utf32/16 parent codec. + +### Changed +- Improving the package final size by compressing frequencies.json. +- Huge improvement over the larges payload. + +### Added +- CLI now produces JSON consumable output. +- Return ASCII if given sequences fit. Given reasonable confidence. + +## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13) + +### Fixed +- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40) + +## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12) + +### Fixed +- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39) + +## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12) + +### Fixed +- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38) + +## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09) + +### Changed +- Amend the previous release to allow prettytable 2.0 (PR #35) + +## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08) + +### Fixed +- Fix error while using the package with a python pre-release interpreter (PR #33) + +### Changed +- Dependencies refactoring, constraints revised. + +### Added +- Add python 3.9 and 3.10 to the supported interpreters + +MIT License + +Copyright (c) 2019 TAHRI Ahmed R. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/RECORD b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/RECORD new file mode 100644 index 0000000..2f892ce --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/RECORD @@ -0,0 +1,35 @@ +../../../bin/normalizer,sha256=b22tssr0xPqRG8jFDVdmhYAoL8oJ-SGHfennG9cdI8I,283 +charset_normalizer-3.3.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +charset_normalizer-3.3.2.dist-info/LICENSE,sha256=6zGgxaT7Cbik4yBV0lweX5w1iidS_vPNcgIT0cz-4kE,1070 +charset_normalizer-3.3.2.dist-info/METADATA,sha256=cfLhl5A6SI-F0oclm8w8ux9wshL1nipdeCdVnYb4AaA,33550 +charset_normalizer-3.3.2.dist-info/RECORD,, +charset_normalizer-3.3.2.dist-info/WHEEL,sha256=FCrbbeH_Uuw2ZMaB8nW-JE7XeUWVfF-XtWcVJYU0Zm8,110 +charset_normalizer-3.3.2.dist-info/entry_points.txt,sha256=ADSTKrkXZ3hhdOVFi6DcUEHQRS0xfxDIE_pEz4wLIXA,65 +charset_normalizer-3.3.2.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19 +charset_normalizer/__init__.py,sha256=UzI3xC8PhmcLRMzSgPb6minTmRq0kWznnCBJ8ZCc2XI,1577 +charset_normalizer/__main__.py,sha256=JxY8bleaENOFlLRb9HfoeZCzAMnn2A1oGR5Xm2eyqg0,73 +charset_normalizer/__pycache__/__init__.cpython-312.pyc,, +charset_normalizer/__pycache__/__main__.cpython-312.pyc,, +charset_normalizer/__pycache__/api.cpython-312.pyc,, +charset_normalizer/__pycache__/cd.cpython-312.pyc,, +charset_normalizer/__pycache__/constant.cpython-312.pyc,, +charset_normalizer/__pycache__/legacy.cpython-312.pyc,, +charset_normalizer/__pycache__/md.cpython-312.pyc,, +charset_normalizer/__pycache__/models.cpython-312.pyc,, +charset_normalizer/__pycache__/utils.cpython-312.pyc,, +charset_normalizer/__pycache__/version.cpython-312.pyc,, +charset_normalizer/api.py,sha256=WOlWjy6wT8SeMYFpaGbXZFN1TMXa-s8vZYfkL4G29iQ,21097 +charset_normalizer/cd.py,sha256=xwZliZcTQFA3jU0c00PRiu9MNxXTFxQkFLWmMW24ZzI,12560 +charset_normalizer/cli/__init__.py,sha256=D5ERp8P62llm2FuoMzydZ7d9rs8cvvLXqE-1_6oViPc,100 +charset_normalizer/cli/__main__.py,sha256=2F-xURZJzo063Ye-2RLJ2wcmURpbKeAzKwpiws65dAs,9744 +charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc,, +charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc,, +charset_normalizer/constant.py,sha256=p0IsOVcEbPWYPOdWhnhRbjK1YVBy6fs05C5vKC-zoxU,40481 +charset_normalizer/legacy.py,sha256=T-QuVMsMeDiQEk8WSszMrzVJg_14AMeSkmHdRYhdl1k,2071 +charset_normalizer/md.cpython-312-darwin.so,sha256=gn0KHqCaBQKs1NXXD-KhWWZuIsln7MbSyMHBRQzgzK8,50117 +charset_normalizer/md.py,sha256=NkSuVLK13_a8c7BxZ4cGIQ5vOtGIWOdh22WZEvjp-7U,19624 +charset_normalizer/md__mypyc.cpython-312-darwin.so,sha256=6gGafMj9_ZMZrOf5ONR4lCisR_Rr8DC1dcZXuzzrxos,232652 +charset_normalizer/models.py,sha256=I5i0s4aKCCgLPY2tUY3pwkgFA-BUbbNxQ7hVkVTt62s,11624 +charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +charset_normalizer/utils.py,sha256=teiosMqzKjXyAHXnGdjSBOgnBZwx-SkBbCLrx0UXy8M,11894 +charset_normalizer/version.py,sha256=iHKUfHD3kDRSyrh_BN2ojh43TA5-UZQjvbVIEFfpHDs,79 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/WHEEL b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/WHEEL new file mode 100644 index 0000000..2e30bef --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.2) +Root-Is-Purelib: false +Tag: cp312-cp312-macosx_11_0_arm64 + diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/entry_points.txt b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/entry_points.txt new file mode 100644 index 0000000..65619e7 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +normalizer = charset_normalizer.cli:cli_detect diff --git a/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/top_level.txt new file mode 100644 index 0000000..66958f0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer-3.3.2.dist-info/top_level.txt @@ -0,0 +1 @@ +charset_normalizer diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__init__.py b/venv/lib/python3.12/site-packages/charset_normalizer/__init__.py new file mode 100644 index 0000000..55991fc --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/__init__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +Charset-Normalizer +~~~~~~~~~~~~~~ +The Real First Universal Charset Detector. +A library that helps you read text from an unknown charset encoding. +Motivated by chardet, This package is trying to resolve the issue by taking a new approach. +All IANA character set names for which the Python core library provides codecs are supported. + +Basic usage: + >>> from charset_normalizer import from_bytes + >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) + >>> best_guess = results.best() + >>> str(best_guess) + 'Bсеки човек има право на образование. Oбразованието!' + +Others methods and usages are available - see the full documentation +at . +:copyright: (c) 2021 by Ahmed TAHRI +:license: MIT, see LICENSE for more details. +""" +import logging + +from .api import from_bytes, from_fp, from_path, is_binary +from .legacy import detect +from .models import CharsetMatch, CharsetMatches +from .utils import set_logging_handler +from .version import VERSION, __version__ + +__all__ = ( + "from_fp", + "from_path", + "from_bytes", + "is_binary", + "detect", + "CharsetMatch", + "CharsetMatches", + "__version__", + "VERSION", + "set_logging_handler", +) + +# Attach a NullHandler to the top level logger by default +# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library + +logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__main__.py b/venv/lib/python3.12/site-packages/charset_normalizer/__main__.py new file mode 100644 index 0000000..beae2ef --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/__main__.py @@ -0,0 +1,4 @@ +from .cli import cli_detect + +if __name__ == "__main__": + cli_detect() diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aeff71ee317052b345ea89c3c57bc59d12b65710 GIT binary patch literal 1743 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 X$YM!H7E3y^SOR1{TlG*Pmh^uB>RIf9 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e864cab1cbf622432a3b1e299acf78b4cab7e4d0 GIT binary patch literal 13452 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9a80544399e2866318d260d72f48344e48279b6 GIT binary patch literal 38770 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 JI_wMl{tMproc#a* literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62a1c83c722c9b004e6e0dbc88f77252423caeee GIT binary patch literal 24517 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

sSLFTPtD5)o}1LXvLAWBI76ndl$`kXUEo% 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5796a068429045a08da3a5973cb113f16a538879 GIT binary patch literal 16617 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 Jaul;Y{QnW!7*_xQ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ed38ee25f2848f716da958337ee4c467f8f5bf4 GIT binary patch literal 14330 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 F{{<5HsU83T literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4aee067512e4406db445b86f94f80b7af99a2d08 GIT binary patch literal 340 zcmX@j%ge<81Y*bEruhTu#~=<2Fhd!i^?;1&3@Hpz3@MCJjH!%StS}`AI)!O9BZL>l zT*<7-QYFCUT2YW+oT^ZkT2!2wpT||jYOH6hXY`9v&rg%(7JGbrN`7*D{4MVIc&G{> zhqbsMC$r=hdzfobu&2M@N`}uMGk@jjhZX}((Jx8ON-Qo&EXmB#cgasK%}vcKDc1K( zEh*10$}W!gNKDR7EXl~v(=SWSE7Q-(Owuo?1o4ga42|@QGfPr+3qVTJQ;YSJGZKr6 zQ%mCW@{4j4b26(^i-4NI?$j%&{Ka9Do1apelWJE43LTKYiWPyx2WCb_#*a))j4U5G e82H5+xNmTYUgwg&$R$0)`7)P6BYP1CP!#|XUtWU% literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/api.py b/venv/lib/python3.12/site-packages/charset_normalizer/api.py new file mode 100644 index 0000000..0ba08e3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/api.py @@ -0,0 +1,626 @@ +import logging +from os import PathLike +from typing import BinaryIO, List, Optional, Set, Union + +from .cd import ( + coherence_ratio, + encoding_languages, + mb_encoding_languages, + merge_coherence_ratios, +) +from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE +from .md import mess_ratio +from .models import CharsetMatch, CharsetMatches +from .utils import ( + any_specified_encoding, + cut_sequence_chunks, + iana_name, + identify_sig_or_bom, + is_cp_similar, + is_multi_byte_encoding, + should_strip_sig_or_bom, +) + +# Will most likely be controversial +# logging.addLevelName(TRACE, "TRACE") +logger = logging.getLogger("charset_normalizer") +explain_handler = logging.StreamHandler() +explain_handler.setFormatter( + logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") +) + + +def from_bytes( + sequences: Union[bytes, bytearray], + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.2, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Given a raw bytes sequence, return the best possibles charset usable to render str objects. + If there is no results, it is a strong indicator that the source is binary/not text. + By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence. + And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. + + The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page + but never take it for granted. Can improve the performance. + + You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that + purpose. + + This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. + By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' + toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. + Custom logging format and handler can be set manually. + """ + + if not isinstance(sequences, (bytearray, bytes)): + raise TypeError( + "Expected object of type bytes or bytearray, got: {0}".format( + type(sequences) + ) + ) + + if explain: + previous_logger_level: int = logger.level + logger.addHandler(explain_handler) + logger.setLevel(TRACE) + + length: int = len(sequences) + + if length == 0: + logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level or logging.WARNING) + return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) + + if cp_isolation is not None: + logger.log( + TRACE, + "cp_isolation is set. use this flag for debugging purpose. " + "limited list of encoding allowed : %s.", + ", ".join(cp_isolation), + ) + cp_isolation = [iana_name(cp, False) for cp in cp_isolation] + else: + cp_isolation = [] + + if cp_exclusion is not None: + logger.log( + TRACE, + "cp_exclusion is set. use this flag for debugging purpose. " + "limited list of encoding excluded : %s.", + ", ".join(cp_exclusion), + ) + cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] + else: + cp_exclusion = [] + + if length <= (chunk_size * steps): + logger.log( + TRACE, + "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", + steps, + chunk_size, + length, + ) + steps = 1 + chunk_size = length + + if steps > 1 and length / steps < chunk_size: + chunk_size = int(length / steps) + + is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE + is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE + + if is_too_small_sequence: + logger.log( + TRACE, + "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( + length + ), + ) + elif is_too_large_sequence: + logger.log( + TRACE, + "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( + length + ), + ) + + prioritized_encodings: List[str] = [] + + specified_encoding: Optional[str] = ( + any_specified_encoding(sequences) if preemptive_behaviour else None + ) + + if specified_encoding is not None: + prioritized_encodings.append(specified_encoding) + logger.log( + TRACE, + "Detected declarative mark in sequence. Priority +1 given for %s.", + specified_encoding, + ) + + tested: Set[str] = set() + tested_but_hard_failure: List[str] = [] + tested_but_soft_failure: List[str] = [] + + fallback_ascii: Optional[CharsetMatch] = None + fallback_u8: Optional[CharsetMatch] = None + fallback_specified: Optional[CharsetMatch] = None + + results: CharsetMatches = CharsetMatches() + + sig_encoding, sig_payload = identify_sig_or_bom(sequences) + + if sig_encoding is not None: + prioritized_encodings.append(sig_encoding) + logger.log( + TRACE, + "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", + len(sig_payload), + sig_encoding, + ) + + prioritized_encodings.append("ascii") + + if "utf_8" not in prioritized_encodings: + prioritized_encodings.append("utf_8") + + for encoding_iana in prioritized_encodings + IANA_SUPPORTED: + if cp_isolation and encoding_iana not in cp_isolation: + continue + + if cp_exclusion and encoding_iana in cp_exclusion: + continue + + if encoding_iana in tested: + continue + + tested.add(encoding_iana) + + decoded_payload: Optional[str] = None + bom_or_sig_available: bool = sig_encoding == encoding_iana + strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( + encoding_iana + ) + + if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: + logger.log( + TRACE, + "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", + encoding_iana, + ) + continue + if encoding_iana in {"utf_7"} and not bom_or_sig_available: + logger.log( + TRACE, + "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.", + encoding_iana, + ) + continue + + try: + is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) + except (ModuleNotFoundError, ImportError): + logger.log( + TRACE, + "Encoding %s does not provide an IncrementalDecoder", + encoding_iana, + ) + continue + + try: + if is_too_large_sequence and is_multi_byte_decoder is False: + str( + sequences[: int(50e4)] + if strip_sig_or_bom is False + else sequences[len(sig_payload) : int(50e4)], + encoding=encoding_iana, + ) + else: + decoded_payload = str( + sequences + if strip_sig_or_bom is False + else sequences[len(sig_payload) :], + encoding=encoding_iana, + ) + except (UnicodeDecodeError, LookupError) as e: + if not isinstance(e, LookupError): + logger.log( + TRACE, + "Code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + similar_soft_failure_test: bool = False + + for encoding_soft_failed in tested_but_soft_failure: + if is_cp_similar(encoding_iana, encoding_soft_failed): + similar_soft_failure_test = True + break + + if similar_soft_failure_test: + logger.log( + TRACE, + "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", + encoding_iana, + encoding_soft_failed, + ) + continue + + r_ = range( + 0 if not bom_or_sig_available else len(sig_payload), + length, + int(length / steps), + ) + + multi_byte_bonus: bool = ( + is_multi_byte_decoder + and decoded_payload is not None + and len(decoded_payload) < length + ) + + if multi_byte_bonus: + logger.log( + TRACE, + "Code page %s is a multi byte encoding table and it appear that at least one character " + "was encoded using n-bytes.", + encoding_iana, + ) + + max_chunk_gave_up: int = int(len(r_) / 4) + + max_chunk_gave_up = max(max_chunk_gave_up, 2) + early_stop_count: int = 0 + lazy_str_hard_failure = False + + md_chunks: List[str] = [] + md_ratios = [] + + try: + for chunk in cut_sequence_chunks( + sequences, + encoding_iana, + r_, + chunk_size, + bom_or_sig_available, + strip_sig_or_bom, + sig_payload, + is_multi_byte_decoder, + decoded_payload, + ): + md_chunks.append(chunk) + + md_ratios.append( + mess_ratio( + chunk, + threshold, + explain is True and 1 <= len(cp_isolation) <= 2, + ) + ) + + if md_ratios[-1] >= threshold: + early_stop_count += 1 + + if (early_stop_count >= max_chunk_gave_up) or ( + bom_or_sig_available and strip_sig_or_bom is False + ): + break + except ( + UnicodeDecodeError + ) as e: # Lazy str loading may have missed something there + logger.log( + TRACE, + "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + early_stop_count = max_chunk_gave_up + lazy_str_hard_failure = True + + # We might want to check the sequence again with the whole content + # Only if initial MD tests passes + if ( + not lazy_str_hard_failure + and is_too_large_sequence + and not is_multi_byte_decoder + ): + try: + sequences[int(50e3) :].decode(encoding_iana, errors="strict") + except UnicodeDecodeError as e: + logger.log( + TRACE, + "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 + if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: + tested_but_soft_failure.append(encoding_iana) + logger.log( + TRACE, + "%s was excluded because of initial chaos probing. Gave up %i time(s). " + "Computed mean chaos is %f %%.", + encoding_iana, + early_stop_count, + round(mean_mess_ratio * 100, ndigits=3), + ) + # Preparing those fallbacks in case we got nothing. + if ( + enable_fallback + and encoding_iana in ["ascii", "utf_8", specified_encoding] + and not lazy_str_hard_failure + ): + fallback_entry = CharsetMatch( + sequences, encoding_iana, threshold, False, [], decoded_payload + ) + if encoding_iana == specified_encoding: + fallback_specified = fallback_entry + elif encoding_iana == "ascii": + fallback_ascii = fallback_entry + else: + fallback_u8 = fallback_entry + continue + + logger.log( + TRACE, + "%s passed initial chaos probing. Mean measured chaos is %f %%", + encoding_iana, + round(mean_mess_ratio * 100, ndigits=3), + ) + + if not is_multi_byte_decoder: + target_languages: List[str] = encoding_languages(encoding_iana) + else: + target_languages = mb_encoding_languages(encoding_iana) + + if target_languages: + logger.log( + TRACE, + "{} should target any language(s) of {}".format( + encoding_iana, str(target_languages) + ), + ) + + cd_ratios = [] + + # We shall skip the CD when its about ASCII + # Most of the time its not relevant to run "language-detection" on it. + if encoding_iana != "ascii": + for chunk in md_chunks: + chunk_languages = coherence_ratio( + chunk, + language_threshold, + ",".join(target_languages) if target_languages else None, + ) + + cd_ratios.append(chunk_languages) + + cd_ratios_merged = merge_coherence_ratios(cd_ratios) + + if cd_ratios_merged: + logger.log( + TRACE, + "We detected language {} using {}".format( + cd_ratios_merged, encoding_iana + ), + ) + + results.append( + CharsetMatch( + sequences, + encoding_iana, + mean_mess_ratio, + bom_or_sig_available, + cd_ratios_merged, + decoded_payload, + ) + ) + + if ( + encoding_iana in [specified_encoding, "ascii", "utf_8"] + and mean_mess_ratio < 0.1 + ): + logger.debug( + "Encoding detection: %s is most likely the one.", encoding_iana + ) + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([results[encoding_iana]]) + + if encoding_iana == sig_encoding: + logger.debug( + "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " + "the beginning of the sequence.", + encoding_iana, + ) + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([results[encoding_iana]]) + + if len(results) == 0: + if fallback_u8 or fallback_ascii or fallback_specified: + logger.log( + TRACE, + "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", + ) + + if fallback_specified: + logger.debug( + "Encoding detection: %s will be used as a fallback match", + fallback_specified.encoding, + ) + results.append(fallback_specified) + elif ( + (fallback_u8 and fallback_ascii is None) + or ( + fallback_u8 + and fallback_ascii + and fallback_u8.fingerprint != fallback_ascii.fingerprint + ) + or (fallback_u8 is not None) + ): + logger.debug("Encoding detection: utf_8 will be used as a fallback match") + results.append(fallback_u8) + elif fallback_ascii: + logger.debug("Encoding detection: ascii will be used as a fallback match") + results.append(fallback_ascii) + + if results: + logger.debug( + "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", + results.best().encoding, # type: ignore + len(results) - 1, + ) + else: + logger.debug("Encoding detection: Unable to determine any suitable charset.") + + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + + return results + + +def from_fp( + fp: BinaryIO, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but using a file pointer that is already ready. + Will not close the file pointer. + """ + return from_bytes( + fp.read(), + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + language_threshold, + enable_fallback, + ) + + +def from_path( + path: Union[str, bytes, PathLike], # type: ignore[type-arg] + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. + Can raise IOError. + """ + with open(path, "rb") as fp: + return from_fp( + fp, + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + language_threshold, + enable_fallback, + ) + + +def is_binary( + fp_or_path_or_payload: Union[PathLike, str, BinaryIO, bytes], # type: ignore[type-arg] + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: Optional[List[str]] = None, + cp_exclusion: Optional[List[str]] = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = False, +) -> bool: + """ + Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string. + Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match + are disabled to be stricter around ASCII-compatible but unlikely to be a string. + """ + if isinstance(fp_or_path_or_payload, (str, PathLike)): + guesses = from_path( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + elif isinstance( + fp_or_path_or_payload, + ( + bytes, + bytearray, + ), + ): + guesses = from_bytes( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + else: + guesses = from_fp( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + + return not guesses diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/cd.py b/venv/lib/python3.12/site-packages/charset_normalizer/cd.py new file mode 100644 index 0000000..4ea6760 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/cd.py @@ -0,0 +1,395 @@ +import importlib +from codecs import IncrementalDecoder +from collections import Counter +from functools import lru_cache +from typing import Counter as TypeCounter, Dict, List, Optional, Tuple + +from .constant import ( + FREQUENCIES, + KO_NAMES, + LANGUAGE_SUPPORTED_COUNT, + TOO_SMALL_SEQUENCE, + ZH_NAMES, +) +from .md import is_suspiciously_successive_range +from .models import CoherenceMatches +from .utils import ( + is_accentuated, + is_latin, + is_multi_byte_encoding, + is_unicode_range_secondary, + unicode_range, +) + + +def encoding_unicode_range(iana_name: str) -> List[str]: + """ + Return associated unicode ranges in a single byte code page. + """ + if is_multi_byte_encoding(iana_name): + raise IOError("Function not supported on multi-byte code page") + + decoder = importlib.import_module( + "encodings.{}".format(iana_name) + ).IncrementalDecoder + + p: IncrementalDecoder = decoder(errors="ignore") + seen_ranges: Dict[str, int] = {} + character_count: int = 0 + + for i in range(0x40, 0xFF): + chunk: str = p.decode(bytes([i])) + + if chunk: + character_range: Optional[str] = unicode_range(chunk) + + if character_range is None: + continue + + if is_unicode_range_secondary(character_range) is False: + if character_range not in seen_ranges: + seen_ranges[character_range] = 0 + seen_ranges[character_range] += 1 + character_count += 1 + + return sorted( + [ + character_range + for character_range in seen_ranges + if seen_ranges[character_range] / character_count >= 0.15 + ] + ) + + +def unicode_range_languages(primary_range: str) -> List[str]: + """ + Return inferred languages used with a unicode range. + """ + languages: List[str] = [] + + for language, characters in FREQUENCIES.items(): + for character in characters: + if unicode_range(character) == primary_range: + languages.append(language) + break + + return languages + + +@lru_cache() +def encoding_languages(iana_name: str) -> List[str]: + """ + Single-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + unicode_ranges: List[str] = encoding_unicode_range(iana_name) + primary_range: Optional[str] = None + + for specified_range in unicode_ranges: + if "Latin" not in specified_range: + primary_range = specified_range + break + + if primary_range is None: + return ["Latin Based"] + + return unicode_range_languages(primary_range) + + +@lru_cache() +def mb_encoding_languages(iana_name: str) -> List[str]: + """ + Multi-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + if ( + iana_name.startswith("shift_") + or iana_name.startswith("iso2022_jp") + or iana_name.startswith("euc_j") + or iana_name == "cp932" + ): + return ["Japanese"] + if iana_name.startswith("gb") or iana_name in ZH_NAMES: + return ["Chinese"] + if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: + return ["Korean"] + + return [] + + +@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) +def get_target_features(language: str) -> Tuple[bool, bool]: + """ + Determine main aspects from a supported language if it contains accents and if is pure Latin. + """ + target_have_accents: bool = False + target_pure_latin: bool = True + + for character in FREQUENCIES[language]: + if not target_have_accents and is_accentuated(character): + target_have_accents = True + if target_pure_latin and is_latin(character) is False: + target_pure_latin = False + + return target_have_accents, target_pure_latin + + +def alphabet_languages( + characters: List[str], ignore_non_latin: bool = False +) -> List[str]: + """ + Return associated languages associated to given characters. + """ + languages: List[Tuple[str, float]] = [] + + source_have_accents = any(is_accentuated(character) for character in characters) + + for language, language_characters in FREQUENCIES.items(): + target_have_accents, target_pure_latin = get_target_features(language) + + if ignore_non_latin and target_pure_latin is False: + continue + + if target_have_accents is False and source_have_accents: + continue + + character_count: int = len(language_characters) + + character_match_count: int = len( + [c for c in language_characters if c in characters] + ) + + ratio: float = character_match_count / character_count + + if ratio >= 0.2: + languages.append((language, ratio)) + + languages = sorted(languages, key=lambda x: x[1], reverse=True) + + return [compatible_language[0] for compatible_language in languages] + + +def characters_popularity_compare( + language: str, ordered_characters: List[str] +) -> float: + """ + Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. + The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). + Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) + """ + if language not in FREQUENCIES: + raise ValueError("{} not available".format(language)) + + character_approved_count: int = 0 + FREQUENCIES_language_set = set(FREQUENCIES[language]) + + ordered_characters_count: int = len(ordered_characters) + target_language_characters_count: int = len(FREQUENCIES[language]) + + large_alphabet: bool = target_language_characters_count > 26 + + for character, character_rank in zip( + ordered_characters, range(0, ordered_characters_count) + ): + if character not in FREQUENCIES_language_set: + continue + + character_rank_in_language: int = FREQUENCIES[language].index(character) + expected_projection_ratio: float = ( + target_language_characters_count / ordered_characters_count + ) + character_rank_projection: int = int(character_rank * expected_projection_ratio) + + if ( + large_alphabet is False + and abs(character_rank_projection - character_rank_in_language) > 4 + ): + continue + + if ( + large_alphabet is True + and abs(character_rank_projection - character_rank_in_language) + < target_language_characters_count / 3 + ): + character_approved_count += 1 + continue + + characters_before_source: List[str] = FREQUENCIES[language][ + 0:character_rank_in_language + ] + characters_after_source: List[str] = FREQUENCIES[language][ + character_rank_in_language: + ] + characters_before: List[str] = ordered_characters[0:character_rank] + characters_after: List[str] = ordered_characters[character_rank:] + + before_match_count: int = len( + set(characters_before) & set(characters_before_source) + ) + + after_match_count: int = len( + set(characters_after) & set(characters_after_source) + ) + + if len(characters_before_source) == 0 and before_match_count <= 4: + character_approved_count += 1 + continue + + if len(characters_after_source) == 0 and after_match_count <= 4: + character_approved_count += 1 + continue + + if ( + before_match_count / len(characters_before_source) >= 0.4 + or after_match_count / len(characters_after_source) >= 0.4 + ): + character_approved_count += 1 + continue + + return character_approved_count / len(ordered_characters) + + +def alpha_unicode_split(decoded_sequence: str) -> List[str]: + """ + Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. + Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; + One containing the latin letters and the other hebrew. + """ + layers: Dict[str, str] = {} + + for character in decoded_sequence: + if character.isalpha() is False: + continue + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + continue + + layer_target_range: Optional[str] = None + + for discovered_range in layers: + if ( + is_suspiciously_successive_range(discovered_range, character_range) + is False + ): + layer_target_range = discovered_range + break + + if layer_target_range is None: + layer_target_range = character_range + + if layer_target_range not in layers: + layers[layer_target_range] = character.lower() + continue + + layers[layer_target_range] += character.lower() + + return list(layers.values()) + + +def merge_coherence_ratios(results: List[CoherenceMatches]) -> CoherenceMatches: + """ + This function merge results previously given by the function coherence_ratio. + The return type is the same as coherence_ratio. + """ + per_language_ratios: Dict[str, List[float]] = {} + for result in results: + for sub_result in result: + language, ratio = sub_result + if language not in per_language_ratios: + per_language_ratios[language] = [ratio] + continue + per_language_ratios[language].append(ratio) + + merge = [ + ( + language, + round( + sum(per_language_ratios[language]) / len(per_language_ratios[language]), + 4, + ), + ) + for language in per_language_ratios + ] + + return sorted(merge, key=lambda x: x[1], reverse=True) + + +def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches: + """ + We shall NOT return "English—" in CoherenceMatches because it is an alternative + of "English". This function only keeps the best match and remove the em-dash in it. + """ + index_results: Dict[str, List[float]] = dict() + + for result in results: + language, ratio = result + no_em_name: str = language.replace("—", "") + + if no_em_name not in index_results: + index_results[no_em_name] = [] + + index_results[no_em_name].append(ratio) + + if any(len(index_results[e]) > 1 for e in index_results): + filtered_results: CoherenceMatches = [] + + for language in index_results: + filtered_results.append((language, max(index_results[language]))) + + return filtered_results + + return results + + +@lru_cache(maxsize=2048) +def coherence_ratio( + decoded_sequence: str, threshold: float = 0.1, lg_inclusion: Optional[str] = None +) -> CoherenceMatches: + """ + Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. + A layer = Character extraction by alphabets/ranges. + """ + + results: List[Tuple[str, float]] = [] + ignore_non_latin: bool = False + + sufficient_match_count: int = 0 + + lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] + if "Latin Based" in lg_inclusion_list: + ignore_non_latin = True + lg_inclusion_list.remove("Latin Based") + + for layer in alpha_unicode_split(decoded_sequence): + sequence_frequencies: TypeCounter[str] = Counter(layer) + most_common = sequence_frequencies.most_common() + + character_count: int = sum(o for c, o in most_common) + + if character_count <= TOO_SMALL_SEQUENCE: + continue + + popular_character_ordered: List[str] = [c for c, o in most_common] + + for language in lg_inclusion_list or alphabet_languages( + popular_character_ordered, ignore_non_latin + ): + ratio: float = characters_popularity_compare( + language, popular_character_ordered + ) + + if ratio < threshold: + continue + elif ratio >= 0.8: + sufficient_match_count += 1 + + results.append((language, round(ratio, 4))) + + if sufficient_match_count >= 3: + break + + return sorted( + filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True + ) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py new file mode 100644 index 0000000..d95fedf --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py @@ -0,0 +1,6 @@ +from .__main__ import cli_detect, query_yes_no + +__all__ = ( + "cli_detect", + "query_yes_no", +) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py new file mode 100644 index 0000000..f4bcbaa --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py @@ -0,0 +1,296 @@ +import argparse +import sys +from json import dumps +from os.path import abspath, basename, dirname, join, realpath +from platform import python_version +from typing import List, Optional +from unicodedata import unidata_version + +import charset_normalizer.md as md_module +from charset_normalizer import from_fp +from charset_normalizer.models import CliDetectionResult +from charset_normalizer.version import __version__ + + +def query_yes_no(question: str, default: str = "yes") -> bool: + """Ask a yes/no question via input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits . + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is True for "yes" or False for "no". + + Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input + """ + valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} + if default is None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while True: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == "": + return valid[default] + elif choice in valid: + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' " "(or 'y' or 'n').\n") + + +def cli_detect(argv: Optional[List[str]] = None) -> int: + """ + CLI assistant using ARGV and ArgumentParser + :param argv: + :return: 0 if everything is fine, anything else equal trouble + """ + parser = argparse.ArgumentParser( + description="The Real First Universal Charset Detector. " + "Discover originating encoding used on text file. " + "Normalize text to unicode." + ) + + parser.add_argument( + "files", type=argparse.FileType("rb"), nargs="+", help="File(s) to be analysed" + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + default=False, + dest="verbose", + help="Display complementary information about file if any. " + "Stdout will contain logs about the detection process.", + ) + parser.add_argument( + "-a", + "--with-alternative", + action="store_true", + default=False, + dest="alternatives", + help="Output complementary possibilities if any. Top-level JSON WILL be a list.", + ) + parser.add_argument( + "-n", + "--normalize", + action="store_true", + default=False, + dest="normalize", + help="Permit to normalize input file. If not set, program does not write anything.", + ) + parser.add_argument( + "-m", + "--minimal", + action="store_true", + default=False, + dest="minimal", + help="Only output the charset detected to STDOUT. Disabling JSON output.", + ) + parser.add_argument( + "-r", + "--replace", + action="store_true", + default=False, + dest="replace", + help="Replace file when trying to normalize it instead of creating a new one.", + ) + parser.add_argument( + "-f", + "--force", + action="store_true", + default=False, + dest="force", + help="Replace file without asking if you are sure, use this flag with caution.", + ) + parser.add_argument( + "-t", + "--threshold", + action="store", + default=0.2, + type=float, + dest="threshold", + help="Define a custom maximum amount of chaos allowed in decoded content. 0. <= chaos <= 1.", + ) + parser.add_argument( + "--version", + action="version", + version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format( + __version__, + python_version(), + unidata_version, + "OFF" if md_module.__file__.lower().endswith(".py") else "ON", + ), + help="Show version information and exit.", + ) + + args = parser.parse_args(argv) + + if args.replace is True and args.normalize is False: + print("Use --replace in addition of --normalize only.", file=sys.stderr) + return 1 + + if args.force is True and args.replace is False: + print("Use --force in addition of --replace only.", file=sys.stderr) + return 1 + + if args.threshold < 0.0 or args.threshold > 1.0: + print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) + return 1 + + x_ = [] + + for my_file in args.files: + matches = from_fp(my_file, threshold=args.threshold, explain=args.verbose) + + best_guess = matches.best() + + if best_guess is None: + print( + 'Unable to identify originating encoding for "{}". {}'.format( + my_file.name, + "Maybe try increasing maximum amount of chaos." + if args.threshold < 1.0 + else "", + ), + file=sys.stderr, + ) + x_.append( + CliDetectionResult( + abspath(my_file.name), + None, + [], + [], + "Unknown", + [], + False, + 1.0, + 0.0, + None, + True, + ) + ) + else: + x_.append( + CliDetectionResult( + abspath(my_file.name), + best_guess.encoding, + best_guess.encoding_aliases, + [ + cp + for cp in best_guess.could_be_from_charset + if cp != best_guess.encoding + ], + best_guess.language, + best_guess.alphabets, + best_guess.bom, + best_guess.percent_chaos, + best_guess.percent_coherence, + None, + True, + ) + ) + + if len(matches) > 1 and args.alternatives: + for el in matches: + if el != best_guess: + x_.append( + CliDetectionResult( + abspath(my_file.name), + el.encoding, + el.encoding_aliases, + [ + cp + for cp in el.could_be_from_charset + if cp != el.encoding + ], + el.language, + el.alphabets, + el.bom, + el.percent_chaos, + el.percent_coherence, + None, + False, + ) + ) + + if args.normalize is True: + if best_guess.encoding.startswith("utf") is True: + print( + '"{}" file does not need to be normalized, as it already came from unicode.'.format( + my_file.name + ), + file=sys.stderr, + ) + if my_file.closed is False: + my_file.close() + continue + + dir_path = dirname(realpath(my_file.name)) + file_name = basename(realpath(my_file.name)) + + o_: List[str] = file_name.split(".") + + if args.replace is False: + o_.insert(-1, best_guess.encoding) + if my_file.closed is False: + my_file.close() + elif ( + args.force is False + and query_yes_no( + 'Are you sure to normalize "{}" by replacing it ?'.format( + my_file.name + ), + "no", + ) + is False + ): + if my_file.closed is False: + my_file.close() + continue + + try: + x_[0].unicode_path = join(dir_path, ".".join(o_)) + + with open(x_[0].unicode_path, "w", encoding="utf-8") as fp: + fp.write(str(best_guess)) + except IOError as e: + print(str(e), file=sys.stderr) + if my_file.closed is False: + my_file.close() + return 2 + + if my_file.closed is False: + my_file.close() + + if args.minimal is False: + print( + dumps( + [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, + ensure_ascii=True, + indent=4, + ) + ) + else: + for my_file in args.files: + print( + ", ".join( + [ + el.encoding or "undefined" + for el in x_ + if el.path == abspath(my_file.name) + ] + ) + ) + + return 0 + + +if __name__ == "__main__": + cli_detect() diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..681decdbb809845991e1b7b3784285276fbf21a0 GIT binary patch literal 301 zcmXv~u};G<5Vf61jS3YT;ukUy3s?~o15-DaEGLs3t*Pw<+bIegU%@xd+Xs0c&<7du zNrhHLZRBlJbrxL=a*pw(@v8uLs#>YIY@A%9TT7!KWZRGas<^n6K}S4q$H)SMtd`0L zjI@Kd%IH`0l9rSJ+UW>TwEaH2woTm`yz%2B##6!x(Kg|nf3sqnCP(6J;xp>~0lGR@ AFaQ7m literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc b/venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1891e976e5788fee8a6b3324c71da4e2a67a3b0 GIT binary patch literal 10402 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/constant.py b/venv/lib/python3.12/site-packages/charset_normalizer/constant.py new file mode 100644 index 0000000..8634904 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/constant.py @@ -0,0 +1,1995 @@ +# -*- coding: utf-8 -*- +from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE +from encodings.aliases import aliases +from re import IGNORECASE, compile as re_compile +from typing import Dict, List, Set, Union + +# Contain for each eligible encoding a list of/item bytes SIG/BOM +ENCODING_MARKS: Dict[str, Union[bytes, List[bytes]]] = { + "utf_8": BOM_UTF8, + "utf_7": [ + b"\x2b\x2f\x76\x38", + b"\x2b\x2f\x76\x39", + b"\x2b\x2f\x76\x2b", + b"\x2b\x2f\x76\x2f", + b"\x2b\x2f\x76\x38\x2d", + ], + "gb18030": b"\x84\x31\x95\x33", + "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], + "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], +} + +TOO_SMALL_SEQUENCE: int = 32 +TOO_BIG_SEQUENCE: int = int(10e6) + +UTF8_MAXIMAL_ALLOCATION: int = 1_112_064 + +# Up-to-date Unicode ucd/15.0.0 +UNICODE_RANGES_COMBINED: Dict[str, range] = { + "Control character": range(32), + "Basic Latin": range(32, 128), + "Latin-1 Supplement": range(128, 256), + "Latin Extended-A": range(256, 384), + "Latin Extended-B": range(384, 592), + "IPA Extensions": range(592, 688), + "Spacing Modifier Letters": range(688, 768), + "Combining Diacritical Marks": range(768, 880), + "Greek and Coptic": range(880, 1024), + "Cyrillic": range(1024, 1280), + "Cyrillic Supplement": range(1280, 1328), + "Armenian": range(1328, 1424), + "Hebrew": range(1424, 1536), + "Arabic": range(1536, 1792), + "Syriac": range(1792, 1872), + "Arabic Supplement": range(1872, 1920), + "Thaana": range(1920, 1984), + "NKo": range(1984, 2048), + "Samaritan": range(2048, 2112), + "Mandaic": range(2112, 2144), + "Syriac Supplement": range(2144, 2160), + "Arabic Extended-B": range(2160, 2208), + "Arabic Extended-A": range(2208, 2304), + "Devanagari": range(2304, 2432), + "Bengali": range(2432, 2560), + "Gurmukhi": range(2560, 2688), + "Gujarati": range(2688, 2816), + "Oriya": range(2816, 2944), + "Tamil": range(2944, 3072), + "Telugu": range(3072, 3200), + "Kannada": range(3200, 3328), + "Malayalam": range(3328, 3456), + "Sinhala": range(3456, 3584), + "Thai": range(3584, 3712), + "Lao": range(3712, 3840), + "Tibetan": range(3840, 4096), + "Myanmar": range(4096, 4256), + "Georgian": range(4256, 4352), + "Hangul Jamo": range(4352, 4608), + "Ethiopic": range(4608, 4992), + "Ethiopic Supplement": range(4992, 5024), + "Cherokee": range(5024, 5120), + "Unified Canadian Aboriginal Syllabics": range(5120, 5760), + "Ogham": range(5760, 5792), + "Runic": range(5792, 5888), + "Tagalog": range(5888, 5920), + "Hanunoo": range(5920, 5952), + "Buhid": range(5952, 5984), + "Tagbanwa": range(5984, 6016), + "Khmer": range(6016, 6144), + "Mongolian": range(6144, 6320), + "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400), + "Limbu": range(6400, 6480), + "Tai Le": range(6480, 6528), + "New Tai Lue": range(6528, 6624), + "Khmer Symbols": range(6624, 6656), + "Buginese": range(6656, 6688), + "Tai Tham": range(6688, 6832), + "Combining Diacritical Marks Extended": range(6832, 6912), + "Balinese": range(6912, 7040), + "Sundanese": range(7040, 7104), + "Batak": range(7104, 7168), + "Lepcha": range(7168, 7248), + "Ol Chiki": range(7248, 7296), + "Cyrillic Extended-C": range(7296, 7312), + "Georgian Extended": range(7312, 7360), + "Sundanese Supplement": range(7360, 7376), + "Vedic Extensions": range(7376, 7424), + "Phonetic Extensions": range(7424, 7552), + "Phonetic Extensions Supplement": range(7552, 7616), + "Combining Diacritical Marks Supplement": range(7616, 7680), + "Latin Extended Additional": range(7680, 7936), + "Greek Extended": range(7936, 8192), + "General Punctuation": range(8192, 8304), + "Superscripts and Subscripts": range(8304, 8352), + "Currency Symbols": range(8352, 8400), + "Combining Diacritical Marks for Symbols": range(8400, 8448), + "Letterlike Symbols": range(8448, 8528), + "Number Forms": range(8528, 8592), + "Arrows": range(8592, 8704), + "Mathematical Operators": range(8704, 8960), + "Miscellaneous Technical": range(8960, 9216), + "Control Pictures": range(9216, 9280), + "Optical Character Recognition": range(9280, 9312), + "Enclosed Alphanumerics": range(9312, 9472), + "Box Drawing": range(9472, 9600), + "Block Elements": range(9600, 9632), + "Geometric Shapes": range(9632, 9728), + "Miscellaneous Symbols": range(9728, 9984), + "Dingbats": range(9984, 10176), + "Miscellaneous Mathematical Symbols-A": range(10176, 10224), + "Supplemental Arrows-A": range(10224, 10240), + "Braille Patterns": range(10240, 10496), + "Supplemental Arrows-B": range(10496, 10624), + "Miscellaneous Mathematical Symbols-B": range(10624, 10752), + "Supplemental Mathematical Operators": range(10752, 11008), + "Miscellaneous Symbols and Arrows": range(11008, 11264), + "Glagolitic": range(11264, 11360), + "Latin Extended-C": range(11360, 11392), + "Coptic": range(11392, 11520), + "Georgian Supplement": range(11520, 11568), + "Tifinagh": range(11568, 11648), + "Ethiopic Extended": range(11648, 11744), + "Cyrillic Extended-A": range(11744, 11776), + "Supplemental Punctuation": range(11776, 11904), + "CJK Radicals Supplement": range(11904, 12032), + "Kangxi Radicals": range(12032, 12256), + "Ideographic Description Characters": range(12272, 12288), + "CJK Symbols and Punctuation": range(12288, 12352), + "Hiragana": range(12352, 12448), + "Katakana": range(12448, 12544), + "Bopomofo": range(12544, 12592), + "Hangul Compatibility Jamo": range(12592, 12688), + "Kanbun": range(12688, 12704), + "Bopomofo Extended": range(12704, 12736), + "CJK Strokes": range(12736, 12784), + "Katakana Phonetic Extensions": range(12784, 12800), + "Enclosed CJK Letters and Months": range(12800, 13056), + "CJK Compatibility": range(13056, 13312), + "CJK Unified Ideographs Extension A": range(13312, 19904), + "Yijing Hexagram Symbols": range(19904, 19968), + "CJK Unified Ideographs": range(19968, 40960), + "Yi Syllables": range(40960, 42128), + "Yi Radicals": range(42128, 42192), + "Lisu": range(42192, 42240), + "Vai": range(42240, 42560), + "Cyrillic Extended-B": range(42560, 42656), + "Bamum": range(42656, 42752), + "Modifier Tone Letters": range(42752, 42784), + "Latin Extended-D": range(42784, 43008), + "Syloti Nagri": range(43008, 43056), + "Common Indic Number Forms": range(43056, 43072), + "Phags-pa": range(43072, 43136), + "Saurashtra": range(43136, 43232), + "Devanagari Extended": range(43232, 43264), + "Kayah Li": range(43264, 43312), + "Rejang": range(43312, 43360), + "Hangul Jamo Extended-A": range(43360, 43392), + "Javanese": range(43392, 43488), + "Myanmar Extended-B": range(43488, 43520), + "Cham": range(43520, 43616), + "Myanmar Extended-A": range(43616, 43648), + "Tai Viet": range(43648, 43744), + "Meetei Mayek Extensions": range(43744, 43776), + "Ethiopic Extended-A": range(43776, 43824), + "Latin Extended-E": range(43824, 43888), + "Cherokee Supplement": range(43888, 43968), + "Meetei Mayek": range(43968, 44032), + "Hangul Syllables": range(44032, 55216), + "Hangul Jamo Extended-B": range(55216, 55296), + "High Surrogates": range(55296, 56192), + "High Private Use Surrogates": range(56192, 56320), + "Low Surrogates": range(56320, 57344), + "Private Use Area": range(57344, 63744), + "CJK Compatibility Ideographs": range(63744, 64256), + "Alphabetic Presentation Forms": range(64256, 64336), + "Arabic Presentation Forms-A": range(64336, 65024), + "Variation Selectors": range(65024, 65040), + "Vertical Forms": range(65040, 65056), + "Combining Half Marks": range(65056, 65072), + "CJK Compatibility Forms": range(65072, 65104), + "Small Form Variants": range(65104, 65136), + "Arabic Presentation Forms-B": range(65136, 65280), + "Halfwidth and Fullwidth Forms": range(65280, 65520), + "Specials": range(65520, 65536), + "Linear B Syllabary": range(65536, 65664), + "Linear B Ideograms": range(65664, 65792), + "Aegean Numbers": range(65792, 65856), + "Ancient Greek Numbers": range(65856, 65936), + "Ancient Symbols": range(65936, 66000), + "Phaistos Disc": range(66000, 66048), + "Lycian": range(66176, 66208), + "Carian": range(66208, 66272), + "Coptic Epact Numbers": range(66272, 66304), + "Old Italic": range(66304, 66352), + "Gothic": range(66352, 66384), + "Old Permic": range(66384, 66432), + "Ugaritic": range(66432, 66464), + "Old Persian": range(66464, 66528), + "Deseret": range(66560, 66640), + "Shavian": range(66640, 66688), + "Osmanya": range(66688, 66736), + "Osage": range(66736, 66816), + "Elbasan": range(66816, 66864), + "Caucasian Albanian": range(66864, 66928), + "Vithkuqi": range(66928, 67008), + "Linear A": range(67072, 67456), + "Latin Extended-F": range(67456, 67520), + "Cypriot Syllabary": range(67584, 67648), + "Imperial Aramaic": range(67648, 67680), + "Palmyrene": range(67680, 67712), + "Nabataean": range(67712, 67760), + "Hatran": range(67808, 67840), + "Phoenician": range(67840, 67872), + "Lydian": range(67872, 67904), + "Meroitic Hieroglyphs": range(67968, 68000), + "Meroitic Cursive": range(68000, 68096), + "Kharoshthi": range(68096, 68192), + "Old South Arabian": range(68192, 68224), + "Old North Arabian": range(68224, 68256), + "Manichaean": range(68288, 68352), + "Avestan": range(68352, 68416), + "Inscriptional Parthian": range(68416, 68448), + "Inscriptional Pahlavi": range(68448, 68480), + "Psalter Pahlavi": range(68480, 68528), + "Old Turkic": range(68608, 68688), + "Old Hungarian": range(68736, 68864), + "Hanifi Rohingya": range(68864, 68928), + "Rumi Numeral Symbols": range(69216, 69248), + "Yezidi": range(69248, 69312), + "Arabic Extended-C": range(69312, 69376), + "Old Sogdian": range(69376, 69424), + "Sogdian": range(69424, 69488), + "Old Uyghur": range(69488, 69552), + "Chorasmian": range(69552, 69600), + "Elymaic": range(69600, 69632), + "Brahmi": range(69632, 69760), + "Kaithi": range(69760, 69840), + "Sora Sompeng": range(69840, 69888), + "Chakma": range(69888, 69968), + "Mahajani": range(69968, 70016), + "Sharada": range(70016, 70112), + "Sinhala Archaic Numbers": range(70112, 70144), + "Khojki": range(70144, 70224), + "Multani": range(70272, 70320), + "Khudawadi": range(70320, 70400), + "Grantha": range(70400, 70528), + "Newa": range(70656, 70784), + "Tirhuta": range(70784, 70880), + "Siddham": range(71040, 71168), + "Modi": range(71168, 71264), + "Mongolian Supplement": range(71264, 71296), + "Takri": range(71296, 71376), + "Ahom": range(71424, 71504), + "Dogra": range(71680, 71760), + "Warang Citi": range(71840, 71936), + "Dives Akuru": range(71936, 72032), + "Nandinagari": range(72096, 72192), + "Zanabazar Square": range(72192, 72272), + "Soyombo": range(72272, 72368), + "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384), + "Pau Cin Hau": range(72384, 72448), + "Devanagari Extended-A": range(72448, 72544), + "Bhaiksuki": range(72704, 72816), + "Marchen": range(72816, 72896), + "Masaram Gondi": range(72960, 73056), + "Gunjala Gondi": range(73056, 73136), + "Makasar": range(73440, 73472), + "Kawi": range(73472, 73568), + "Lisu Supplement": range(73648, 73664), + "Tamil Supplement": range(73664, 73728), + "Cuneiform": range(73728, 74752), + "Cuneiform Numbers and Punctuation": range(74752, 74880), + "Early Dynastic Cuneiform": range(74880, 75088), + "Cypro-Minoan": range(77712, 77824), + "Egyptian Hieroglyphs": range(77824, 78896), + "Egyptian Hieroglyph Format Controls": range(78896, 78944), + "Anatolian Hieroglyphs": range(82944, 83584), + "Bamum Supplement": range(92160, 92736), + "Mro": range(92736, 92784), + "Tangsa": range(92784, 92880), + "Bassa Vah": range(92880, 92928), + "Pahawh Hmong": range(92928, 93072), + "Medefaidrin": range(93760, 93856), + "Miao": range(93952, 94112), + "Ideographic Symbols and Punctuation": range(94176, 94208), + "Tangut": range(94208, 100352), + "Tangut Components": range(100352, 101120), + "Khitan Small Script": range(101120, 101632), + "Tangut Supplement": range(101632, 101760), + "Kana Extended-B": range(110576, 110592), + "Kana Supplement": range(110592, 110848), + "Kana Extended-A": range(110848, 110896), + "Small Kana Extension": range(110896, 110960), + "Nushu": range(110960, 111360), + "Duployan": range(113664, 113824), + "Shorthand Format Controls": range(113824, 113840), + "Znamenny Musical Notation": range(118528, 118736), + "Byzantine Musical Symbols": range(118784, 119040), + "Musical Symbols": range(119040, 119296), + "Ancient Greek Musical Notation": range(119296, 119376), + "Kaktovik Numerals": range(119488, 119520), + "Mayan Numerals": range(119520, 119552), + "Tai Xuan Jing Symbols": range(119552, 119648), + "Counting Rod Numerals": range(119648, 119680), + "Mathematical Alphanumeric Symbols": range(119808, 120832), + "Sutton SignWriting": range(120832, 121520), + "Latin Extended-G": range(122624, 122880), + "Glagolitic Supplement": range(122880, 122928), + "Cyrillic Extended-D": range(122928, 123024), + "Nyiakeng Puachue Hmong": range(123136, 123216), + "Toto": range(123536, 123584), + "Wancho": range(123584, 123648), + "Nag Mundari": range(124112, 124160), + "Ethiopic Extended-B": range(124896, 124928), + "Mende Kikakui": range(124928, 125152), + "Adlam": range(125184, 125280), + "Indic Siyaq Numbers": range(126064, 126144), + "Ottoman Siyaq Numbers": range(126208, 126288), + "Arabic Mathematical Alphabetic Symbols": range(126464, 126720), + "Mahjong Tiles": range(126976, 127024), + "Domino Tiles": range(127024, 127136), + "Playing Cards": range(127136, 127232), + "Enclosed Alphanumeric Supplement": range(127232, 127488), + "Enclosed Ideographic Supplement": range(127488, 127744), + "Miscellaneous Symbols and Pictographs": range(127744, 128512), + "Emoticons range(Emoji)": range(128512, 128592), + "Ornamental Dingbats": range(128592, 128640), + "Transport and Map Symbols": range(128640, 128768), + "Alchemical Symbols": range(128768, 128896), + "Geometric Shapes Extended": range(128896, 129024), + "Supplemental Arrows-C": range(129024, 129280), + "Supplemental Symbols and Pictographs": range(129280, 129536), + "Chess Symbols": range(129536, 129648), + "Symbols and Pictographs Extended-A": range(129648, 129792), + "Symbols for Legacy Computing": range(129792, 130048), + "CJK Unified Ideographs Extension B": range(131072, 173792), + "CJK Unified Ideographs Extension C": range(173824, 177984), + "CJK Unified Ideographs Extension D": range(177984, 178208), + "CJK Unified Ideographs Extension E": range(178208, 183984), + "CJK Unified Ideographs Extension F": range(183984, 191472), + "CJK Compatibility Ideographs Supplement": range(194560, 195104), + "CJK Unified Ideographs Extension G": range(196608, 201552), + "CJK Unified Ideographs Extension H": range(201552, 205744), + "Tags": range(917504, 917632), + "Variation Selectors Supplement": range(917760, 918000), + "Supplementary Private Use Area-A": range(983040, 1048576), + "Supplementary Private Use Area-B": range(1048576, 1114112), +} + + +UNICODE_SECONDARY_RANGE_KEYWORD: List[str] = [ + "Supplement", + "Extended", + "Extensions", + "Modifier", + "Marks", + "Punctuation", + "Symbols", + "Forms", + "Operators", + "Miscellaneous", + "Drawing", + "Block", + "Shapes", + "Supplemental", + "Tags", +] + +RE_POSSIBLE_ENCODING_INDICATION = re_compile( + r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", + IGNORECASE, +) + +IANA_NO_ALIASES = [ + "cp720", + "cp737", + "cp856", + "cp874", + "cp875", + "cp1006", + "koi8_r", + "koi8_t", + "koi8_u", +] + +IANA_SUPPORTED: List[str] = sorted( + filter( + lambda x: x.endswith("_codec") is False + and x not in {"rot_13", "tactis", "mbcs"}, + list(set(aliases.values())) + IANA_NO_ALIASES, + ) +) + +IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) + +# pre-computed code page that are similar using the function cp_similarity. +IANA_SUPPORTED_SIMILAR: Dict[str, List[str]] = { + "cp037": ["cp1026", "cp1140", "cp273", "cp500"], + "cp1026": ["cp037", "cp1140", "cp273", "cp500"], + "cp1125": ["cp866"], + "cp1140": ["cp037", "cp1026", "cp273", "cp500"], + "cp1250": ["iso8859_2"], + "cp1251": ["kz1048", "ptcp154"], + "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1253": ["iso8859_7"], + "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1257": ["iso8859_13"], + "cp273": ["cp037", "cp1026", "cp1140", "cp500"], + "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], + "cp500": ["cp037", "cp1026", "cp1140", "cp273"], + "cp850": ["cp437", "cp857", "cp858", "cp865"], + "cp857": ["cp850", "cp858", "cp865"], + "cp858": ["cp437", "cp850", "cp857", "cp865"], + "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], + "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], + "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], + "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], + "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], + "cp866": ["cp1125"], + "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], + "iso8859_11": ["tis_620"], + "iso8859_13": ["cp1257"], + "iso8859_14": [ + "iso8859_10", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_15": [ + "cp1252", + "cp1254", + "iso8859_10", + "iso8859_14", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_16": [ + "iso8859_14", + "iso8859_15", + "iso8859_2", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], + "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], + "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], + "iso8859_7": ["cp1253"], + "iso8859_9": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "latin_1", + ], + "kz1048": ["cp1251", "ptcp154"], + "latin_1": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "iso8859_9", + ], + "mac_iceland": ["mac_roman", "mac_turkish"], + "mac_roman": ["mac_iceland", "mac_turkish"], + "mac_turkish": ["mac_iceland", "mac_roman"], + "ptcp154": ["cp1251", "kz1048"], + "tis_620": ["iso8859_11"], +} + + +CHARDET_CORRESPONDENCE: Dict[str, str] = { + "iso2022_kr": "ISO-2022-KR", + "iso2022_jp": "ISO-2022-JP", + "euc_kr": "EUC-KR", + "tis_620": "TIS-620", + "utf_32": "UTF-32", + "euc_jp": "EUC-JP", + "koi8_r": "KOI8-R", + "iso8859_1": "ISO-8859-1", + "iso8859_2": "ISO-8859-2", + "iso8859_5": "ISO-8859-5", + "iso8859_6": "ISO-8859-6", + "iso8859_7": "ISO-8859-7", + "iso8859_8": "ISO-8859-8", + "utf_16": "UTF-16", + "cp855": "IBM855", + "mac_cyrillic": "MacCyrillic", + "gb2312": "GB2312", + "gb18030": "GB18030", + "cp932": "CP932", + "cp866": "IBM866", + "utf_8": "utf-8", + "utf_8_sig": "UTF-8-SIG", + "shift_jis": "SHIFT_JIS", + "big5": "Big5", + "cp1250": "windows-1250", + "cp1251": "windows-1251", + "cp1252": "Windows-1252", + "cp1253": "windows-1253", + "cp1255": "windows-1255", + "cp1256": "windows-1256", + "cp1254": "Windows-1254", + "cp949": "CP949", +} + + +COMMON_SAFE_ASCII_CHARACTERS: Set[str] = { + "<", + ">", + "=", + ":", + "/", + "&", + ";", + "{", + "}", + "[", + "]", + ",", + "|", + '"', + "-", +} + + +KO_NAMES: Set[str] = {"johab", "cp949", "euc_kr"} +ZH_NAMES: Set[str] = {"big5", "cp950", "big5hkscs", "hz"} + +# Logging LEVEL below DEBUG +TRACE: int = 5 + + +# Language label that contain the em dash "—" +# character are to be considered alternative seq to origin +FREQUENCIES: Dict[str, List[str]] = { + "English": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "u", + "m", + "f", + "p", + "g", + "w", + "y", + "b", + "v", + "k", + "x", + "j", + "z", + "q", + ], + "English—": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "m", + "u", + "f", + "p", + "g", + "w", + "b", + "y", + "v", + "k", + "j", + "x", + "z", + "q", + ], + "German": [ + "e", + "n", + "i", + "r", + "s", + "t", + "a", + "d", + "h", + "u", + "l", + "g", + "o", + "c", + "m", + "b", + "f", + "k", + "w", + "z", + "p", + "v", + "ü", + "ä", + "ö", + "j", + ], + "French": [ + "e", + "a", + "s", + "n", + "i", + "t", + "r", + "l", + "u", + "o", + "d", + "c", + "p", + "m", + "é", + "v", + "g", + "f", + "b", + "h", + "q", + "à", + "x", + "è", + "y", + "j", + ], + "Dutch": [ + "e", + "n", + "a", + "i", + "r", + "t", + "o", + "d", + "s", + "l", + "g", + "h", + "v", + "m", + "u", + "k", + "c", + "p", + "b", + "w", + "j", + "z", + "f", + "y", + "x", + "ë", + ], + "Italian": [ + "e", + "i", + "a", + "o", + "n", + "l", + "t", + "r", + "s", + "c", + "d", + "u", + "p", + "m", + "g", + "v", + "f", + "b", + "z", + "h", + "q", + "è", + "à", + "k", + "y", + "ò", + ], + "Polish": [ + "a", + "i", + "o", + "e", + "n", + "r", + "z", + "w", + "s", + "c", + "t", + "k", + "y", + "d", + "p", + "m", + "u", + "l", + "j", + "ł", + "g", + "b", + "h", + "ą", + "ę", + "ó", + ], + "Spanish": [ + "e", + "a", + "o", + "n", + "s", + "r", + "i", + "l", + "d", + "t", + "c", + "u", + "m", + "p", + "b", + "g", + "v", + "f", + "y", + "ó", + "h", + "q", + "í", + "j", + "z", + "á", + ], + "Russian": [ + "о", + "а", + "е", + "и", + "н", + "с", + "т", + "р", + "в", + "л", + "к", + "м", + "д", + "п", + "у", + "г", + "я", + "ы", + "з", + "б", + "й", + "ь", + "ч", + "х", + "ж", + "ц", + ], + # Jap-Kanji + "Japanese": [ + "人", + "一", + "大", + "亅", + "丁", + "丨", + "竹", + "笑", + "口", + "日", + "今", + "二", + "彳", + "行", + "十", + "土", + "丶", + "寸", + "寺", + "時", + "乙", + "丿", + "乂", + "气", + "気", + "冂", + "巾", + "亠", + "市", + "目", + "儿", + "見", + "八", + "小", + "凵", + "県", + "月", + "彐", + "門", + "間", + "木", + "東", + "山", + "出", + "本", + "中", + "刀", + "分", + "耳", + "又", + "取", + "最", + "言", + "田", + "心", + "思", + "刂", + "前", + "京", + "尹", + "事", + "生", + "厶", + "云", + "会", + "未", + "来", + "白", + "冫", + "楽", + "灬", + "馬", + "尸", + "尺", + "駅", + "明", + "耂", + "者", + "了", + "阝", + "都", + "高", + "卜", + "占", + "厂", + "广", + "店", + "子", + "申", + "奄", + "亻", + "俺", + "上", + "方", + "冖", + "学", + "衣", + "艮", + "食", + "自", + ], + # Jap-Katakana + "Japanese—": [ + "ー", + "ン", + "ス", + "・", + "ル", + "ト", + "リ", + "イ", + "ア", + "ラ", + "ッ", + "ク", + "ド", + "シ", + "レ", + "ジ", + "タ", + "フ", + "ロ", + "カ", + "テ", + "マ", + "ィ", + "グ", + "バ", + "ム", + "プ", + "オ", + "コ", + "デ", + "ニ", + "ウ", + "メ", + "サ", + "ビ", + "ナ", + "ブ", + "ャ", + "エ", + "ュ", + "チ", + "キ", + "ズ", + "ダ", + "パ", + "ミ", + "ェ", + "ョ", + "ハ", + "セ", + "ベ", + "ガ", + "モ", + "ツ", + "ネ", + "ボ", + "ソ", + "ノ", + "ァ", + "ヴ", + "ワ", + "ポ", + "ペ", + "ピ", + "ケ", + "ゴ", + "ギ", + "ザ", + "ホ", + "ゲ", + "ォ", + "ヤ", + "ヒ", + "ユ", + "ヨ", + "ヘ", + "ゼ", + "ヌ", + "ゥ", + "ゾ", + "ヶ", + "ヂ", + "ヲ", + "ヅ", + "ヵ", + "ヱ", + "ヰ", + "ヮ", + "ヽ", + "゠", + "ヾ", + "ヷ", + "ヿ", + "ヸ", + "ヹ", + "ヺ", + ], + # Jap-Hiragana + "Japanese——": [ + "の", + "に", + "る", + "た", + "と", + "は", + "し", + "い", + "を", + "で", + "て", + "が", + "な", + "れ", + "か", + "ら", + "さ", + "っ", + "り", + "す", + "あ", + "も", + "こ", + "ま", + "う", + "く", + "よ", + "き", + "ん", + "め", + "お", + "け", + "そ", + "つ", + "だ", + "や", + "え", + "ど", + "わ", + "ち", + "み", + "せ", + "じ", + "ば", + "へ", + "び", + "ず", + "ろ", + "ほ", + "げ", + "む", + "べ", + "ひ", + "ょ", + "ゆ", + "ぶ", + "ご", + "ゃ", + "ね", + "ふ", + "ぐ", + "ぎ", + "ぼ", + "ゅ", + "づ", + "ざ", + "ぞ", + "ぬ", + "ぜ", + "ぱ", + "ぽ", + "ぷ", + "ぴ", + "ぃ", + "ぁ", + "ぇ", + "ぺ", + "ゞ", + "ぢ", + "ぉ", + "ぅ", + "ゐ", + "ゝ", + "ゑ", + "゛", + "゜", + "ゎ", + "ゔ", + "゚", + "ゟ", + "゙", + "ゕ", + "ゖ", + ], + "Portuguese": [ + "a", + "e", + "o", + "s", + "i", + "r", + "d", + "n", + "t", + "m", + "u", + "c", + "l", + "p", + "g", + "v", + "b", + "f", + "h", + "ã", + "q", + "é", + "ç", + "á", + "z", + "í", + ], + "Swedish": [ + "e", + "a", + "n", + "r", + "t", + "s", + "i", + "l", + "d", + "o", + "m", + "k", + "g", + "v", + "h", + "f", + "u", + "p", + "ä", + "c", + "b", + "ö", + "å", + "y", + "j", + "x", + ], + "Chinese": [ + "的", + "一", + "是", + "不", + "了", + "在", + "人", + "有", + "我", + "他", + "这", + "个", + "们", + "中", + "来", + "上", + "大", + "为", + "和", + "国", + "地", + "到", + "以", + "说", + "时", + "要", + "就", + "出", + "会", + "可", + "也", + "你", + "对", + "生", + "能", + "而", + "子", + "那", + "得", + "于", + "着", + "下", + "自", + "之", + "年", + "过", + "发", + "后", + "作", + "里", + "用", + "道", + "行", + "所", + "然", + "家", + "种", + "事", + "成", + "方", + "多", + "经", + "么", + "去", + "法", + "学", + "如", + "都", + "同", + "现", + "当", + "没", + "动", + "面", + "起", + "看", + "定", + "天", + "分", + "还", + "进", + "好", + "小", + "部", + "其", + "些", + "主", + "样", + "理", + "心", + "她", + "本", + "前", + "开", + "但", + "因", + "只", + "从", + "想", + "实", + ], + "Ukrainian": [ + "о", + "а", + "н", + "і", + "и", + "р", + "в", + "т", + "е", + "с", + "к", + "л", + "у", + "д", + "м", + "п", + "з", + "я", + "ь", + "б", + "г", + "й", + "ч", + "х", + "ц", + "ї", + ], + "Norwegian": [ + "e", + "r", + "n", + "t", + "a", + "s", + "i", + "o", + "l", + "d", + "g", + "k", + "m", + "v", + "f", + "p", + "u", + "b", + "h", + "å", + "y", + "j", + "ø", + "c", + "æ", + "w", + ], + "Finnish": [ + "a", + "i", + "n", + "t", + "e", + "s", + "l", + "o", + "u", + "k", + "ä", + "m", + "r", + "v", + "j", + "h", + "p", + "y", + "d", + "ö", + "g", + "c", + "b", + "f", + "w", + "z", + ], + "Vietnamese": [ + "n", + "h", + "t", + "i", + "c", + "g", + "a", + "o", + "u", + "m", + "l", + "r", + "à", + "đ", + "s", + "e", + "v", + "p", + "b", + "y", + "ư", + "d", + "á", + "k", + "ộ", + "ế", + ], + "Czech": [ + "o", + "e", + "a", + "n", + "t", + "s", + "i", + "l", + "v", + "r", + "k", + "d", + "u", + "m", + "p", + "í", + "c", + "h", + "z", + "á", + "y", + "j", + "b", + "ě", + "é", + "ř", + ], + "Hungarian": [ + "e", + "a", + "t", + "l", + "s", + "n", + "k", + "r", + "i", + "o", + "z", + "á", + "é", + "g", + "m", + "b", + "y", + "v", + "d", + "h", + "u", + "p", + "j", + "ö", + "f", + "c", + ], + "Korean": [ + "이", + "다", + "에", + "의", + "는", + "로", + "하", + "을", + "가", + "고", + "지", + "서", + "한", + "은", + "기", + "으", + "년", + "대", + "사", + "시", + "를", + "리", + "도", + "인", + "스", + "일", + ], + "Indonesian": [ + "a", + "n", + "e", + "i", + "r", + "t", + "u", + "s", + "d", + "k", + "m", + "l", + "g", + "p", + "b", + "o", + "h", + "y", + "j", + "c", + "w", + "f", + "v", + "z", + "x", + "q", + ], + "Turkish": [ + "a", + "e", + "i", + "n", + "r", + "l", + "ı", + "k", + "d", + "t", + "s", + "m", + "y", + "u", + "o", + "b", + "ü", + "ş", + "v", + "g", + "z", + "h", + "c", + "p", + "ç", + "ğ", + ], + "Romanian": [ + "e", + "i", + "a", + "r", + "n", + "t", + "u", + "l", + "o", + "c", + "s", + "d", + "p", + "m", + "ă", + "f", + "v", + "î", + "g", + "b", + "ș", + "ț", + "z", + "h", + "â", + "j", + ], + "Farsi": [ + "ا", + "ی", + "ر", + "د", + "ن", + "ه", + "و", + "م", + "ت", + "ب", + "س", + "ل", + "ک", + "ش", + "ز", + "ف", + "گ", + "ع", + "خ", + "ق", + "ج", + "آ", + "پ", + "ح", + "ط", + "ص", + ], + "Arabic": [ + "ا", + "ل", + "ي", + "م", + "و", + "ن", + "ر", + "ت", + "ب", + "ة", + "ع", + "د", + "س", + "ف", + "ه", + "ك", + "ق", + "أ", + "ح", + "ج", + "ش", + "ط", + "ص", + "ى", + "خ", + "إ", + ], + "Danish": [ + "e", + "r", + "n", + "t", + "a", + "i", + "s", + "d", + "l", + "o", + "g", + "m", + "k", + "f", + "v", + "u", + "b", + "h", + "p", + "å", + "y", + "ø", + "æ", + "c", + "j", + "w", + ], + "Serbian": [ + "а", + "и", + "о", + "е", + "н", + "р", + "с", + "у", + "т", + "к", + "ј", + "в", + "д", + "м", + "п", + "л", + "г", + "з", + "б", + "a", + "i", + "e", + "o", + "n", + "ц", + "ш", + ], + "Lithuanian": [ + "i", + "a", + "s", + "o", + "r", + "e", + "t", + "n", + "u", + "k", + "m", + "l", + "p", + "v", + "d", + "j", + "g", + "ė", + "b", + "y", + "ų", + "š", + "ž", + "c", + "ą", + "į", + ], + "Slovene": [ + "e", + "a", + "i", + "o", + "n", + "r", + "s", + "l", + "t", + "j", + "v", + "k", + "d", + "p", + "m", + "u", + "z", + "b", + "g", + "h", + "č", + "c", + "š", + "ž", + "f", + "y", + ], + "Slovak": [ + "o", + "a", + "e", + "n", + "i", + "r", + "v", + "t", + "s", + "l", + "k", + "d", + "m", + "p", + "u", + "c", + "h", + "j", + "b", + "z", + "á", + "y", + "ý", + "í", + "č", + "é", + ], + "Hebrew": [ + "י", + "ו", + "ה", + "ל", + "ר", + "ב", + "ת", + "מ", + "א", + "ש", + "נ", + "ע", + "ם", + "ד", + "ק", + "ח", + "פ", + "ס", + "כ", + "ג", + "ט", + "צ", + "ן", + "ז", + "ך", + ], + "Bulgarian": [ + "а", + "и", + "о", + "е", + "н", + "т", + "р", + "с", + "в", + "л", + "к", + "д", + "п", + "м", + "з", + "г", + "я", + "ъ", + "у", + "б", + "ч", + "ц", + "й", + "ж", + "щ", + "х", + ], + "Croatian": [ + "a", + "i", + "o", + "e", + "n", + "r", + "j", + "s", + "t", + "u", + "k", + "l", + "v", + "d", + "m", + "p", + "g", + "z", + "b", + "c", + "č", + "h", + "š", + "ž", + "ć", + "f", + ], + "Hindi": [ + "क", + "र", + "स", + "न", + "त", + "म", + "ह", + "प", + "य", + "ल", + "व", + "ज", + "द", + "ग", + "ब", + "श", + "ट", + "अ", + "ए", + "थ", + "भ", + "ड", + "च", + "ध", + "ष", + "इ", + ], + "Estonian": [ + "a", + "i", + "e", + "s", + "t", + "l", + "u", + "n", + "o", + "k", + "r", + "d", + "m", + "v", + "g", + "p", + "j", + "h", + "ä", + "b", + "õ", + "ü", + "f", + "c", + "ö", + "y", + ], + "Thai": [ + "า", + "น", + "ร", + "อ", + "ก", + "เ", + "ง", + "ม", + "ย", + "ล", + "ว", + "ด", + "ท", + "ส", + "ต", + "ะ", + "ป", + "บ", + "ค", + "ห", + "แ", + "จ", + "พ", + "ช", + "ข", + "ใ", + ], + "Greek": [ + "α", + "τ", + "ο", + "ι", + "ε", + "ν", + "ρ", + "σ", + "κ", + "η", + "π", + "ς", + "υ", + "μ", + "λ", + "ί", + "ό", + "ά", + "γ", + "έ", + "δ", + "ή", + "ω", + "χ", + "θ", + "ύ", + ], + "Tamil": [ + "க", + "த", + "ப", + "ட", + "ர", + "ம", + "ல", + "ன", + "வ", + "ற", + "ய", + "ள", + "ச", + "ந", + "இ", + "ண", + "அ", + "ஆ", + "ழ", + "ங", + "எ", + "உ", + "ஒ", + "ஸ", + ], + "Kazakh": [ + "а", + "ы", + "е", + "н", + "т", + "р", + "л", + "і", + "д", + "с", + "м", + "қ", + "к", + "о", + "б", + "и", + "у", + "ғ", + "ж", + "ң", + "з", + "ш", + "й", + "п", + "г", + "ө", + ], +} + +LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/legacy.py b/venv/lib/python3.12/site-packages/charset_normalizer/legacy.py new file mode 100644 index 0000000..43aad21 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/legacy.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, Optional, Union +from warnings import warn + +from .api import from_bytes +from .constant import CHARDET_CORRESPONDENCE + + +def detect( + byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any +) -> Dict[str, Optional[Union[str, float]]]: + """ + chardet legacy method + Detect the encoding of the given byte string. It should be mostly backward-compatible. + Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) + This function is deprecated and should be used to migrate your project easily, consult the documentation for + further information. Not planned for removal. + + :param byte_str: The byte sequence to examine. + :param should_rename_legacy: Should we rename legacy encodings + to their more modern equivalents? + """ + if len(kwargs): + warn( + f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()" + ) + + if not isinstance(byte_str, (bytearray, bytes)): + raise TypeError( # pragma: nocover + "Expected object of type bytes or bytearray, got: " + "{0}".format(type(byte_str)) + ) + + if isinstance(byte_str, bytearray): + byte_str = bytes(byte_str) + + r = from_bytes(byte_str).best() + + encoding = r.encoding if r is not None else None + language = r.language if r is not None and r.language != "Unknown" else "" + confidence = 1.0 - r.chaos if r is not None else None + + # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process + # but chardet does return 'utf-8-sig' and it is a valid codec name. + if r is not None and encoding == "utf_8" and r.bom: + encoding += "_sig" + + if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE: + encoding = CHARDET_CORRESPONDENCE[encoding] + + return { + "encoding": encoding, + "language": language, + "confidence": confidence, + } diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-darwin.so b/venv/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-darwin.so new file mode 100755 index 0000000000000000000000000000000000000000..d905e2c8d2b8b6509e28a2b5b740f6b0c498a8b5 GIT binary patch literal 50117 zcmeI*U2IfE6bJCLyWO%tffoBv5oAS>YHX<$KOzm>3Iys0EmA_?hHZCCSNDtETj@d@ z$^%9;8qgX^jE2M*im^ttMogsLO3)VxAI1VEnkK%W2?&}H!4y2_-ns4WHo#LKO#YKh zXU@#rGjo5p37$3+#Us<<3=e(!H+4;tww0rWN@~xD5u5R74 zt5?-Ie_I)Qo($dU__$6c?oyqyfMu#A$k>0sK5oa}iHH3h%RX(~mUAmUGQXc=dB^f0 zq7H7Sb8X-%#o0sF%C^}KGM`<1{JiAJFZb|(?6duFMb`)CYhD@nu+_8d=r@DaJm%*r zdsw@=W>|ge^;}Cm5Amq{UO7enKA+?&x#T=Vi}{}w7cFT|C6`3P%~Cg{Q)Vby`E+G4 z&5^Z;9^gju?9JFN59(OnTgp7HGJk;2zsOE3!zd7d00bZa0SG_<0uX=z1Rwwb2tWV= z5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHaf zK;VBPFuG&#(5Q#@bx)<@`F_t&j}i53c2mEPjBBsbKTr6)bcOG}UgN8ojmA`}k~J>s zeu3|t_V``YKe}V6muUVl-|y@(eB<+enZJ4SOTNZ>M%H9JYS`J!Uuf?&=Qewdc*k?i z$lGfc$0G&f^L%l1!d`OD%TwG<4|AtD~iC zLHi2bmdoWegNGzfgO{wFEp35hDrBlyJQ)o{!rMd1%4krjXgZN@q1#PXhGSt^8hQf{TX^u2KD%N^Sy{y@cCb-CTuUS|zj2tWV=5P$##AOHaf zKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_ z009U<00Izz00bZa0SG_<0uX=z1SVO)`TyEi>HkhZjczA-Tcn2o1Rwwb2tWV=5P$## zAOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG`KOQ2){ZIH0U2&N-Jl``9#RdYBN3?*s(R@zHRT5hO@ z^vXaY)gB3{x@aPvG-cdpjoYyvem)-LH8NSull+ug6$(Tm@fIE;7sqw6u&JoTLp@zY zZl%H!D=LZx={^tjcJeuTJ0sTVLi}^4kEpEM3dzmQEEiGFay!0D$K^V{mt&s3Vb2m( z<;83A;zm2>N9^L^rhu!LYa!R{m_zcDbN;boI|F=r?&b-}q-B+BlcO?0Tq$cPkqo~a zFhzjq`maS9wpzqp=d7hX#vJYva`TDZ7R^?kZ{jLt2GP&~znhBe@J>ICu?5j!WlJJ$ zw#8!=k3Lde5ey`^g=3YeI354!oj-p0{$1}gR|iJEexqep=la(!PW$56k$KgB?mGBl zk;1>4k2DNyjLhD2w(nA4r*Zi0{{X~C BKMDW< literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/md.py b/venv/lib/python3.12/site-packages/charset_normalizer/md.py new file mode 100644 index 0000000..77897aa --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/md.py @@ -0,0 +1,615 @@ +from functools import lru_cache +from logging import getLogger +from typing import List, Optional + +from .constant import ( + COMMON_SAFE_ASCII_CHARACTERS, + TRACE, + UNICODE_SECONDARY_RANGE_KEYWORD, +) +from .utils import ( + is_accentuated, + is_arabic, + is_arabic_isolated_form, + is_case_variable, + is_cjk, + is_emoticon, + is_hangul, + is_hiragana, + is_katakana, + is_latin, + is_punctuation, + is_separator, + is_symbol, + is_thai, + is_unprintable, + remove_accent, + unicode_range, +) + + +class MessDetectorPlugin: + """ + Base abstract class used for mess detection plugins. + All detectors MUST extend and implement given methods. + """ + + def eligible(self, character: str) -> bool: + """ + Determine if given character should be fed in. + """ + raise NotImplementedError # pragma: nocover + + def feed(self, character: str) -> None: + """ + The main routine to be executed upon character. + Insert the logic in witch the text would be considered chaotic. + """ + raise NotImplementedError # pragma: nocover + + def reset(self) -> None: # pragma: no cover + """ + Permit to reset the plugin to the initial state. + """ + raise NotImplementedError + + @property + def ratio(self) -> float: + """ + Compute the chaos ratio based on what your feed() has seen. + Must NOT be lower than 0.; No restriction gt 0. + """ + raise NotImplementedError # pragma: nocover + + +class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._punctuation_count: int = 0 + self._symbol_count: int = 0 + self._character_count: int = 0 + + self._last_printable_char: Optional[str] = None + self._frenzy_symbol_in_word: bool = False + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character != self._last_printable_char + and character not in COMMON_SAFE_ASCII_CHARACTERS + ): + if is_punctuation(character): + self._punctuation_count += 1 + elif ( + character.isdigit() is False + and is_symbol(character) + and is_emoticon(character) is False + ): + self._symbol_count += 2 + + self._last_printable_char = character + + def reset(self) -> None: # pragma: no cover + self._punctuation_count = 0 + self._character_count = 0 + self._symbol_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + ratio_of_punctuation: float = ( + self._punctuation_count + self._symbol_count + ) / self._character_count + + return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 + + +class TooManyAccentuatedPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._character_count: int = 0 + self._accentuated_count: int = 0 + + def eligible(self, character: str) -> bool: + return character.isalpha() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_accentuated(character): + self._accentuated_count += 1 + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._accentuated_count = 0 + + @property + def ratio(self) -> float: + if self._character_count < 8: + return 0.0 + + ratio_of_accentuation: float = self._accentuated_count / self._character_count + return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 + + +class UnprintablePlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._unprintable_count: int = 0 + self._character_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if is_unprintable(character): + self._unprintable_count += 1 + self._character_count += 1 + + def reset(self) -> None: # pragma: no cover + self._unprintable_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._unprintable_count * 8) / self._character_count + + +class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._successive_count: int = 0 + self._character_count: int = 0 + + self._last_latin_character: Optional[str] = None + + def eligible(self, character: str) -> bool: + return character.isalpha() and is_latin(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + if ( + self._last_latin_character is not None + and is_accentuated(character) + and is_accentuated(self._last_latin_character) + ): + if character.isupper() and self._last_latin_character.isupper(): + self._successive_count += 1 + # Worse if its the same char duplicated with different accent. + if remove_accent(character) == remove_accent(self._last_latin_character): + self._successive_count += 1 + self._last_latin_character = character + + def reset(self) -> None: # pragma: no cover + self._successive_count = 0 + self._character_count = 0 + self._last_latin_character = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._successive_count * 2) / self._character_count + + +class SuspiciousRange(MessDetectorPlugin): + def __init__(self) -> None: + self._suspicious_successive_range_count: int = 0 + self._character_count: int = 0 + self._last_printable_seen: Optional[str] = None + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character.isspace() + or is_punctuation(character) + or character in COMMON_SAFE_ASCII_CHARACTERS + ): + self._last_printable_seen = None + return + + if self._last_printable_seen is None: + self._last_printable_seen = character + return + + unicode_range_a: Optional[str] = unicode_range(self._last_printable_seen) + unicode_range_b: Optional[str] = unicode_range(character) + + if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): + self._suspicious_successive_range_count += 1 + + self._last_printable_seen = character + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._suspicious_successive_range_count = 0 + self._last_printable_seen = None + + @property + def ratio(self) -> float: + if self._character_count <= 24: + return 0.0 + + ratio_of_suspicious_range_usage: float = ( + self._suspicious_successive_range_count * 2 + ) / self._character_count + + return ratio_of_suspicious_range_usage + + +class SuperWeirdWordPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._word_count: int = 0 + self._bad_word_count: int = 0 + self._foreign_long_count: int = 0 + + self._is_current_word_bad: bool = False + self._foreign_long_watch: bool = False + + self._character_count: int = 0 + self._bad_character_count: int = 0 + + self._buffer: str = "" + self._buffer_accent_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character.isalpha(): + self._buffer += character + if is_accentuated(character): + self._buffer_accent_count += 1 + if ( + self._foreign_long_watch is False + and (is_latin(character) is False or is_accentuated(character)) + and is_cjk(character) is False + and is_hangul(character) is False + and is_katakana(character) is False + and is_hiragana(character) is False + and is_thai(character) is False + ): + self._foreign_long_watch = True + return + if not self._buffer: + return + if ( + character.isspace() or is_punctuation(character) or is_separator(character) + ) and self._buffer: + self._word_count += 1 + buffer_length: int = len(self._buffer) + + self._character_count += buffer_length + + if buffer_length >= 4: + if self._buffer_accent_count / buffer_length > 0.34: + self._is_current_word_bad = True + # Word/Buffer ending with an upper case accentuated letter are so rare, + # that we will consider them all as suspicious. Same weight as foreign_long suspicious. + if ( + is_accentuated(self._buffer[-1]) + and self._buffer[-1].isupper() + and all(_.isupper() for _ in self._buffer) is False + ): + self._foreign_long_count += 1 + self._is_current_word_bad = True + if buffer_length >= 24 and self._foreign_long_watch: + camel_case_dst = [ + i + for c, i in zip(self._buffer, range(0, buffer_length)) + if c.isupper() + ] + probable_camel_cased: bool = False + + if camel_case_dst and (len(camel_case_dst) / buffer_length <= 0.3): + probable_camel_cased = True + + if not probable_camel_cased: + self._foreign_long_count += 1 + self._is_current_word_bad = True + + if self._is_current_word_bad: + self._bad_word_count += 1 + self._bad_character_count += len(self._buffer) + self._is_current_word_bad = False + + self._foreign_long_watch = False + self._buffer = "" + self._buffer_accent_count = 0 + elif ( + character not in {"<", ">", "-", "=", "~", "|", "_"} + and character.isdigit() is False + and is_symbol(character) + ): + self._is_current_word_bad = True + self._buffer += character + + def reset(self) -> None: # pragma: no cover + self._buffer = "" + self._is_current_word_bad = False + self._foreign_long_watch = False + self._bad_word_count = 0 + self._word_count = 0 + self._character_count = 0 + self._bad_character_count = 0 + self._foreign_long_count = 0 + + @property + def ratio(self) -> float: + if self._word_count <= 10 and self._foreign_long_count == 0: + return 0.0 + + return self._bad_character_count / self._character_count + + +class CjkInvalidStopPlugin(MessDetectorPlugin): + """ + GB(Chinese) based encoding often render the stop incorrectly when the content does not fit and + can be easily detected. Searching for the overuse of '丅' and '丄'. + """ + + def __init__(self) -> None: + self._wrong_stop_count: int = 0 + self._cjk_character_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character in {"丅", "丄"}: + self._wrong_stop_count += 1 + return + if is_cjk(character): + self._cjk_character_count += 1 + + def reset(self) -> None: # pragma: no cover + self._wrong_stop_count = 0 + self._cjk_character_count = 0 + + @property + def ratio(self) -> float: + if self._cjk_character_count < 16: + return 0.0 + return self._wrong_stop_count / self._cjk_character_count + + +class ArchaicUpperLowerPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._buf: bool = False + + self._character_count_since_last_sep: int = 0 + + self._successive_upper_lower_count: int = 0 + self._successive_upper_lower_count_final: int = 0 + + self._character_count: int = 0 + + self._last_alpha_seen: Optional[str] = None + self._current_ascii_only: bool = True + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + is_concerned = character.isalpha() and is_case_variable(character) + chunk_sep = is_concerned is False + + if chunk_sep and self._character_count_since_last_sep > 0: + if ( + self._character_count_since_last_sep <= 64 + and character.isdigit() is False + and self._current_ascii_only is False + ): + self._successive_upper_lower_count_final += ( + self._successive_upper_lower_count + ) + + self._successive_upper_lower_count = 0 + self._character_count_since_last_sep = 0 + self._last_alpha_seen = None + self._buf = False + self._character_count += 1 + self._current_ascii_only = True + + return + + if self._current_ascii_only is True and character.isascii() is False: + self._current_ascii_only = False + + if self._last_alpha_seen is not None: + if (character.isupper() and self._last_alpha_seen.islower()) or ( + character.islower() and self._last_alpha_seen.isupper() + ): + if self._buf is True: + self._successive_upper_lower_count += 2 + self._buf = False + else: + self._buf = True + else: + self._buf = False + + self._character_count += 1 + self._character_count_since_last_sep += 1 + self._last_alpha_seen = character + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._character_count_since_last_sep = 0 + self._successive_upper_lower_count = 0 + self._successive_upper_lower_count_final = 0 + self._last_alpha_seen = None + self._buf = False + self._current_ascii_only = True + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return self._successive_upper_lower_count_final / self._character_count + + +class ArabicIsolatedFormPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._character_count: int = 0 + self._isolated_form_count: int = 0 + + def reset(self) -> None: # pragma: no cover + self._character_count = 0 + self._isolated_form_count = 0 + + def eligible(self, character: str) -> bool: + return is_arabic(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_arabic_isolated_form(character): + self._isolated_form_count += 1 + + @property + def ratio(self) -> float: + if self._character_count < 8: + return 0.0 + + isolated_form_usage: float = self._isolated_form_count / self._character_count + + return isolated_form_usage + + +@lru_cache(maxsize=1024) +def is_suspiciously_successive_range( + unicode_range_a: Optional[str], unicode_range_b: Optional[str] +) -> bool: + """ + Determine if two Unicode range seen next to each other can be considered as suspicious. + """ + if unicode_range_a is None or unicode_range_b is None: + return True + + if unicode_range_a == unicode_range_b: + return False + + if "Latin" in unicode_range_a and "Latin" in unicode_range_b: + return False + + if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: + return False + + # Latin characters can be accompanied with a combining diacritical mark + # eg. Vietnamese. + if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( + "Combining" in unicode_range_a or "Combining" in unicode_range_b + ): + return False + + keywords_range_a, keywords_range_b = unicode_range_a.split( + " " + ), unicode_range_b.split(" ") + + for el in keywords_range_a: + if el in UNICODE_SECONDARY_RANGE_KEYWORD: + continue + if el in keywords_range_b: + return False + + # Japanese Exception + range_a_jp_chars, range_b_jp_chars = ( + unicode_range_a + in ( + "Hiragana", + "Katakana", + ), + unicode_range_b in ("Hiragana", "Katakana"), + ) + if (range_a_jp_chars or range_b_jp_chars) and ( + "CJK" in unicode_range_a or "CJK" in unicode_range_b + ): + return False + if range_a_jp_chars and range_b_jp_chars: + return False + + if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: + if "CJK" in unicode_range_a or "CJK" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + # Chinese/Japanese use dedicated range for punctuation and/or separators. + if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( + unicode_range_a in ["Katakana", "Hiragana"] + and unicode_range_b in ["Katakana", "Hiragana"] + ): + if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: + return False + if "Forms" in unicode_range_a or "Forms" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + return True + + +@lru_cache(maxsize=2048) +def mess_ratio( + decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False +) -> float: + """ + Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. + """ + + detectors: List[MessDetectorPlugin] = [ + md_class() for md_class in MessDetectorPlugin.__subclasses__() + ] + + length: int = len(decoded_sequence) + 1 + + mean_mess_ratio: float = 0.0 + + if length < 512: + intermediary_mean_mess_ratio_calc: int = 32 + elif length <= 1024: + intermediary_mean_mess_ratio_calc = 64 + else: + intermediary_mean_mess_ratio_calc = 128 + + for character, index in zip(decoded_sequence + "\n", range(length)): + for detector in detectors: + if detector.eligible(character): + detector.feed(character) + + if ( + index > 0 and index % intermediary_mean_mess_ratio_calc == 0 + ) or index == length - 1: + mean_mess_ratio = sum(dt.ratio for dt in detectors) + + if mean_mess_ratio >= maximum_threshold: + break + + if debug: + logger = getLogger("charset_normalizer") + + logger.log( + TRACE, + "Mess-detector extended-analysis start. " + f"intermediary_mean_mess_ratio_calc={intermediary_mean_mess_ratio_calc} mean_mess_ratio={mean_mess_ratio} " + f"maximum_threshold={maximum_threshold}", + ) + + if len(decoded_sequence) > 16: + logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}") + logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}") + + for dt in detectors: # pragma: nocover + logger.log(TRACE, f"{dt.__class__}: {dt.ratio}") + + return round(mean_mess_ratio, 3) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-darwin.so b/venv/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-darwin.so new file mode 100755 index 0000000000000000000000000000000000000000..7440ba5169ab8c7c8ed709ba28e32099b4ac89e4 GIT binary patch literal 232652 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/models.py b/venv/lib/python3.12/site-packages/charset_normalizer/models.py new file mode 100644 index 0000000..a760b9c --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/models.py @@ -0,0 +1,340 @@ +from encodings.aliases import aliases +from hashlib import sha256 +from json import dumps +from typing import Any, Dict, Iterator, List, Optional, Tuple, Union + +from .constant import TOO_BIG_SEQUENCE +from .utils import iana_name, is_multi_byte_encoding, unicode_range + + +class CharsetMatch: + def __init__( + self, + payload: bytes, + guessed_encoding: str, + mean_mess_ratio: float, + has_sig_or_bom: bool, + languages: "CoherenceMatches", + decoded_payload: Optional[str] = None, + ): + self._payload: bytes = payload + + self._encoding: str = guessed_encoding + self._mean_mess_ratio: float = mean_mess_ratio + self._languages: CoherenceMatches = languages + self._has_sig_or_bom: bool = has_sig_or_bom + self._unicode_ranges: Optional[List[str]] = None + + self._leaves: List[CharsetMatch] = [] + self._mean_coherence_ratio: float = 0.0 + + self._output_payload: Optional[bytes] = None + self._output_encoding: Optional[str] = None + + self._string: Optional[str] = decoded_payload + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CharsetMatch): + raise TypeError( + "__eq__ cannot be invoked on {} and {}.".format( + str(other.__class__), str(self.__class__) + ) + ) + return self.encoding == other.encoding and self.fingerprint == other.fingerprint + + def __lt__(self, other: object) -> bool: + """ + Implemented to make sorted available upon CharsetMatches items. + """ + if not isinstance(other, CharsetMatch): + raise ValueError + + chaos_difference: float = abs(self.chaos - other.chaos) + coherence_difference: float = abs(self.coherence - other.coherence) + + # Below 1% difference --> Use Coherence + if chaos_difference < 0.01 and coherence_difference > 0.02: + return self.coherence > other.coherence + elif chaos_difference < 0.01 and coherence_difference <= 0.02: + # When having a difficult decision, use the result that decoded as many multi-byte as possible. + # preserve RAM usage! + if len(self._payload) >= TOO_BIG_SEQUENCE: + return self.chaos < other.chaos + return self.multi_byte_usage > other.multi_byte_usage + + return self.chaos < other.chaos + + @property + def multi_byte_usage(self) -> float: + return 1.0 - (len(str(self)) / len(self.raw)) + + def __str__(self) -> str: + # Lazy Str Loading + if self._string is None: + self._string = str(self._payload, self._encoding, "strict") + return self._string + + def __repr__(self) -> str: + return "".format(self.encoding, self.fingerprint) + + def add_submatch(self, other: "CharsetMatch") -> None: + if not isinstance(other, CharsetMatch) or other == self: + raise ValueError( + "Unable to add instance <{}> as a submatch of a CharsetMatch".format( + other.__class__ + ) + ) + + other._string = None # Unload RAM usage; dirty trick. + self._leaves.append(other) + + @property + def encoding(self) -> str: + return self._encoding + + @property + def encoding_aliases(self) -> List[str]: + """ + Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. + """ + also_known_as: List[str] = [] + for u, p in aliases.items(): + if self.encoding == u: + also_known_as.append(p) + elif self.encoding == p: + also_known_as.append(u) + return also_known_as + + @property + def bom(self) -> bool: + return self._has_sig_or_bom + + @property + def byte_order_mark(self) -> bool: + return self._has_sig_or_bom + + @property + def languages(self) -> List[str]: + """ + Return the complete list of possible languages found in decoded sequence. + Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. + """ + return [e[0] for e in self._languages] + + @property + def language(self) -> str: + """ + Most probable language found in decoded sequence. If none were detected or inferred, the property will return + "Unknown". + """ + if not self._languages: + # Trying to infer the language based on the given encoding + # Its either English or we should not pronounce ourselves in certain cases. + if "ascii" in self.could_be_from_charset: + return "English" + + # doing it there to avoid circular import + from charset_normalizer.cd import encoding_languages, mb_encoding_languages + + languages = ( + mb_encoding_languages(self.encoding) + if is_multi_byte_encoding(self.encoding) + else encoding_languages(self.encoding) + ) + + if len(languages) == 0 or "Latin Based" in languages: + return "Unknown" + + return languages[0] + + return self._languages[0][0] + + @property + def chaos(self) -> float: + return self._mean_mess_ratio + + @property + def coherence(self) -> float: + if not self._languages: + return 0.0 + return self._languages[0][1] + + @property + def percent_chaos(self) -> float: + return round(self.chaos * 100, ndigits=3) + + @property + def percent_coherence(self) -> float: + return round(self.coherence * 100, ndigits=3) + + @property + def raw(self) -> bytes: + """ + Original untouched bytes. + """ + return self._payload + + @property + def submatch(self) -> List["CharsetMatch"]: + return self._leaves + + @property + def has_submatch(self) -> bool: + return len(self._leaves) > 0 + + @property + def alphabets(self) -> List[str]: + if self._unicode_ranges is not None: + return self._unicode_ranges + # list detected ranges + detected_ranges: List[Optional[str]] = [ + unicode_range(char) for char in str(self) + ] + # filter and sort + self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) + return self._unicode_ranges + + @property + def could_be_from_charset(self) -> List[str]: + """ + The complete list of encoding that output the exact SAME str result and therefore could be the originating + encoding. + This list does include the encoding available in property 'encoding'. + """ + return [self._encoding] + [m.encoding for m in self._leaves] + + def output(self, encoding: str = "utf_8") -> bytes: + """ + Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. + Any errors will be simply ignored by the encoder NOT replaced. + """ + if self._output_encoding is None or self._output_encoding != encoding: + self._output_encoding = encoding + self._output_payload = str(self).encode(encoding, "replace") + + return self._output_payload # type: ignore + + @property + def fingerprint(self) -> str: + """ + Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. + """ + return sha256(self.output()).hexdigest() + + +class CharsetMatches: + """ + Container with every CharsetMatch items ordered by default from most probable to the less one. + Act like a list(iterable) but does not implements all related methods. + """ + + def __init__(self, results: Optional[List[CharsetMatch]] = None): + self._results: List[CharsetMatch] = sorted(results) if results else [] + + def __iter__(self) -> Iterator[CharsetMatch]: + yield from self._results + + def __getitem__(self, item: Union[int, str]) -> CharsetMatch: + """ + Retrieve a single item either by its position or encoding name (alias may be used here). + Raise KeyError upon invalid index or encoding not present in results. + """ + if isinstance(item, int): + return self._results[item] + if isinstance(item, str): + item = iana_name(item, False) + for result in self._results: + if item in result.could_be_from_charset: + return result + raise KeyError + + def __len__(self) -> int: + return len(self._results) + + def __bool__(self) -> bool: + return len(self._results) > 0 + + def append(self, item: CharsetMatch) -> None: + """ + Insert a single match. Will be inserted accordingly to preserve sort. + Can be inserted as a submatch. + """ + if not isinstance(item, CharsetMatch): + raise ValueError( + "Cannot append instance '{}' to CharsetMatches".format( + str(item.__class__) + ) + ) + # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) + if len(item.raw) <= TOO_BIG_SEQUENCE: + for match in self._results: + if match.fingerprint == item.fingerprint and match.chaos == item.chaos: + match.add_submatch(item) + return + self._results.append(item) + self._results = sorted(self._results) + + def best(self) -> Optional["CharsetMatch"]: + """ + Simply return the first match. Strict equivalent to matches[0]. + """ + if not self._results: + return None + return self._results[0] + + def first(self) -> Optional["CharsetMatch"]: + """ + Redundant method, call the method best(). Kept for BC reasons. + """ + return self.best() + + +CoherenceMatch = Tuple[str, float] +CoherenceMatches = List[CoherenceMatch] + + +class CliDetectionResult: + def __init__( + self, + path: str, + encoding: Optional[str], + encoding_aliases: List[str], + alternative_encodings: List[str], + language: str, + alphabets: List[str], + has_sig_or_bom: bool, + chaos: float, + coherence: float, + unicode_path: Optional[str], + is_preferred: bool, + ): + self.path: str = path + self.unicode_path: Optional[str] = unicode_path + self.encoding: Optional[str] = encoding + self.encoding_aliases: List[str] = encoding_aliases + self.alternative_encodings: List[str] = alternative_encodings + self.language: str = language + self.alphabets: List[str] = alphabets + self.has_sig_or_bom: bool = has_sig_or_bom + self.chaos: float = chaos + self.coherence: float = coherence + self.is_preferred: bool = is_preferred + + @property + def __dict__(self) -> Dict[str, Any]: # type: ignore + return { + "path": self.path, + "encoding": self.encoding, + "encoding_aliases": self.encoding_aliases, + "alternative_encodings": self.alternative_encodings, + "language": self.language, + "alphabets": self.alphabets, + "has_sig_or_bom": self.has_sig_or_bom, + "chaos": self.chaos, + "coherence": self.coherence, + "unicode_path": self.unicode_path, + "is_preferred": self.is_preferred, + } + + def to_json(self) -> str: + return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/py.typed b/venv/lib/python3.12/site-packages/charset_normalizer/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/utils.py b/venv/lib/python3.12/site-packages/charset_normalizer/utils.py new file mode 100644 index 0000000..e5cbbf4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/utils.py @@ -0,0 +1,421 @@ +import importlib +import logging +import unicodedata +from codecs import IncrementalDecoder +from encodings.aliases import aliases +from functools import lru_cache +from re import findall +from typing import Generator, List, Optional, Set, Tuple, Union + +from _multibytecodec import MultibyteIncrementalDecoder + +from .constant import ( + ENCODING_MARKS, + IANA_SUPPORTED_SIMILAR, + RE_POSSIBLE_ENCODING_INDICATION, + UNICODE_RANGES_COMBINED, + UNICODE_SECONDARY_RANGE_KEYWORD, + UTF8_MAXIMAL_ALLOCATION, +) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_accentuated(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: + return False + return ( + "WITH GRAVE" in description + or "WITH ACUTE" in description + or "WITH CEDILLA" in description + or "WITH DIAERESIS" in description + or "WITH CIRCUMFLEX" in description + or "WITH TILDE" in description + or "WITH MACRON" in description + or "WITH RING ABOVE" in description + ) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def remove_accent(character: str) -> str: + decomposed: str = unicodedata.decomposition(character) + if not decomposed: + return character + + codes: List[str] = decomposed.split(" ") + + return chr(int(codes[0], 16)) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def unicode_range(character: str) -> Optional[str]: + """ + Retrieve the Unicode range official name from a single character. + """ + character_ord: int = ord(character) + + for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): + if character_ord in ord_range: + return range_name + + return None + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_latin(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: + return False + return "LATIN" in description + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_punctuation(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "P" in character_category: + return True + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Punctuation" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_symbol(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "S" in character_category or "N" in character_category: + return True + + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Forms" in character_range and character_category != "Lo" + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_emoticon(character: str) -> bool: + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + return False + + return "Emoticons" in character_range or "Pictographs" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_separator(character: str) -> bool: + if character.isspace() or character in {"|", "+", "<", ">"}: + return True + + character_category: str = unicodedata.category(character) + + return "Z" in character_category or character_category in {"Po", "Pd", "Pc"} + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_case_variable(character: str) -> bool: + return character.islower() != character.isupper() + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_cjk(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "CJK" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hiragana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "HIRAGANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_katakana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "KATAKANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hangul(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "HANGUL" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_thai(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "THAI" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_arabic(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "ARABIC" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_arabic_isolated_form(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "ARABIC" in character_name and "ISOLATED FORM" in character_name + + +@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) +def is_unicode_range_secondary(range_name: str) -> bool: + return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_unprintable(character: str) -> bool: + return ( + character.isspace() is False # includes \n \t \r \v + and character.isprintable() is False + and character != "\x1A" # Why? Its the ASCII substitute character. + and character != "\ufeff" # bug discovered in Python, + # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. + ) + + +def any_specified_encoding(sequence: bytes, search_zone: int = 8192) -> Optional[str]: + """ + Extract using ASCII-only decoder any specified encoding in the first n-bytes. + """ + if not isinstance(sequence, bytes): + raise TypeError + + seq_len: int = len(sequence) + + results: List[str] = findall( + RE_POSSIBLE_ENCODING_INDICATION, + sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), + ) + + if len(results) == 0: + return None + + for specified_encoding in results: + specified_encoding = specified_encoding.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if encoding_alias == specified_encoding: + return encoding_iana + if encoding_iana == specified_encoding: + return encoding_iana + + return None + + +@lru_cache(maxsize=128) +def is_multi_byte_encoding(name: str) -> bool: + """ + Verify is a specific encoding is a multi byte one based on it IANA name + """ + return name in { + "utf_8", + "utf_8_sig", + "utf_16", + "utf_16_be", + "utf_16_le", + "utf_32", + "utf_32_le", + "utf_32_be", + "utf_7", + } or issubclass( + importlib.import_module("encodings.{}".format(name)).IncrementalDecoder, + MultibyteIncrementalDecoder, + ) + + +def identify_sig_or_bom(sequence: bytes) -> Tuple[Optional[str], bytes]: + """ + Identify and extract SIG/BOM in given sequence. + """ + + for iana_encoding in ENCODING_MARKS: + marks: Union[bytes, List[bytes]] = ENCODING_MARKS[iana_encoding] + + if isinstance(marks, bytes): + marks = [marks] + + for mark in marks: + if sequence.startswith(mark): + return iana_encoding, mark + + return None, b"" + + +def should_strip_sig_or_bom(iana_encoding: str) -> bool: + return iana_encoding not in {"utf_16", "utf_32"} + + +def iana_name(cp_name: str, strict: bool = True) -> str: + cp_name = cp_name.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if cp_name in [encoding_alias, encoding_iana]: + return encoding_iana + + if strict: + raise ValueError("Unable to retrieve IANA for '{}'".format(cp_name)) + + return cp_name + + +def range_scan(decoded_sequence: str) -> List[str]: + ranges: Set[str] = set() + + for character in decoded_sequence: + character_range: Optional[str] = unicode_range(character) + + if character_range is None: + continue + + ranges.add(character_range) + + return list(ranges) + + +def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: + if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): + return 0.0 + + decoder_a = importlib.import_module( + "encodings.{}".format(iana_name_a) + ).IncrementalDecoder + decoder_b = importlib.import_module( + "encodings.{}".format(iana_name_b) + ).IncrementalDecoder + + id_a: IncrementalDecoder = decoder_a(errors="ignore") + id_b: IncrementalDecoder = decoder_b(errors="ignore") + + character_match_count: int = 0 + + for i in range(255): + to_be_decoded: bytes = bytes([i]) + if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): + character_match_count += 1 + + return character_match_count / 254 + + +def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: + """ + Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using + the function cp_similarity. + """ + return ( + iana_name_a in IANA_SUPPORTED_SIMILAR + and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] + ) + + +def set_logging_handler( + name: str = "charset_normalizer", + level: int = logging.INFO, + format_string: str = "%(asctime)s | %(levelname)s | %(message)s", +) -> None: + logger = logging.getLogger(name) + logger.setLevel(level) + + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(format_string)) + logger.addHandler(handler) + + +def cut_sequence_chunks( + sequences: bytes, + encoding_iana: str, + offsets: range, + chunk_size: int, + bom_or_sig_available: bool, + strip_sig_or_bom: bool, + sig_payload: bytes, + is_multi_byte_decoder: bool, + decoded_payload: Optional[str] = None, +) -> Generator[str, None, None]: + if decoded_payload and is_multi_byte_decoder is False: + for i in offsets: + chunk = decoded_payload[i : i + chunk_size] + if not chunk: + break + yield chunk + else: + for i in offsets: + chunk_end = i + chunk_size + if chunk_end > len(sequences) + 8: + continue + + cut_sequence = sequences[i : i + chunk_size] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode( + encoding_iana, + errors="ignore" if is_multi_byte_decoder else "strict", + ) + + # multi-byte bad cutting detector and adjustment + # not the cleanest way to perform that fix but clever enough for now. + if is_multi_byte_decoder and i > 0: + chunk_partial_size_chk: int = min(chunk_size, 16) + + if ( + decoded_payload + and chunk[:chunk_partial_size_chk] not in decoded_payload + ): + for j in range(i, i - 4, -1): + cut_sequence = sequences[j:chunk_end] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode(encoding_iana, errors="ignore") + + if chunk[:chunk_partial_size_chk] in decoded_payload: + break + + yield chunk diff --git a/venv/lib/python3.12/site-packages/charset_normalizer/version.py b/venv/lib/python3.12/site-packages/charset_normalizer/version.py new file mode 100644 index 0000000..5a4da4f --- /dev/null +++ b/venv/lib/python3.12/site-packages/charset_normalizer/version.py @@ -0,0 +1,6 @@ +""" +Expose version +""" + +__version__ = "3.3.2" +VERSION = __version__.split(".") diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/LICENSE.rst b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/LICENSE.rst new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/METADATA b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/METADATA new file mode 100644 index 0000000..7a6bbb2 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/METADATA @@ -0,0 +1,103 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.1.7 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: colorama ; platform_system == "Windows" +Requires-Dist: importlib-metadata ; python_version < "3.8" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Chat: https://discord.gg/pallets diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/RECORD b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/RECORD new file mode 100644 index 0000000..497ee45 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/RECORD @@ -0,0 +1,39 @@ +click-8.1.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.7.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.7.dist-info/METADATA,sha256=qIMevCxGA9yEmJOM_4WHuUJCwWpsIEVbCPOhs45YPN4,3014 +click-8.1.7.dist-info/RECORD,, +click-8.1.7.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92 +click-8.1.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click/__init__.py,sha256=YDDbjm406dTOA0V8bTtdGnhN7zj5j-_dFRewZF_pLvw,3138 +click/__pycache__/__init__.cpython-312.pyc,, +click/__pycache__/_compat.cpython-312.pyc,, +click/__pycache__/_termui_impl.cpython-312.pyc,, +click/__pycache__/_textwrap.cpython-312.pyc,, +click/__pycache__/_winconsole.cpython-312.pyc,, +click/__pycache__/core.cpython-312.pyc,, +click/__pycache__/decorators.cpython-312.pyc,, +click/__pycache__/exceptions.cpython-312.pyc,, +click/__pycache__/formatting.cpython-312.pyc,, +click/__pycache__/globals.cpython-312.pyc,, +click/__pycache__/parser.cpython-312.pyc,, +click/__pycache__/shell_completion.cpython-312.pyc,, +click/__pycache__/termui.cpython-312.pyc,, +click/__pycache__/testing.cpython-312.pyc,, +click/__pycache__/types.cpython-312.pyc,, +click/__pycache__/utils.cpython-312.pyc,, +click/_compat.py,sha256=5318agQpbt4kroKsbqDOYpTSWzL_YCZVUQiTT04yXmc,18744 +click/_termui_impl.py,sha256=3dFYv4445Nw-rFvZOTBMBPYwB1bxnmNk9Du6Dm_oBSU,24069 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=j6oEWtGgGna8JarD6WxhXmNnxLnfRjwXglbBc-8jr7U,114086 +click/decorators.py,sha256=-ZlbGYgV-oI8jr_oH4RpuL1PFS-5QmeuEAsLDAYgxtw,18719 +click/exceptions.py,sha256=fyROO-47HWFDjt2qupo7A3J32VlpM-ovJnfowu92K3s,9273 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961 +click/parser.py,sha256=LKyYQE9ZLj5KgIDXkrcTHQRXIggfoivX14_UVIn56YA,19067 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=Ty3VM_ts0sQhj6u7eFTiLwHPoTgcXTGEAUg2OpLqYKw,18460 +click/termui.py,sha256=H7Q8FpmPelhJ2ovOhfCRhjMtCpNyjFXryAMLZODqsdc,28324 +click/testing.py,sha256=1Qd4kS5bucn1hsNIRryd0WtTMuCpkA93grkWxT8POsU,16084 +click/types.py,sha256=TZvz3hKvBztf-Hpa2enOmP4eznSPLzijjig5b_0XMxE,36391 +click/utils.py,sha256=1476UduUNY6UePGU4m18uzVHLt1sKM2PP3yWsQhbItM,20298 diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/WHEEL b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/WHEEL new file mode 100644 index 0000000..2c08da0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/top_level.txt new file mode 100644 index 0000000..dca9a90 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click-8.1.7.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/venv/lib/python3.12/site-packages/click/__init__.py b/venv/lib/python3.12/site-packages/click/__init__.py new file mode 100644 index 0000000..9a1dab0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/__init__.py @@ -0,0 +1,73 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.7" diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..712e6689a60bb82466320f4580da6f36ce82f31a GIT binary patch literal 2714 zcmY+_NmCm~8wcW3Y|IBC(mx7>oqiBo0tET>3IK8a2{{*{XYFhurch z@)`0)a>+F(RjDdfIlYIs>U}GfOHTPek6028e}4U_mzh>;=9m8doPocYpZ|MaDHz7@ z)VTiZxxyb~y@v6lQ8$E9Pt<$7gx@22669XESM;)za8e}MDL5rk>@=JfX?6zAhzvUm zXGNCX2lt6Sb`H*o96Rsj{emd43vj>aXZOPcVt_pW4~jwdAUq_7*hBEJ7-kQ{cf=j` z9e6~Hut(s#;x79xJSs-nqwqa(kA2U(?~jQw_I>z)c)%WmABu9K0l!*z@qR zSZ0^t6|urDd$0UevC3Y6*Tfoo5ndPT>?L?ZY_ON%O|i*dfnST)>{sxX*kZ53Z^Rq+ z8oVvG+3WC**kNzLZ^c{oCcGsIa%-s;IKxczgc7*k^CU2jYOe1HTjR*l*$Y z;yrs8J`{)S3jCG$3a*N;FZYW3-?wvB&vhK!gF0t(->yx6@Rm_ClKdiR~!%JyX}6}n~Z+f_5p&59#V7@WJxw`q)p zP3$g|YFy2pZ%Qw^t&h;wT9K`_RhLev>^P*!(>DVP{23;_y38!M!`ip#HAwyvs`~AG z1D~bR|6X~w7Am^Ip^9C<-l;QfHzaBUsC94ex>7*ppSL-{$7laLM_%7b-+}ANeWmz9 zhrV&O#;N${kit>;318gJw&i&4>k<9$u>l7m?NE0k`@SeUvaW7#q#-Ip?kN8ArnvuHd_|l`UnO1PkWaaqy14`*?GjtvLFuP~R^3?UoN!la) zPaS+X-aQ3!2VQ8$AMJp*z4!2lirK^9rqn%Kr!rog+EMXCJ7Zb((6Ov`5@%H^ym}3lq)1VuDKZpUiarW@ zgR4BEox3^UTH$SOsD6q8ib0AYieZX76eARODMl&oA=){4eGav{Pt`Gs2NVw}9#K4| z7^iqbF@b33y4ym}FJ)5oDOEEKFRa;~R+H39M|`@}6gO}-{g$hqQRn9rFDRxdUQ!e( zW+-MU<|yVVN)%;8I~C*G)M|kWixf)~%M>dVuP9b2)+p8~HYheJUQ=vQyg{^6t=Pqt zZc|~0;w{B4MTMe@Xy+~K`uA`BWc-1W@mH;UhTn`X$MRcSM|doG<-O41=cO(m$r#U% z3vIo(oeP|~FerbP!RInw0Og3^63eBw8R zvBW@eh3lK#AN4H;iWrW8Xu=B}W0jjbY|Mt9sAF;fYoUV9U35R4=onKS0~Z54?HIEi eW1O2suHYjS=h^7+ioL-o{x&fBLtdTW#{LFkK>;-Y literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/_compat.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/_compat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..195db64a21f75cdb6d234c08898293c9d23187b6 GIT binary patch literal 27459 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 TF+=+uz0Re(3#OoBa_IjCSn41u literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7055cccee87b0448bda826fd34c48635f1f45eb2 GIT binary patch literal 30542 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/_textwrap.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/_textwrap.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..607a784d4bf9b8236c87d0d14aa96f7b2f6f3a34 GIT binary patch literal 2455 zcmaJ@|7%-S6u<9lUz7A(`ejSobXmK`W}D5nZWFiRm@8^kT0})G%H!?5*EY%POLpH& z+jK85q(Z8~>Mu59i18;kis-+vU;IHqnr=1mO`)JaxF3XICyXKJxi2qW*3BKrx#ym* z_n!O7Nq%T*@*tpt-~Bl?#v$|@+0+R34sE{*%PLZkLTPBSx>A!g>}ideWhYq*(dcEQ zFiS{bRTOtJy0PxE##Dt#E<;7QyJRySq3mWkshjG8IV~23!wGqXQ}`*5(y+u%HmHIksGPzb?IvYd_>h)ue-CUGnG`GzS**n@LTeOijjn34oQ2}9>^eCM z4qKE$ljCQ3i&v1vb)#&9#ao<$KoTrEUSH7-wHnskS`@MblHm+kGRUHh(EmhG@dh`z zZmBivVYUopi7?}LN&3700!3JxnUxmo)(cpb5~7yWr^WdsRt%dbP1F^eNhMQ}Mw>NM zZ3^=che;(&ULQ9Cvpq&il2uVtr%apGB*U~BISmY}hCv)cHF_XN-!|YuqNW;`Ajphq z(b1%wo>g_zh>oi!6iyi8E0Ua$%$cMfom2I>s1~~rO=ZY_WccW@s1Y;OXQ5yMuxdnQ zEhZ+X7|RFj4A_7JH+&dXH}Uj#U`s@7{*0$mV0Z0xgj1@k6jT0H5t&fW3w& zz#kwC0s5*lkAof}vhaLt9)`gvDeu;BH{H zKdC98eHqFtjQ3Ramz1^c`Q@R{!zb z=xyJ=^5Ci5=%%m#KD_?GiAPlb7=2LhgLBNe!_-ZlJr_VXJuO5Iw4RGFHzP!Evjpgm z;Dk&MXGZ-9!YZ0ZS-NgcQE_71MZ2fMD0=@ngx-Vq&oWsS&_r6ci(tMn3Y8dz2k?Oh z83VfrJm@(2y6+;3yM`?G8v2}mIE6lWo`oNYxObN;Y^@!yH_4pB1e6abPlUG{RUHNe zmQ0ll94%&&Id0%yaKJ&rT7lVYJQ>p?d=)DDiH62=HWO18U^GF110RDNpJ1Yf3U3v4 zVp7*Ki+k!pQD+E4kRb!RjLJ<<3BLN(0dd$lqCMB$5ZUwpYAF@*z+2b`y~fAikqQd$`kukqUz4`q6Jr z-8l8FQap6}FS6feY7UjXUM^T*DhQVA%ssMHPe=|2FE0?#lj&~rW+oNWr|~ctY>)f5 z1%4l#yH@Wq0;Y%edmx;tcI^cW5QixWmka@`Fcd}IK`nQX|5r44k3U2OSB6UdaM2(B J8^OlO@EtlIJChiaa=*-$u6Aypf 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 Iv4;ct-_zg-UH||9 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/core.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b30fcf06ff67a7600075f8eadf72fbc9c3749a1 GIT binary patch literal 135539 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 Sd}6uPp4xTvE6Qau?EeB;TH)RR literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/exceptions.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d559c60beef292208bb20ec6efccef66350261d0 GIT binary patch literal 14750 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 PvJpGO;dBESa4-XPHwXe5 ztYL*I4J0}QW5*aqPBbc~%1}`$BiU>%U0X?9J z*4F;M*WEK1a7gXeZj#4+w1aw5+Uxg>sU zivhU!mOPF4ki4S(INqWIty+q;Mh>N0jePMfRY_IDChAW=(fN#49?_+>8n%e;>z1MF z|EEzrl8247tvC-O_l)tYjPYrf!#2^2In+8i?Vs2nR!CK1C7=Quu^PV`$%hfDhCO2K zb?Z=_i95@QzU!P=cgLiSG_*zBg0Z@caf@%M>baDtl6(b9)MFM6)4ad&A$1?{^SO#p zEUHS^)bU_6I3md?v5!b9l|01qbNF_sk~|)WNKxdS%0wir24WLx&eQ*;H%_1F3%qr{ zZ}42sBFCnboK2S0NjcgTqOQi{K*o&U`U513T$r2X<6Iy2^_Mtq)}$6%#!YwhJnHsw z+}D8jta;X=QeXDO`7x`JFTUeukvC|h+KuwK#eini#re3Ixa~%_g}ZUm!l_Q9t!TQ= zscz#7qZm8DD8l=Wo;RTOJymj%^P2}`TC5W6Y4$z%t?xkcD#wEYaqjCFo8iaLn&PJK z@{2sr-EdpDY3|R=Q@o!a_!z))rmh!q{IwiEtq>4F5T1zLZz__kbgR->P?-p-;YfF1 zEHpVTMOCGHKvJh-@)ad;E*QEJR7Ydc?yFMtYIh`jxqD)ozI(d%ALv%XsTv)4M#`1CZ?Y_kB>-E>Dq*RVn!I3g36>U1=Qf>h}3mF5(@<*%89N* zi(1S~sYmi}+`rFp>8eASwu86Sg}0OK->F9S*XtJ4y;E7u`|UZW6vb5Kpep6eM3o!y-C{ViAQ{0W=W= zxtdyeOJ*vQ;PBw5TtYI(W!u{4`hQkgn=n6UXis(iNyYrR#Oa0F2TiTX;Sa}dk1f?M z1y{Dd@Rz&p_WZ|vD@`va`WJfMd-ai-YuuSPb5*{_4$f1ZsXFw%tEu51L_UgqKYFk2 z;7Zk@75AaE<;GdjrvTFT8x40h27;{-9~0Buj1q!&qJWe*azVCyy@ zmoR55su#{Azxqk-(#1Osnb!Ro-+@fUffdIAP@u~9YlSUhTRWe#kYLDJ*^1;U!qKoA z4n_jus0a?sRV$O173u9swP zoA@F(!o634pGUO5=M|j^Pr{q17&eQx>z-LVMlOhmVsB$)tl$NVqh0gch0{-s5p!Z3(z4(Ub7HQHq2*)n{~}s zV7|i;I-vD?-dXo72inlS+4P9^c`tFDG24R>SaG-99(R=;*EUA`f74T>uK|VUqQWyF zJa>hP5JW5eGlV(t9JRo37^~YfI6mVpqt``jy#1WQPnme`tH1=ke)pRBs~kkEEBF^6 z#VKJ_icCndFgzIzso_{uP)CER5QavKM8c4QYGhiN0@o@6F@BdIyfQ6_(r|DxqV5&K zs*B`LP*EV((1LYUg%|)r#wh~81qB5{H6jTG_7`Hq43=vVp&I6XxO%95ag5%*&L#fgW4QQ1&rST@pg0*#99yWEV=Vy>R5xCBLA?fPxqffm)1u3`jI4$P&?ffMM^iaz_JG{bR5)1z!eS}CoW-WikDAxdHw8$<8I#F*9z`Y1d;IS!?LarGi87#gLuQ>4(O8onyAnUsuPhCz>N91PwZjs!=DM-_=EfTg0fFRUVQ z>lchKlybAqf<^XIw7JNnJfQg8gIMLah)X279~y8cisfBMay7EVXdajvh312m6p{u) zs3<%n)Jbfu|5qe`XkO&zIfb7_D)MAUj}(Na!rVGOItH5J6`u=$QY8bsvIFNA6n?d72wP&UHDSorsQrk7w<`W>2O`h<53 zKH*)Ai2YA^0Y;{k*k&SUV;fA&S;k^vSQI()<;mfkO;_yv1T!h-=H@h$!W9^fOe&+K z(`Q;~kpoOR7OcZ!HQ7AM2oe~FpI6poJvCW(MdI!GLpP7lAAkQua_}>Ed)DKy$9?j2Mx2vtq~>=i$P)`5LaeZn5%K5|f?1ClR*#4*ImIl8+kZC-yV8hbfyfA-Z zLA~#3$=7n#9glpRwetFFYfksvEC1ZOHREVZ*cQwSgITX{)!Ux&!a!fLeYE$!x0_g| zs%Fu7%bDD{+O#jzv~NjVY3jLO)w^aCf4KMd-jur1wD(@szF#@HiWkz}ZkX&_+wv8h zr{?Cd`C|+6`zOi}2Sga|%S z+EJzyGu{w@*#cVB|Y z&>FK4TYyFVw8`I|^PYn#*RMIUFu?vAt2a0bjTDN&Kx1~EqM0m3XO|fb`z{9+C}=VS zp>5z3!^%6a?o^n*np7r(5!irZlhDmkNh0fujDxF^JS`{_QV8x3Q(STsnGhf;do{}r z5Cpi&F$M<0CPsrOF-<*-(p4!!b|R(+3u;P+rXr0QmW9|pVJOO$tI1PlTr$RG`!BroR$zSm zq76QftJ*w$CSP+-G!C$dF!3JJeLlu!Hl(DQ*Z&R)^CYQXpxAOAYKr^eZ=(7kTx9McsUyD&v64~PX%YDxK4t1JlPiS4N;sOUMqmZ{ zPNRQ73C~D5JAxCF<55MUU`1$Bmcb5&KC?mF46Udafr{P_Gz%Ru_|H!>}6qzAve((u-THCxw|u-tHE zx3&?)=4|Kogymaqru#t`W;d6FV2B|YQyfKx;%{SkZ+^;IbaDQU&NMuSsHtgY|6AII z3ks9ba4059x|y!+Kw^9H9horDNZK{vH^~<<7BeG|AEf-3ktnp9M)bR(8N+J9>ZOX#W3=8iJHhqt+)q6E%5=5c@488!*b*paHOPHY25#ev5j1 zjS@0La~3%4BRNY@9zkSWbDK+K742HKRR0E&VX4e>6~#!PSO|xIfTNZ_CTRtyqWrRb z!2Pl51IRem5+QT6Do8bqp+DvOl60E2#;rxUR}7ttR*F7e0Y>sZ(Oj+t#flJXD;p`> z5XCYfMrVoJKC#`==T+QRQK@|I;w)GUupko+Y#>wZMJSkEA!uJ7&keILI9-NJ79E7= z{{=3#^0<`8WaB)sp`0`SqbNia7#y0<&r~=G5M6F)TA%c$9;_f{($qKQDC7|hj!T-V z+|Z1;?Wj=nec_Q)fCOQ6i~}PE3KmVYBZH?pYfO3+3f+kF6ha}z@I;r;r$xX>)t6}Z zOP4y{B#e#<9hWW@fe*~sv|{F%J>gG0Byk2=Sag)SQSgv>1IGk>K$9s<|BybHzd{N5 zIZVg-?V1oJF(qH3B#0#EnWUiu8VWfVd8E3LK>n0M3YW-)M{}XvOu7bGubIYD8MUG6 z7Ipq5k~uE#gGZ4#@t~nGx$6V>!ffhPx^73Jf2~PKRi}DaI}c?#52ZT}r-j4m#v^xq zcWrlr>H3!w9ym*jL$`)f+g3XcX7Io6V8XTLuKV7u)bW+37nToXnht*EKD1WX@Vz6c z*H)VMXX^GR`m>%Y@|qr0HD-McS>M)dXLokTUN~>nHNQ05y%m^@x0?A?@q3D9+(Q+3T_vjuRW ztGzc}^R9*7`;G=pkl9D2pom~piBiSR*QD2L$S|dkZV96(gK?v z9BS(Hgy~^|hhv`UEKr4ZG&@Xrnl7}H3N{C$$z~N+sga=oW2UtnAqv%h1%OHu5|9E> zg=6m>D=-^5^k&Xe&roLpkP;3dna%Xucab4m9GD`v`C)RGxTFjfRN^xBkOeq^s3$n+fVvm8E@}X+kaug^)K(WZlovLdkIMqM}QaCxYgg z;gkz8dShkucqNlJ6ptF*7^Kt!L)ubVG-+3qaU}Q9nDOv-nmXM}7(@<{p zsOIm`S0VcylFPx>)Ges1^}93pU%fkF%fgfdS3mI7WvhJnzv#N<%C>FKcI?V-+x6IO z^Hw}IJDje3%~R4qJCr4VB0z_@Zpu)UmE?m3qZv=Zy4i(wUF3?EP0^^Hjry-FE@hGzK>hrzkWnN zptrGez=CaIAV(gZXa$E=6ibYpF4=7KHgJLsV^?UWmxE+0wz_dbEu6~53+1q$m=}2k z+Yo1Q<)PSN!&j8PtE!+t7`q83gD(S!8;rYCM?elgEd zhe7*Uhf0?T*b}$M9isCS*BxCh;N;XfMoYWtG5qjZSKK9ED34p*rEvu;WLwFqxJ0+; zX`<^We(;F9d~dea&%s<@aW{irur6`hxW@usy0PmSP&d#Ut&ZVz-{bcNqYzI8LC+5F zSgb~~-ku?o5at?!ot){N-Z!^ zw!1D?G!VEuav8^m=*!M@6r4q>Q<8qtq=DKfk`1&rzHzn{Vs3%(-YDe zS&qr_m#AnD1N<>K$>Oj(6oyf*&Nz2%0HvN?|@I|xW_HHAhOW+ z{!GI1pn7XkU8&xdusy&T&(-&jCEGu9H$SLpPPg>0)SOLw&i>q2pR^_4zU@pMUh(Z& zx{~p|m~j5Qbw^75su-m4O_RSgd+>yy^^zmf6-cE^jKRlaD{_oV!vj4n^!iDf!o z$~2$2Uv+X#(|LMNrvH*?wIr@~oyy>U$Ei&7EBC5S|Gcp!Ir!nw?V%-qrnP4|m}xzH zw`QgBc;do?=547jFAaS$l$<bD#P?wS9Uy z-S+x@-y6R$bFDk_Had%ercU<$q)K?ShueBok2H`gSYmsTCMI@caZuyd(esWrnatNE zE&3InqPAu&3Yxjlpl}h6r?Uk9yC%BK28maQaF%O1&3Arbn<-AatHG|snPyUC=L}CG z%C22lM97%kScE9Sl?}$4kVi!Wj4m(e*8JXrY$A!MMd>JtW5m{J3+UpH2&u^%>>zd{ zgi5qAAZ2M76*31W^g8UK7#Z+eqn>U%AP5inzU`i*~2 z^l6#@snEr+cMhCtq2yc2J;fhz~u=(H^e<7X8 z)On}+1pgh2pG)HXam_LFe=(mZB`_gRzjc_I%rh#tGqH!tglG*53)f9eGc9kh`?gwO zR`ZNCN)c}}6$Lub`Lq^--s}lFa8AIq_hvzFly4yl)S*9ozsl;HQ}a^`Djo8!RCcBv zolN$?Qz7*^Fd!2y7>*osIG_)i#-l2KLk@=pw2cCRoGTC*kBO5J%6kHVw{g6t*VqFA zF&09x8AeWyS96XpF>@vuk>3QAoEchF)04%84WmNaZfxUCP&>y(b_Fpc<*b8bvdD32 zMAXhX&LcJ-RH1plL1o{hp$%2;88p$v+N(@A}&OI_Yt&V&X*WQtB-=5v> zf8?yT?pSMT&0FyXZ&X#^oSC0VcFunzZ>JIm=c`*hdh2L1bn9fE+U8xHt76?vxg92J zXYzEO!zO%|?TK3(MKi^mV37Et%GRzu@q#w?QsnWwLHdc0R`Bw`prZ z%aF6{Ms10JqBsECKlhMX#4XNQUZktkWXFTuXU!YD&4N9yojW5sZV}Dw8jne|pb!5A zafgBj8aEGb@aJwEv~cKKM$3uT>l`B8;2L^x9mrnp9;xWKj{Z+yBafSgP1xJcpc??r z;vyDZA~Yhm8ZGoQC))K;NpxX{34n1#ESPc|k0H*B`#f@NLJlMH%d{Vkig_7H1p)04P1Bpf=(HYH4TP0|g5&g2KW_9*jY_yFNXk^RH8n3mp8|6h=ss9b zyBS70noR@ZmEHHlnKc5@QJivXzJQLI7QKa=F{Rysqro%{+t1AICw%u{2`7+*Bu^7Z zjKm3X{Sp^RNA2X4?QPiPm8jovkn_ZG9LLX>#o&pVtwcfklLqpgHe7Mn>-S^s*B9RY!@-XZ{8}bL;Z{BIEIW?W z91;uNy4P+oS>*+)JB=h)TV~yJW{`=6+czHvdp6EY{v!Zrrn#udApGRvT%NgCvQ2Gi zOa0F(x8N3jbyKqE+gnq7rn)0xTXR=0Tzv1PY{!nYr)|yQy6K#Eey3;Q>bH-j%;}nK z_Z{2wUaqP>U&UGN@1FhU*;^HJXYX0svIs}MIR9dX&|LBDSaI)2?>d%tA4^+~X{yQc zaDdPujl`0Ee`C(3PSeFw`8^coT)HiZKapS>LMF>cCaIsZ!<`z(pIGR3!4TKOJ$8+B z#0>KLl+07h%0M6(jmA`FPAE`dnwr7iOUS=Zjc!oFwBb$4ZKFPx%duEQJJMjv=37)l zRNJJAz^0nIJRyG{wIC^{bR*51d7gj3)%=v({!>o)SFZJ^Tr0$N`}R3cBFIE~?R;#7 z+m^T4`NK*6L)UFrYX1)oe{^`MXW6`TB-7cOX*ihYPI zRF?Ny_@1oGeRKEx?uFME-@5fy@?xqp`ISuFj*JU`5J9!QhuM40YI}F+n?noyqWzXV zX--~DIxaWLX#2v^CGVfPZYxbuX3v>J5`@;7&-6`ox#C5oa%NtPT}O`LI)CZLm$wt^ys&^C2tyHVoOsjVKYqM(MmLviKh z?sjHKih|Ngh5dUJGv*9lw&sVO15O6UtTXNm z?SB@};8|Z~N&FTp83wH*Eh9H^7tJi@j40^^HuLTRv;v11O!Bt)O zA_?zp6zXjWShOwZu96nnFp3+{i9T3Ml%)4r;U|&{Sx|h5$&e}6E1V4MdJPoILXoRx zATG+%3(UUAR5kDm4emDzo?9-2EnGjFKR#8EuHw&xD6+_9!S-DHVqwt>%FL7buoWFx z%Xg#eu;J2qYn!RdqWw9)D{a>wd#!{oo%F9twFU>FMgHok($;2QPmZUiU8*kz&H zg$Ev`@%TMVu95+wcFlNb{M$3xFrqLwJi3_A@E&|2$_^!KQB;++ks#z5M6yJq};%# zuGES`;ntXNy%t(sse7~%2wLS{2w_QO-LB$AI;y!{4Hjs#>cVc#U92j&tXASeN(e3$ zT-)`jU1k2F>n~DQNsy?rh6_5&3{ioDccB;~kWXtha{&$Ovbvwd({#GVRdsrylYV(= z2O(eRMZBXVpQjD59j?e6hda~L^jrC3vHt0h309+V;!abyLM2xS-@=@zgEF)%&Su(R zUL7EpbfFmd@Cs!8pzCgJEc&#kp`RMe^;p@9ea8X&3afhvQU?N%fx`rIC8umZCDVKv zJb13|E4Ri^2@!~eyq44Ka`y{pD@W!qJkT^Sh=DI50(J*uG1ng%Dza=Qfu2g5zM`a5 zKoQaK38jQvuB%vml%Dk+zO0XmGQ9`qOwCh~!6l{`rF#;60ygCwbZcb$u$6qtxSbt& zt?_E(H}3BazV+~%4__;99XWn8JGGgb`s{XQ^0zN;4nFxQF+uPj*@@d@hc_Sn!OgLm z_eVD~FSZk8+qI!`1R&B^QQIGEo*AantJ!y53J{6<^{=}h7Qy~eIF+O4^Z7I4=@-x zbLE@ocr9oE4wx`12&u;#9GC<73%6nfin)Zoyhb8Qgh3eB4lE2hn4&@0+qvXpussEj z9D^>tPgul z7gzxaBS~`SX&L}xqKTBCMZ6%mhytO8Qzt({+6}I5!O<^@bGi^is_OdtI3NLY9K@s0 z^(JmK0sI_z4Gwq%f~C$)#1kO*9Lhcg9i(!aq=q*84}F*&|5fIb^doP~{XKnjZRSpY zdhM4VX2)J@z1rGL9lA4^)$Yg{ry;>z{AU6aO7m9E$b%SK zq?h_d5e!9vqW-DKjYfT{6++Dr2VgTAP*uU1gKKncG&FbN(G#bm6 z;5Ur>$n-KY6$iqDG8rEcCmqD7@B-#&cp|GD1YVRn8)Ermp3W+PQKv!J6Px!_->C&o z-Q(XA$3O&WK)wgvcET`>kI2}^xb6*fW^$jmC5zV zwrLnCAT~3zjkE1kXa63q-mta_4A*}Chn0<$8@a8*$xm_pK>S{6!Wcm*7~UQI5i1wa5KKoWe4l)#rrP!eV8Wm~o-QKYDcW7>*j$EM>UA?#8F1p@Q} z6h#_LXvZ0Yj$DzEQ$kHLf^xZvI{U^_rc*1OYtPP1d%o#(N{CX3AaaLym(DbQv;&*I zCh^Qo`}zJBy8!8xlKZ369rCxo{kv@^7iW1|MSS19CUB+%n`I z$k$P052#}pIi!}zzoq&ImOh*>rN)#|vAzvMMtajfTIf+rymeXg`gtU&2zR=N_c>x@LKVxuTS9kW=C(k)_5uI&ep#U$3EWBloL0- z$%%FE0m|sthZPMUv@;zbXINRyrK*Tc|7RQ5< zCld9^QAzZK$Do4qq1~1EKho#>+pQTCo97l^#wvv{7a$@C1^m;O-6^YZl}US(FvMzZ+JW;`l5kw zsKdix5~~snj0R{z*cE?R1W1Gcgn%@;V{DQJ1gMnRV0S(8Naqd&`!;so;pqwnJ**Ic zA*uonJJ#3SrPO@bfOH%AEgi!?FP{-a>D6%w5le1m5w(VL@!t{_MS|s7NXZcWK8mB%(8?N8S>|F2u*-9x)(#`$W&Yv~wA)%R3T>5QhFQy#Xc&9PMJw_> z%vwbA6h1}1c3oLDbrV<6nl_$jmDYk*Yshd4E6d}5TA1LxMZR|cQbz;lfgcFX0z7?Z zKyH9P0GjMX0C5stUZ2ST*F%6C7z+3qZisBRdGG|HILrjegm9zdAQT=(b$mGNgj~i$ zV?O^mLWTME6{I;7kRwqb5>dLqT4LQ2ijW9JF#?gVLU$zku?VlJh-ECkT4v^M3V#oQ)mJ3-&i;jAnf4D z)doHFjE{NLSt?@|C7G}@Ez2{&)iedH@F-RWSam263}PAB;tckML(*UeE7_Of{Zsa+ z)X_tz>*W_-k;|}+e(mJrgHABP-`X&OAMguY5jV@vxMJK$VJYO%qn?ISz!@WiO*TCF z{3b4{;f7{THuBs{+$1-_T`<1HP4GAPKCdxj84F`ehoTuHA{pCp+AReK8e}(G&X^)t znh0SV&&-#DJD&$$kL-*}BfiKOz$Cb{C+t_iYGlS55ezexU9ikRGoH~$7AWL>V?Vq$;+=Txf)jyADHDwI)dAW`v0_!)!4`lcYGD#v4D*}Q(Jcr~>RK`)bPVzP+byC4j z01g)Ci)zkMI_Li06Ei*cODpH5mP;FFPNaK!XAY<9JTpC6lSQbW+mYq)`f1no6W30> z|LV18{*gXEE92}Hzj9F>S7TgQwY%a^r5$d(=epkBpLUd7IzD@RekgJJa`2v`DP3GP zck=C*?ze7VeEz4gW!Ii-v1G%1Wy17>x@0WgwdC59wQ?@^l5|1kC*%gb13`X z+};NwS~JuRk;F+3Li${A&}dkBRVaP~xoy{GvY|FBak zn?ys5BP@*?kWp(vF&LG#u@>l?13l+zl`=dlmHYCV`WRGZxZe_75+@Rf_<}%uUW2?H zDH(y`Smktj6o4p-j0FSH0SsT>g(9Q)kDNv@!=)Y0Im29O{OHV)w8in(^y|}aejCd* zw>v%&FG*W$@y__knG17!?^tl2%I0>>b;TzV#za@*aKeH;S+Z_PW96FWd~;{!TH^ zsIRxm`LaLcevCDiE77{wka0)D=cLd;h-8sqU`iSo8V~u|dU%a&<>Wmmm@$vZ(oo<+ zg!;yjQWmf{UyBxzr0?_ij~qmRMYPyvUYql;RCc5)JC-W`(>LF-IqIFe|n}j z-kmOS$6r)SEJl_qcP~}!S+eh4GVPUjqm7I?5|u$Z^r7p&p#(G=q}AXa1X~0#@0(N! z6I`J&W*E>Yg(%>Q;DtTlJd8zH!5;1vP?%{`%s66E^YZUJx5jf9D@>q2G2~0WSXzyks^K{q}m7(Ym#w^Yhi*I@h2pV1$1Ijep8l?+98l|Uobdq=nsnN@ZLWN&eGaI*i z8rAGq{*=Z>C%^gNb{ca{?8h{Gqq+6o?>VKc9QYzONQG-*l(6qKaE?H%(FM5!yXrM( z1hyX;*TgW$I9LF`1aSvDnXzHfN#Fw2leeI3#`c0QIG&?<0$VVzAU}>AnK)u1gBO5h z$D{Hgd`1KWH1*sebZuNOxf=zhspJHL8E$PeCzP(*oR_xEZkroQ_Qba>+q^T~=}lW^ zy6>8*(-l=S-Ea1#ZH}34qH>#mT~QrB0t|TR#O#T=@q3Q?&x~AUP1eOZoHHkW|3xw9 zsQjEW37bKuiX4}0v$nb23y;q~e$QIJYA=~Nku65vml2}RH>$f#+{dQouI}Y@$uF4;e)Jndo5(}K=7id; zc#`*)$|St?VOP(LWFYvQ^w;p4R| zki-Hcrx-VYPvv1>8m5a9(6C1xF3M6}_As3HmjD_|RFh_778NTo+G3q9idiGhywoc4 zG0P7*(ePuVTJ8-{NSbpP8Q#F!u%2(=dO&%pa@w&zYe*QuOwLiHn(L45C0(1uLIlWfQ(MiVzd z4mBZ((h=eSAl8&|b(`a+yVmM-ZC%`S(RshQ_0NtVQv46)Rq^iobuCH%5Bp}HiTBPO z`Biz%{YuYL)6q|iAB}&~wbanJT>0#h>)Eu!b?KSeXI32bDMx)`D0%Wq;I5QrQDJE<}I~yJ%mUDdQkq0b?fwkGJe}w+7yhO z$GU`;Gd7@fQ5y1%2ct^UMwkHrgJR6h+w_2XBm^ju>3@(N^-a% z_x&HKB+SIX3u(La(i5{!BwFv-8`90*_z}iJMoHDQ>}W_AmtJ~#_T|JgcZ$8~<~Guy z6qdM?FLCTnadX;HO0`!U4Jk)MviZ9Ans@Q*%Z^7@9FL|PkKPvUIS!}|_T4FN|0Bgs ze{K7@?Vh7st#b5EaT7*JW4PXTt?%ZZ4FM z8Pl0?I4FMuiSii)H#h|ildg+#mn^u7uL$vcZ*o}&*VLM>s7yDte&*aFRIL`*WCgsl zX3pulG%`DqD4z{yEtFy{Oevxi8&_JkV4JrkcF#Mrc1m$@uJUX##Y#9=>7}XJsYJuo zmMbkOr)Q0t&mQJEb4k{~3%e4hp;Z)itr^vXthrcdNu0d;{FUdk9HNT{*z30V1$`;= zAQa%ozxJrC@7iA>DK9UG4pIS#M)2NNt*jQwNeU*(4DMS1?+$ZT*dM|N^q{sB<7W&fIGCO^PC_)i2}M_rrs7v| zD$I7qys(p}lZ@IJMJS3w2VzFicn++m{CHG_DK0Pgh?+U>0T^9l$uXzgqfa;97gXA$ zj*f{)YNdjA&YW0}c2udjAXkstyl#o{Fx3H6WCP8LaY{NciWYUoOOy|k(p}I=E;>Rx zyW!Cvl{zOLh7zw;L3ZmDbp(Z^#ar8o;AxI$yZj179~$lJ{6(|K|4V*>hj?T+p^d*Z zPVit>nV2Gvq6(CghK@(%c0>!+wqF)KNlpb9#^eK2O&WCOh*94Bp%wajs!s;R|3Pa0 zrK)|`_9lFbT{n*Zh`+Y?56n*RhNTqN;!<9*X|$@1dR`;k+#pYT7#mEVFm6nH6nUlN zh9P630!;q-?f=1}4BMdy>_*tr6mf}wO!gwkm=%`~<;c*Rn#zC;zKf6D{zkMKGUcFS_yyR#` zc;8)>qLo;#+PCc92X&9r{Uc-I$PaCIoQ>(~x_Kd8TA670e(n9rt@qs(OO*$g-G^4( zM^o;j>H3DNFI{un~YG( z!xRfpzzC)Ae2A1MXDNXeifv8-iDW34f_wOn1QEQ+eP%EURf)bVhu6)958H3G-#&F~ zC;R-QX^m2|wkn}z74&jqc4F?;g{k?eWYhe&7x@otH*7aMKiq$7|84)RgQ>RerK;|f zvnMN{IOglxoV8HQ%GpZ3C_+pb2z9@X#?k)LvqmPn0vg9ZjMfnK8#0L|P#5#05voH% zxny1gwB|4`okjJbIN{MX!U79i;2~Zb)yQDf%tc_tU3wNpC zD0;w&nDmtVqNxV$h=ORqUYWs(m~)!W29a?HsHKDZB`d3C({D4EYkz32Ln;!BA5g-i zM+3BRmWU-7rybhZMvT!3ou}^1a-*PrXm(c7g<1}{T$=QpLUW}Bs{tB@UY4uX2lKy~MS;fsLTeYG77Nk{^i)6;3NMLk^;Iy(0 zKu8WCVMXCL#!{Kr9~@W6$`FDX#vk-Wat?j4`#=y3!1a*aC}FT6S2i2*eXMG(9TF{`tM_ZXsro@~#d_$yYM4w6}Dtv~FQW4gY&l7={98dx?L!F0@Cb~ir>>on` zblCOWan_>hL!!6|22qH-3E+=H!(uIo0a@}>Z5X@Au0%eTIS)(4^^eUAcB={5H%2Zv z0M#(t+-zVPBkLKOMO`+IyyK_lK+0TV z$e%^a!_1&^-RKA!f$to;V$F~rC_0rrIe9!nzMi!9IZG1^#QSqQ0EZgIDRDoW;{L&J zF%OWAZpFoJ&@;h2GntR4vgxcLYD|4{9y({k%ubkdvS9{YW`$N1i@LPoXMk{U<)n1h zU>z!duE2OoQixU;99<&}&)Te@!vE|y$WjUj3Q|! z2k@an-|5~j`5j*xcI*Iw*n@JJDy(C80(xY!w?T3SU@=dbOl5#sJmD3>^eCkL2E#zg za7{CwDbf_Irim(EEJ<%} zNbX6zOpVm0TfG{gRP^w@=P3+j$1b&d2=hawc=~BKE-37|zzn351w?p?0i+xe1j8LU84lQN3+E6bzipc^RsR z%*zlrd9edwh6$HKR)XtT07z7838KRJfC#5!kEcsfANt{6fU>^OB>4#r4l;G*Ap8h& zQAG`j1g(w1K}A8S6e?6!4h|BA8ysXR%RxBzX?193gRprH!jqfzmm@zO3?>u}3@Hdt zIf`Jx0O$#uZm1voiij5em>4*rOPc_B{HbN%AWuP&a{e6M(4KbC{h?!3=)0njN7vg+_XIM}ABg|-t^Mz#Y1!mi>S9Mn)B@ueD; zXIEi}+gQ(K6GJ)y{#s>r$=#T)_Gpc$0091!`Er5zBnA{%J4ZGYWC_%W+eE;a>^97q z5pd8*VGMMh1`x&ugARt3hDAO}#Khx%5}d(2$JcqmD-=(Nolbr(%XB#!wAlnKVwU@~c_2xH3s#3UgNqkF`KB0NOD? zm>=?o!sNU`C42~Q?3fyY&VY_l%f{#h>v;n{&S&(}VI$ijoP^7`()z?{=I5I=2t}3f z8(49)ryT8zd+$0r*;i}I(Yh$yb#y@4w>qZ_T%XHCw=4`Q zAILn2jMJvP_Ylsdc7pTWt9Syu7JRr_En(WMf71m#By$3Tia*DJLXliYel{^aFK|FW z;PXPtq}m{%aM7c0+JZuoFDH;N)wB+k>x1=+c{saY*+>S>r)Qr|v|QbGWn0S8a@+mawg0Ym zxwYr#wKuzqHUCzaK4;T`)QK6i3$M|eiz-!DIGv#kRw0un~tgAAG(rI@jzLuXHTX#o5IB%C_isI*IZxNH$fDDOjVT9U5!>o5Zy@-(9A`wChuBx<4h2h3c@2@Nu|b}YzpqF)mirLIqsT?KCK z1l@9+0y;5ZLuV)sNsLph3yga$)<6opXGET*Tn5y{BxKCEh6Yn>L9OSDKJu7t`Dg2do+}wA&>u39!e^q13)d)^TxaaCf zmsYHl?zmIB14wbfK5t)fDVg_Nt*h%&I+Ompu6DGY-NZTFm(IO&PT_yH(^N}TDM;~f zTF1Q7!ZP^&eh$6?A4uBxoag0E=5Ef98m4i19@q1LZ1l^jNNHNg+Za(64t{zl^L?Yr z^ghT!7~@G}$&jHQ!A>1(t%Wr)*REuHEjub(MLE977W7MCkB3pXd$!n$wWdGs$o^A27#dbQwrGOW6fWu z&v^#M7M;ZZfR>nA2^Uzzh0uH`WpDn}(fN0E zI~M(LayfA8z;fN;_%rv*HYXxCcYJjEZ(jWP#k*yFOOC$P(u#%6^P7{#RB1DWNPFpu zz5b599_lF9<|U_h{n_hGhVHud!hdna-H~#4EJkkj-afMIK0JG5wRqD~aqImuPuf-f z?#ZR9gUc0%Rw|CBDvo|~YN_Jra>Ypytn!j9XDBW~+sqDVExA-OTQWDEkW}XxnXr?e zj->i%oJ~IfgKm9H8$}#K7{QI~UPI7n5l)t-M-~@rzE`7T_5~PhXCTt>ADG6 zV?`itxm}yKg|HXXHjGg3h}#OuV9XfdFJ|D%$b)~=MUe8Ym|5P5k%KSX_~@=F_FFWM zkb!T*lfU;&(4e9vLNkouTKakw4+L6xU2pE({vQqO8J1|6z$xol{WZ?mFrk}j6txZ zVhp?$4U;Q}G&CLdRJ|V7(6axW(8e|dAmC1S+>~|{$9W>oC+91H2jEfdTrI1hn{1a` zp> zHjr|>;@wDM_vH)Ue=_Z^S$KN>=@s|ZlzVIP)y1Yo-{P6Y*1PUqxW_WrvszuZQoSox zz3b-g+vbmiySeh(>;d>Gtk}2Sv2VR` zFvo7MI5wvoo0D6U)r*ZEwBBgFxpTSw@RGNCX-m&N#}Tm3+n-pnZ)I#n#;&kH%(ai< z@pU`}5d+3kGy{@IjjqR0KqS(T9H_Sr;!y!KW;%y<LHXv-Yc z(3IMz+!`}O7BJCOP(6DvWP!?p71e&?0ORbzIKQ$Y`s3C^ZlcD)%S1LDq*+^hr6_D!7=ZM3%`M# zY@F^REZa9Fq&xN|U=UKftT?ybac=ufwRcX)J_c1x-0{U;uBs*N-g4hvm##jTu0E2k zu3xj5Dk^_x<*MrEhmzZFK0i0KT=~RWv4xzOEO2IWaV6z*zPI~P^s4=eJ=t}oBz|1! z9qzCzuI+bR+wZ$KCnn!-VhF81aVGKV+%w73D=m+v@aKLMzE+8%%YDg{cidY^L~qA< z;4+KxWbItdW@`1S^NMqkU#_MsFkCcL3s+IA2>;2U?E-Jmj%4RUm#s!2G|j~ zMW2jIc!OfZDtOHsh(8kzGFJ5xR)$@y);N21*TidTsUYopGe$%(y`dG@*96vT6TCJ*$AG=@Ok{pJIyY-fJ zx%%;Van|N4f)75lo1T=zldQj4@)2C_d+`eqn?C1Cikb<6%X1gs#g)yEr10l_go*Ag zDOXF<4~3|!6TgbEs!@Jd#j2vyQiyCK@=HfkwjOPL$=r$mZF!fC``EVqaFg-l$J!A7 zqLD|)?y1XuTDoakx*A!exJ1Daf{bNgKn(i_1`0d@ndjG8Dltq!fC3`F^7kotmxAvg z$OxzDM_Mwbo`63p|0_yv+5H9n_*H_J`Qzga z{`eI8ia&nVNy#qw9vjoy((a0d-uYf!1b8}Y#P@2E?NZfj)m-U9C4R=jsCe}!Y^l+LP6UB{P7kEe=GtO=-@Z7vdO7QdF|@S-)rD_dD2R4vA`99|!p*65Wz z#@7ig>GH~~k=|`y=4!e7hEw@I^fmToV?=)T$*n>!pX|L*Awu?&@J0-uUGynYrrMSCU_vQ#K7Q#RNrzxeb^&m9@) zK6a%0>EnGzGo?!7139-P@=!70hMma|d!AxQBx9`N&%>a!mp%yt%A}XeSWd&`=moeK zlNK{$hVdPPlm89nZ#W|Vp3=TW0lDC@BciCschTo#6m(O-4haMKQTp6X0o^+J()y%w zx#fWT2|jTOxX3dI@l!H9|CynTH?4JWeEFwb{imGgQ?Bm6b8Vk;TR-KRKjj)%ji$E_ zzH#u^rp8ZA9iN)&KQ*;~YIQCotoX5HPUx$+x4kyQ#YHgeVcu+3g)-I@%lI7ColES_9ytOmMfN|5kT30t^X$f zq3xFK_U>EGRLh}{nwLDisp_Mt;$xpQ{MW62yLIX0>A&5!RQ!BOcwtRI!`TbGnXjGO zo#pUKbY6Y*%A=53jLFARo3^h}TDHu@@0*Ljb(G(iEWKWPt#mlCvdS zcxU2NmcuK5FxKevcRl=WzU4Cx!S8~6Jw*}x?hr5Vou6?Ce&;%E;+sF`C}hk1e*thY BXNCX( literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/shell_completion.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/shell_completion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0245ca6516a01578236a42f743c678d50db332a GIT binary patch literal 22771 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/testing.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..015e6d8a0bf958f47dd76b58617e3571ece15107 GIT binary patch literal 24576 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 R3!sOiCT*{M(Zck`{|k#l-mCxs literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/__pycache__/utils.cpython-312.pyc b/venv/lib/python3.12/site-packages/click/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14e53debb3d8435a682b00e05407589ee651826e GIT binary patch literal 26306 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/click/_compat.py b/venv/lib/python3.12/site-packages/click/_compat.py new file mode 100644 index 0000000..23f8866 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/_compat.py @@ -0,0 +1,623 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +WIN = sys.platform.startswith("win") +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO[t.Any]) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO[t.Any], bool], bool], + find_binary: t.Callable[[t.IO[t.Any]], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, "os.PathLike[str]", int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO[t.Any]: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: "t.Union[str, os.PathLike[str]]", + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO[t.Any], bool]: + binary = "b" in mode + filename = os.fspath(filename) + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO[t.Any], af), True + + +class _AtomicFile: + def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( # noqa: F811 + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO[t.Any]) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.Optional[t.TextIO]], + wrapper_func: t.Callable[[], t.TextIO], +) -> t.Callable[[], t.Optional[t.TextIO]]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.Optional[t.TextIO]: + stream = src_func() + + if stream is None: + return None + + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/venv/lib/python3.12/site-packages/click/_termui_impl.py b/venv/lib/python3.12/site-packages/click/_termui_impl.py new file mode 100644 index 0000000..f744657 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/_termui_impl.py @@ -0,0 +1,739 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ +from io import StringIO +from types import TracebackType + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label: str = label or "" + + if file is None: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + file = StringIO() + + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width: int = width + self.autowidth: bool = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter: t.Iterable[V] = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.last_eta: float + self.start: float + self.start = self.last_eta = time.time() + self.eta_known: bool = False + self.finished: bool = False + self.max_width: t.Optional[int] = None + self.entered: bool = False + self.current_item: t.Optional[V] = None + self.is_hidden: bool = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar[V]": + self.entered = True + self.render_progress() + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if stdout is None: + stdout = StringIO() + + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + return _tempfilepager(generator, pager_cmd, color) + return _pipepager(generator, pager_cmd, color) + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if WIN or sys.platform.startswith("os2"): + return _tempfilepager(generator, "more <", color) + if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: + return _pipepager(generator, "less", color) + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: + return _pipepager(generator, "more", color) + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) + try: + for text in generator: + if not color: + text = strip_ansi(text) + + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): + pass + else: + stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: + """Page through text by invoking a program on a temporary file.""" + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + os.system(f'{cmd} "{filename}"') + finally: + os.close(fd) + os.unlink(filename) + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if os.system(f"which {editor} >/dev/null 2>&1") == 0: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url.replace('"', "")) + args = f'explorer /select,"{url}"' + else: + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' + return os.system(args) + elif CYGWIN: + if locate: + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' + else: + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' + return os.system(args) + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import tty + import termios + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/venv/lib/python3.12/site-packages/click/_textwrap.py b/venv/lib/python3.12/site-packages/click/_textwrap.py new file mode 100644 index 0000000..b47dcbd --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> t.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/venv/lib/python3.12/site-packages/click/_winconsole.py b/venv/lib/python3.12/site-packages/click/_winconsole.py new file mode 100644 index 0000000..6b20df3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/_winconsole.py @@ -0,0 +1,279 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +import io +import sys +import time +import typing as t +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self): + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/venv/lib/python3.12/site-packages/click/core.py b/venv/lib/python3.12/site-packages/click/core.py new file mode 100644 index 0000000..cc65e89 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/core.py @@ -0,0 +1,3042 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat +from types import TracebackType + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.MutableMapping[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.MutableMapping[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[ + t.Callable[[str], str] + ] = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional["Context"] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + @t.overload + def invoke( + __self, # noqa: B902 + __callback: "t.Callable[..., V]", + *args: t.Any, + **kwargs: t.Any, + ) -> V: + ... + + @t.overload + def invoke( + __self, # noqa: B902 + __callback: "Command", + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: + ... + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", "t.Callable[..., V]"], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Union[t.Any, V]: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = t.cast("t.Callable[..., V]", other_cmd.callback) + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.MutableMapping[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, info_name=info_name, parent=parent, **extra # type: ignore + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invocable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt) as e: + echo(file=sys.stderr) + raise Abort() from e + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + + .. versionchanged:: 8.2.0 + Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). + """ + if complete_var is None: + complete_name = prog_name.replace("-", "_").replace(".", "_") + complete_var = f"_{complete_name}_COMPLETE".upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List["Parameter"] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + return Option( + help_options, + is_flag=True, + is_eager=True, + expose_value=False, + callback=show_help, + help=_("Show this message and exit."), + ) + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + if self.help is not None: + # truncate the help text to the first form feed + text = inspect.cleandoc(self.help).partition("\f")[0] + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + :param attrs: Other command arguments described in :class:`Command`. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[ + t.Union[t.MutableMapping[str, Command], t.Sequence[Command]] + ] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.MutableMapping[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: + ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: + ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": + ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: + ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + + See :class:`MultiCommand` and :class:`Command` for the description of + ``name`` and ``attrs``. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The latter is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name: t.Optional[str] + self.opts: t.List[str] + self.secondary_opts: t.List[str] + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type: types.ParamType = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator[t.Any]: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + + def convert(value: t.Any) -> t.Any: + return self.type(value, param=self, ctx=ctx) + + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + :param attrs: Other command arguments described in :class:`Parameter`. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + self.default: t.Union[t.Any, t.Callable[[], t.Any]] + + if is_flag and default_is_missing and not self.required: + if multiple: + self.default = () + else: + self.default = False + + if flag_value is None: + flag_value = not self.default + + self.type: types.ParamType + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag: bool = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError("Could not determine name for option") + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if self.default else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return t.cast(Option, param).flag_value + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the constructor of :class:`Parameter`. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Could not determine name for argument") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/venv/lib/python3.12/site-packages/click/decorators.py b/venv/lib/python3.12/site-packages/click/decorators.py new file mode 100644 index 0000000..d9bba95 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/decorators.py @@ -0,0 +1,561 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") +T = t.TypeVar("T") +_AnyCallable = t.Callable[..., t.Any] +FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) + + +def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(new_func, f) + + +def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + +def make_pass_decorator( + object_type: t.Type[T], ensure: bool = False +) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + ctx = get_current_context() + + obj: t.Optional[T] + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + return decorator # type: ignore[return-value] + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator # type: ignore[return-value] + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +# variant: no call, directly as decorator for a function. +@t.overload +def command(name: _AnyCallable) -> Command: + ... + + +# variant: with positional name and with positional or keyword cls argument: +# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) +@t.overload +def command( + name: t.Optional[str], + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: + ... + + +# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) +@t.overload +def command( + name: None = None, + *, + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: + ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def command( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Command]: + ... + + +def command( + name: t.Union[t.Optional[str], _AnyCallable] = None, + cls: t.Optional[t.Type[CmdType]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = t.cast(t.Type[CmdType], Command) + + def decorator(f: _AnyCallable) -> CmdType: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + if t.TYPE_CHECKING: + assert cls is not None + assert not callable(name) + + cmd = cls( + name=name or f.__name__.lower().replace("_", "-"), + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +GrpType = t.TypeVar("GrpType", bound=Group) + + +# variant: no call, directly as decorator for a function. +@t.overload +def group(name: _AnyCallable) -> Group: + ... + + +# variant: with positional name and with positional or keyword cls argument: +# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) +@t.overload +def group( + name: t.Optional[str], + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: + ... + + +# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) +@t.overload +def group( + name: None = None, + *, + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: + ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def group( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Group]: + ... + + +def group( + name: t.Union[str, _AnyCallable, None] = None, + cls: t.Optional[t.Type[GrpType]] = None, + **attrs: t.Any, +) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if cls is None: + cls = t.cast(t.Type[GrpType], Group) + + if callable(name): + return command(cls=cls, **attrs)(name) + + return command(name, cls, **attrs) + + +def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument( + *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default argument class, refer to :class:`Argument` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Argument + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def option( + *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default option class, refer to :class:`Option` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Option + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + message % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/venv/lib/python3.12/site-packages/click/exceptions.py b/venv/lib/python3.12/site-packages/click/exceptions.py new file mode 100644 index 0000000..fe68a36 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/exceptions.py @@ -0,0 +1,288 @@ +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .utils import echo +from .utils import format_filename + +if t.TYPE_CHECKING: + from .core import Command + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + + echo(_("Error: {message}").format(message=self.format_message()), file=file) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd: t.Optional["Command"] = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename: str = format_filename(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code: int = code diff --git a/venv/lib/python3.12/site-packages/click/formatting.py b/venv/lib/python3.12/site-packages/click/formatting.py new file mode 100644 index 0000000..ddd2a2f --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer: t.List[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> t.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> t.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/venv/lib/python3.12/site-packages/click/globals.py b/venv/lib/python3.12/site-packages/click/globals.py new file mode 100644 index 0000000..480058f --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/globals.py @@ -0,0 +1,68 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/venv/lib/python3.12/site-packages/click/parser.py b/venv/lib/python3.12/site-packages/click/parser.py new file mode 100644 index 0000000..5fa7adf --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/parser.py @@ -0,0 +1,529 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes: t.Set[str] = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: t.Any, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List["CoreParameter"] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args: bool = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options: bool = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we recombine the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/venv/lib/python3.12/site-packages/click/py.typed b/venv/lib/python3.12/site-packages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/click/shell_completion.py b/venv/lib/python3.12/site-packages/click/shell_completion.py new file mode 100644 index 0000000..dc9e00b --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/shell_completion.py @@ -0,0 +1,596 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value: t.Any = value + self.type: str = type + self.help: t.Optional[str] = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + %(complete_func)s "$@" +else + # eval/source/. command, register function for later + compdef %(complete_func)s %(prog_name)s +fi +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + @staticmethod + def _check_version() -> None: + import subprocess + + output = subprocess.run( + ["bash", "-c", 'echo "${BASH_VERSION}"'], stdout=subprocess.PIPE + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + echo( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ), + err=True, + ) + else: + echo( + _("Couldn't detect Bash version, shell completion is not supported."), + err=True, + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: ShellCompleteType, name: t.Optional[str] = None +) -> ShellCompleteType: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + return cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + # Will be None if expose_value is False. + value = ctx.params.get(param.name) + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + args: t.List[str], +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + sub_ctx = ctx + + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/venv/lib/python3.12/site-packages/click/termui.py b/venv/lib/python3.12/site-packages/click/termui.py new file mode 100644 index 0000000..db7a4b2 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/termui.py @@ -0,0 +1,784 @@ +import inspect +import io +import itertools +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + + # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor + echo("\033[2J\033[1;1H", nl=False) + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/venv/lib/python3.12/site-packages/click/testing.py b/venv/lib/python3.12/site-packages/click/testing.py new file mode 100644 index 0000000..e0df0d2 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/testing.py @@ -0,0 +1,479 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(input) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env: t.Mapping[str, t.Optional[str]] = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) + os.chdir(dt) + + try: + yield dt + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: # noqa: B014 + pass diff --git a/venv/lib/python3.12/site-packages/click/types.py b/venv/lib/python3.12/site-packages/click/types.py new file mode 100644 index 0000000..2b1d179 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/types.py @@ -0,0 +1,1089 @@ +import os +import stat +import sys +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import format_filename +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name: str = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = sys.getfilesystemencoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats: t.Sequence[str] = formats or [ + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%d %H:%M:%S", + ] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type[t.Any]] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Starting with Click 2.0, files can also be opened atomically in which + case all writes go into a separate file in the same folder and upon + completion the file will be moved over to the original location. This + is useful if a file regularly read by other users is modified. + + See :ref:`file-args` for more information. + """ + + name = "filename" + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: "t.Union[str, os.PathLike[str]]") -> bool: + if self.lazy is not None: + return self.lazy + if os.fspath(value) == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, + value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> t.IO[t.Any]: + if _is_file_like(value): + return value + + value = t.cast("t.Union[str, os.PathLike[str]]", value) + + try: + lazy = self.resolve_lazy_flag(value) + + if lazy: + lf = LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + if ctx is not None: + ctx.call_on_close(lf.close_intelligently) + + return t.cast(t.IO[t.Any], lf) + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: # noqa: B014 + self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": + return hasattr(value, "read") or hasattr(value, "write") + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``path_type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type[t.Any]] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name: str = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result( + self, value: "t.Union[str, os.PathLike[str]]" + ) -> "t.Union[str, bytes, os.PathLike[str]]": + if self.type is not None and not isinstance(value, self.type): + if self.type is str: + return os.fsdecode(value) + elif self.type is bytes: + return os.fsencode(value) + else: + return t.cast("os.PathLike[str]", self.type(value)) + + return value + + def convert( + self, + value: "t.Union[str, os.PathLike[str]]", + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> "t.Union[str, bytes, os.PathLike[str]]": + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} '{filename}' is a directory.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type[t.Any], ParamType]]) -> None: + self.types: t.Sequence[ParamType] = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/venv/lib/python3.12/site-packages/click/utils.py b/venv/lib/python3.12/site-packages/click/utils.py new file mode 100644 index 0000000..d536434 --- /dev/null +++ b/venv/lib/python3.12/site-packages/click/utils.py @@ -0,0 +1,624 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType +from types import TracebackType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: "t.Callable[P, R]") -> "t.Callable[P, t.Optional[R]]": + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> t.Optional[R]: + try: + return func(*args, **kwargs) + except Exception: + pass + return None + + return update_wrapper(wrapper, func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(sys.getfilesystemencoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: t.Union[str, "os.PathLike[str]"], + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name: str = os.fspath(filename) + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO[t.Any]] + self.should_close: bool + + if self.name == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO[t.Any]: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: # noqa: E402 + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO[t.Any]) -> None: + self._file: t.IO[t.Any] = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + return + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO[t.Any]: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast( + t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) + ) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO[t.Any], KeepOpenFile(f)) + + return f + + +def format_filename( + filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", + shorten: bool = False, +) -> str: + """Format a filename as a string for display. Ensures the filename can be + displayed by replacing any invalid bytes or surrogate escapes in the name + with the replacement character ``�``. + + Invalid bytes or surrogate escapes will raise an error when written to a + stream with ``errors="strict". This will typically happen with ``stdout`` + when the locale is something like ``en_GB.UTF-8``. + + Many scenarios *are* safe to write surrogates though, due to PEP 538 and + PEP 540, including: + + - Writing to ``stderr``, which uses ``errors="backslashreplace"``. + - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens + stdout and stderr with ``errors="surrogateescape"``. + - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. + - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. + Python opens stdout and stderr with ``errors="surrogateescape"``. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + else: + filename = os.fspath(filename) + + if isinstance(filename, bytes): + filename = filename.decode(sys.getfilesystemencoding(), "replace") + else: + filename = filename.encode("utf-8", "surrogateescape").decode( + "utf-8", "replace" + ) + + return filename + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no effect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO[t.Any]) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + # It is set to "" inside a Shiv or PEX zipapp. + if getattr(_main, "__package__", None) in {None, ""} or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/LICENSE.txt b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/METADATA b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/METADATA new file mode 100644 index 0000000..5a02107 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/METADATA @@ -0,0 +1,101 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 3.0.3 +Summary: A simple framework for building complex web applications. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Typing :: Typed +Requires-Dist: Werkzeug>=3.0.0 +Requires-Dist: Jinja2>=3.1.2 +Requires-Dist: itsdangerous>=2.1.2 +Requires-Dist: click>=8.1.3 +Requires-Dist: blinker>=1.6.2 +Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10' +Requires-Dist: asgiref>=3.2 ; extra == "async" +Requires-Dist: python-dotenv ; extra == "dotenv" +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/flask/ +Provides-Extra: async +Provides-Extra: dotenv + +# Flask + +Flask is a lightweight [WSGI][] web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around [Werkzeug][] +and [Jinja][], and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +[WSGI]: https://wsgi.readthedocs.io/ +[Werkzeug]: https://werkzeug.palletsprojects.com/ +[Jinja]: https://jinja.palletsprojects.com/ + + +## Installing + +Install and update from [PyPI][] using an installer such as [pip][]: + +``` +$ pip install -U Flask +``` + +[PyPI]: https://pypi.org/project/Flask/ +[pip]: https://pip.pypa.io/en/stable/getting-started/ + + +## A Simple Example + +```python +# save this as app.py +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def hello(): + return "Hello, World!" +``` + +``` +$ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + + +## Contributing + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the [contributing guidelines][]. + +[contributing guidelines]: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst + + +## Donate + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/RECORD b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/RECORD new file mode 100644 index 0000000..8130da5 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/RECORD @@ -0,0 +1,58 @@ +../../../bin/flask,sha256=GjjNCmIZ43wujdezIXTITwlfrcLWb86nRDkXBcP_-bE,258 +flask-3.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask-3.0.3.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +flask-3.0.3.dist-info/METADATA,sha256=exPahy4aahjV-mYqd9qb5HNP8haB_IxTuaotoSvCtag,3177 +flask-3.0.3.dist-info/RECORD,, +flask-3.0.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask-3.0.3.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +flask-3.0.3.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40 +flask/__init__.py,sha256=6xMqdVA0FIQ2U1KVaGX3lzNCdXPzoHPaa0hvQCNcfSk,2625 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-312.pyc,, +flask/__pycache__/__main__.cpython-312.pyc,, +flask/__pycache__/app.cpython-312.pyc,, +flask/__pycache__/blueprints.cpython-312.pyc,, +flask/__pycache__/cli.cpython-312.pyc,, +flask/__pycache__/config.cpython-312.pyc,, +flask/__pycache__/ctx.cpython-312.pyc,, +flask/__pycache__/debughelpers.cpython-312.pyc,, +flask/__pycache__/globals.cpython-312.pyc,, +flask/__pycache__/helpers.cpython-312.pyc,, +flask/__pycache__/logging.cpython-312.pyc,, +flask/__pycache__/sessions.cpython-312.pyc,, +flask/__pycache__/signals.cpython-312.pyc,, +flask/__pycache__/templating.cpython-312.pyc,, +flask/__pycache__/testing.cpython-312.pyc,, +flask/__pycache__/typing.cpython-312.pyc,, +flask/__pycache__/views.cpython-312.pyc,, +flask/__pycache__/wrappers.cpython-312.pyc,, +flask/app.py,sha256=7-lh6cIj27riTE1Q18Ok1p5nOZ8qYiMux4Btc6o6mNc,60143 +flask/blueprints.py,sha256=7INXPwTkUxfOQXOOv1yu52NpHPmPGI5fMTMFZ-BG9yY,4430 +flask/cli.py,sha256=OOaf_Efqih1i2in58j-5ZZZmQnPpaSfiUFbEjlL9bzw,35825 +flask/config.py,sha256=bLzLVAj-cq-Xotu9erqOFte0xSFaVXyfz0AkP4GbwmY,13312 +flask/ctx.py,sha256=4atDhJJ_cpV1VMq4qsfU4E_61M1oN93jlS2H9gjrl58,15120 +flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080 +flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713 +flask/helpers.py,sha256=tYrcQ_73GuSZVEgwFr-eMmV69UriFQDBmt8wZJIAqvg,23084 +flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602 +flask/json/__pycache__/__init__.cpython-312.pyc,, +flask/json/__pycache__/provider.cpython-312.pyc,, +flask/json/__pycache__/tag.cpython-312.pyc,, +flask/json/provider.py,sha256=q6iB83lSiopy80DZPrU-9mGcWwrD0mvLjiv9fHrRZgc,7646 +flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281 +flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228 +flask/sansio/__pycache__/app.cpython-312.pyc,, +flask/sansio/__pycache__/blueprints.cpython-312.pyc,, +flask/sansio/__pycache__/scaffold.cpython-312.pyc,, +flask/sansio/app.py,sha256=YG5Gf7JVf1c0yccWDZ86q5VSfJUidOVp27HFxFNxC7U,38053 +flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637 +flask/sansio/scaffold.py,sha256=WLV9TRQMMhGlXz-1OKtQ3lv6mtIBQZxdW2HezYrGxoI,30633 +flask/sessions.py,sha256=RU4lzm9MQW9CtH8rVLRTDm8USMJyT4LbvYe7sxM2__k,14807 +flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750 +flask/templating.py,sha256=2TcXLT85Asflm2W9WOSFxKCmYn5e49w_Jkg9-NaaJWo,7537 +flask/testing.py,sha256=3BFXb3bP7R5r-XLBuobhczbxDu8-1LWRzYuhbr-lwaE,10163 +flask/typing.py,sha256=ZavK-wV28Yv8CQB7u73qZp_jLalpbWdrXS37QR1ftN0,3190 +flask/views.py,sha256=B66bTvYBBcHMYk4dA1ScZD0oTRTBl0I5smp1lRm9riI,6939 +flask/wrappers.py,sha256=m1j5tIJxIu8_sPPgTAB_G4TTh52Q-HoDuw_qHV5J59g,5831 diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/REQUESTED b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/WHEEL b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/entry_points.txt b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/entry_points.txt new file mode 100644 index 0000000..eec6733 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask-3.0.3.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +flask=flask.cli:main + diff --git a/venv/lib/python3.12/site-packages/flask/__init__.py b/venv/lib/python3.12/site-packages/flask/__init__.py new file mode 100644 index 0000000..e86eb43 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/__init__.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import typing as t + +from . import json as json +from .app import Flask as Flask +from .blueprints import Blueprint as Blueprint +from .config import Config as Config +from .ctx import after_this_request as after_this_request +from .ctx import copy_current_request_context as copy_current_request_context +from .ctx import has_app_context as has_app_context +from .ctx import has_request_context as has_request_context +from .globals import current_app as current_app +from .globals import g as g +from .globals import request as request +from .globals import session as session +from .helpers import abort as abort +from .helpers import flash as flash +from .helpers import get_flashed_messages as get_flashed_messages +from .helpers import get_template_attribute as get_template_attribute +from .helpers import make_response as make_response +from .helpers import redirect as redirect +from .helpers import send_file as send_file +from .helpers import send_from_directory as send_from_directory +from .helpers import stream_with_context as stream_with_context +from .helpers import url_for as url_for +from .json import jsonify as jsonify +from .signals import appcontext_popped as appcontext_popped +from .signals import appcontext_pushed as appcontext_pushed +from .signals import appcontext_tearing_down as appcontext_tearing_down +from .signals import before_render_template as before_render_template +from .signals import got_request_exception as got_request_exception +from .signals import message_flashed as message_flashed +from .signals import request_finished as request_finished +from .signals import request_started as request_started +from .signals import request_tearing_down as request_tearing_down +from .signals import template_rendered as template_rendered +from .templating import render_template as render_template +from .templating import render_template_string as render_template_string +from .templating import stream_template as stream_template +from .templating import stream_template_string as stream_template_string +from .wrappers import Request as Request +from .wrappers import Response as Response + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Flask 3.1. Use feature detection or" + " 'importlib.metadata.version(\"flask\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("flask") + + raise AttributeError(name) diff --git a/venv/lib/python3.12/site-packages/flask/__main__.py b/venv/lib/python3.12/site-packages/flask/__main__.py new file mode 100644 index 0000000..4e28416 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..965506ae50107b9fa562d20e0a79ef1e8ffa18ca GIT binary patch literal 2488 zcmZXW&uPR8v0WpcG*u+t&q97;i1WlSrGi9foG);poX{POrqf%9J z#?Cr9nv<;Bd8a@NlC$<1r$~#EbHD?1Kyn_qL`#wjz=L#9@)>)`Dbup#BJeOBmOKDF zLPsQ*fJf=5xXC#jS z&(c}RMm5QkcG{Vz^OC3R1!s{iN}dK@qDzuzfS2jA))p6JH15h+)FHhni3Wa*Y$)UEYA&Yy@YZ=V`?YxT=-3Y zY8$~WK<*Q}%Y1IR0vegCp4+yzfyzc(Fs_S^73iFO)nx(pPq#e3r?a|%z+OSSV2*Dag6W13+-i0OgPx*e>@tWV@L?~|kmby@IBVg!xq!K*-nMM) z7(Q-r&(V(^Jl>OL!I|Oc`Yy;L#muI=>hD$i#aU;;l{-SfvIxJ^wwFu{if2g zxBJOzVd2J48X!rC^6DYL19AYj+wLkM{IZ!aiB0Y+@>jW^I7sZE@2SU3icD-WQ@^Gk z!C3exj(nd9w&&2lw)Vztfsg}U}dz_d0qM3*!8 zP(U5SOq$2Fs^$1_T5PLXcbG6tLm2gbAgc>_WOf&7RTwOQM4R=O7#UrC zk5AcdO%2QcA1ci58{CD&24M;*EMMzK4by*l+!bcyi9@wNb2zXSpT+B(!)Zx|Dc5jV zn0qq?-+)L0OoygvubT~6AP*XX?HGX%H<;bH=C!>slGH78Cm(-wpH|5VIjVp4-@C z?p_1d-0*wYhArA?1eRdud~|`!p&^&v&~-QkLf7kl4>JVU1*QNpbQvbDV+40Vz9!Gq z!uR+8RHvV3=bvZC{>l#iSp1=Qm`D^qR*o{HIQML9{IEcBl_QeLwE}JWt3r*5tLDs3d$JDILZXdB+3*> zs0P-yi-S+2X$EB$We!C{nMYYbSwvYvSq2I7{o4VS%U94^MS+7&cn$lr`y7^zv8|zP z9R*YN3*lFgFM+(yUU59LYqJmeO=#j74ZZ_8Oe%^Jk%bqe{12Io$XrC~5m}1J2NAg$ zk2Nh7@5!M+;S;c5ipY&v PS0l1^lo?RwWSIW}O&!YL literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/__main__.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea3f68be3033d746c1b71bf023860cdcd7b37dd4 GIT binary patch literal 249 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 CPu!dU literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/blueprints.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/blueprints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4774db8a62f6573086a5bbec650fd41b42c3db50 GIT binary patch literal 4903 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 E0ue7FmH+?% literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/config.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..efdd4e1235a6761a65b3c05aa8ee8a5dd9e79938 GIT binary patch literal 16226 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/debughelpers.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/debughelpers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..069958058a955c0607db3dc1fcb51dc84de20780 GIT binary patch literal 9140 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/globals.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/globals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dfba437a309bff42c0abe3b51114cf1eea39283 GIT binary patch literal 1873 zcmb_c&2Jk;6yNoCys@1R$Elq(nI@$)Ewu%xw|)qP(nN(QA_<7C%4*{o+uQ8!EVHwY z?UTiYh!ZzB=2%oN{1aTbRLZ4Y6ogc9=m9BFdMX#*?5=B9>XDT^e)E3sYku#|{GQ8Y zCHSuV_D|#2lq5YDo57b11^MiIS(1K~b|fre*_13&0CCrqS zR@1UX;twYVfrkI=B2MCzIc88MX zj^4n};|qWzfp=poOD{ypE3&WXwoSRt4Qjg^u+Oeio0AUzLT6(4DXr_~CZnD13qcX6 zlAoBmy9YvE`^a%tdFQT4cXiVh)yP=&;2qrkoTLjfT#)!>FQ&rJ6MJ_el1gs7BJ>(LOJO}CasMVmL z?7qQU0;s}Ii>kc5Qbk)t_!ER_-LoJ?c#H;R$fArO!v@g`l+|9YAqWj4@J_E3@dXXI zKjia)pVsPa4blK_1<&54o{cpN_|%((jX`VtbWj8D_;C64n=Av$-XCuv zn}w|!oa_H2S}+Ga07BQcw>MFgsfys3u4nSM&_r#-VQ$1c08QBuvXBnv=BP#YMT7M= zHK5aCA{<6{O=4AhlOdT=7Of71Rz?Vo1}@S(@D)L7WX!}X<|`wvetH0n2L!v}_%a1{ zD+_*B(;6Q47|}E)ZlRwNgK0N?nFI6T$hLLnvV;Kh`-JWFh}W!|;!ZK~GWxmguQu;! zt7~^w@2zj#W#Y99I~Rw_gLVbI4NJ>J`Q4xZKeNxEtpwr+)hU`yMV~dxZL*vQUeL6W z%MC>qMEFUuObI;jfD;BD(?VSo%Zyk`u>35Y!79DdYdbEasd4g9cO95ov-WW`*KTct z@O`+vuC}Jv_jKN(cCAh9cFi<)Yfe|}Kdiq0LCrNdx#kFyCUI*)lWNWI;ix*@SD70Y z#hyuSu}hFqyfp49EGKbUmj9HNo=a25($e43JAcI!-`)Q9_Hm+eoLD|iEC%bPb`I|W zQi}DJgPj2~vj`psTZdNxnThq~{;dEx$qZ6lz5e9-+R>HuzVamZ?vb?qY~k|LMB#7_ n>=#9(uLqHe3!wj@{7B>|itMukq`W*t$^w~xDe7Vu;ne>Dk-jb7 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/helpers.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/helpers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1d3d999228b2de8b9b6f13bc46d378ebde5c0d3 GIT binary patch literal 24817 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/logging.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/logging.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84882be9ebeb3b33e5af1aa1003cc8d75d8432df GIT binary patch literal 3278 zcmZuz-EUk+6`#A`-p|;MjS@^U0z3AGWEZH?hs8>P#CD>ZG*Vm&i>lr0y|cU5zI*R7 zGaGv?r(KmuiBYA%L+iAv6rK<$LgJCXfEQluI>^>-D+RTcs05M~2dU(VbLQ^#I#=Vi@|M6=_6^QQ!#~VJp_?EB0xGg%^(dYI{A808hk9G?K+6@I;M-5xpIH*kvfD zjHD5}9V(^+gasB(_2hhtr5F;>pFLq+h3t+n2K`ts}>Uy$l#Bg&5CaV`v81FLbSa( zAl8Y*Io0@Jk6u8o7n-4+fSDUahWv$vh)?zU8zdXh-vd9UP1~Td&S=9ClIqPScbeSP zC8LaUhf^Ur(;Ku3Bys_RWmeR#a`bAI>a@FuIE7{ks#m0WlbxfMQ=`(Mx~^y-k;NTY`0^4b8|pc;;`x+mZ4f`E@YR5}=J%O^Z?3r(ss) zzIC-#3Ko>Iif)ffYBrh<2Lq_pFgdG8tL+(wbqGk6L9iTZLOg{ME0@`_EadZ5aDOr9 zdykPRd66l3PGJZzjw^`+QOkxn9-td#_Dz#Jwi|?)xe+gDewo-EUv?_32D7EeUt@B~;ftblMXxOCvhLXVo1iRjne+K(8^KzeuF-71jzHp&_0E zrb;*MfFuO3sJi5T0OC$yovf0DgX_ox%}?v!1Xjr{ZB^rw5~RF#H&E3K?RIQcTiCzw z{u&{d_hlb;^>VEp0Nx`~LInCqI|ysBp1e;ftJ=Gh?O-;v^5LaAt1MEpiWvd72X8&C zdzX-!w#t)k+-Rk)s~KI=CDXFHY{;Sxx(2yoW3JQ~9~ZRHV6t8)vuYLY6f9AT-DDP> ze9J$ES;d*FF*)V)%p%Lh?!|d7x)`IE5JDz_cu#wkXaFRuK`4%v;7)Zlhk^y3WON%n&%{K91Lrk92^BnB$01&=v5AIbv@94EkY++au4cudV}}FL_MU*dP&xJ!>Zob~33o)=_{jp- zo*b1b{JTe|i8u}O2{8LYJ5aHbFD${(x26$^Sfbjh=Ff^D(An?L_j-vpPc@%YBdZ$J zHBJ93YyW1>NqT5Ib!szp>b`ie{K4{8YN9j!I2ymx zey4qZ_`%4BBRjG5z06wXqv(Uw2dPJ~GhZY|?*HsjVie}LV<$FaCqBwQik*F&=ht1nL&%&e|ns*!vI1np&6n{9)&%!Tz+>Mt? z)fQ-Dr4mOd=7?4tU*~Q_wwrJUt|r~|661?2tW|>t2tY8$ymzBD%b5o}_MRB2xnEqL zDqXrVb?Mcs*Jj+f&~0HlISiUIis|XaIrZEP;Ac=*5>8}V9i?R4?b|0+KshG9+PqgK zVv`<{UF0vr0%DX9@Y@Y)n)Vs__U9!135kC~2EHU?Uy_l>!O)#o-g)J-(COU>2_&Bc zlG^ZI5U5>6ojRuV@17-t6Tcnb9vI&o7~hyEYz_Rdli4AeZ8EY+Ms`9&otf>>&}L|8 WWBA%u=(VT8fEIWfAJPVtQ~w7>q*3Ys literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/sessions.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/sessions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f55650212361ca26916be0fd4de67d85cd193cea GIT binary patch literal 16322 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/signals.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/signals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5104da03c7adf118caad11b1ab290929edaa279 GIT binary patch literal 1230 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/testing.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..098040762de53e144637454c1bd6eac05e53ce83 GIT binary patch literal 13688 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/typing.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..600bf2102c7a25b0661271046d0041379a5a7a4f GIT binary patch literal 4285 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 UN3i_FS07iNyxQ_9ftQ&7Kl8K}lK=n! literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/__pycache__/wrappers.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/__pycache__/wrappers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8106653b7411eb30e7619117fdfece91c0d1a097 GIT binary patch literal 6131 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/app.py b/venv/lib/python3.12/site-packages/flask/app.py new file mode 100644 index 0000000..7622b5e --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/app.py @@ -0,0 +1,1498 @@ +from __future__ import annotations + +import collections.abc as cabc +import os +import sys +import typing as t +import weakref +from datetime import timedelta +from inspect import iscoroutinefunction +from itertools import chain +from types import TracebackType +from urllib.parse import quote as _url_quote + +import click +from werkzeug.datastructures import Headers +from werkzeug.datastructures import ImmutableDict +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.exceptions import HTTPException +from werkzeug.exceptions import InternalServerError +from werkzeug.routing import BuildError +from werkzeug.routing import MapAdapter +from werkzeug.routing import RequestRedirect +from werkzeug.routing import RoutingException +from werkzeug.routing import Rule +from werkzeug.serving import is_running_from_reloader +from werkzeug.wrappers import Response as BaseResponse + +from . import cli +from . import typing as ft +from .ctx import AppContext +from .ctx import RequestContext +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import g +from .globals import request +from .globals import request_ctx +from .globals import session +from .helpers import get_debug_flag +from .helpers import get_flashed_messages +from .helpers import get_load_dotenv +from .helpers import send_from_directory +from .sansio.app import App +from .sansio.scaffold import _sentinel +from .sessions import SecureCookieSessionInterface +from .sessions import SessionInterface +from .signals import appcontext_tearing_down +from .signals import got_request_exception +from .signals import request_finished +from .signals import request_started +from .signals import request_tearing_down +from .templating import Environment +from .wrappers import Request +from .wrappers import Response + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + + from .testing import FlaskClient + from .testing import FlaskCliRunner + +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + + +def _make_timedelta(value: timedelta | int | None) -> timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class Flask(App): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + default_config = ImmutableDict( + { + "DEBUG": None, + "TESTING": False, + "PROPAGATE_EXCEPTIONS": None, + "SECRET_KEY": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "SERVER_NAME": None, + "APPLICATION_ROOT": "/", + "SESSION_COOKIE_NAME": "session", + "SESSION_COOKIE_DOMAIN": None, + "SESSION_COOKIE_PATH": None, + "SESSION_COOKIE_HTTPONLY": True, + "SESSION_COOKIE_SECURE": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "SEND_FILE_MAX_AGE_DEFAULT": None, + "TRAP_BAD_REQUEST_ERRORS": None, + "TRAP_HTTP_EXCEPTIONS": False, + "EXPLAIN_TEMPLATE_LOADING": False, + "PREFERRED_URL_SCHEME": "http", + "TEMPLATES_AUTO_RELOAD": None, + "MAX_COOKIE_SIZE": 4093, + } + ) + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class: type[Request] = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class: type[Response] = Response + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike[str] | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike[str] | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_url_path=static_url_path, + static_folder=static_folder, + static_host=static_host, + host_matching=host_matching, + subdomain_matching=subdomain_matching, + template_folder=template_folder, + instance_path=instance_path, + instance_relative_config=instance_relative_config, + root_path=root_path, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = cli.AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert ( + bool(static_host) == host_matching + ), "Invalid static_host/host_matching combination" + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for + reading. + + For example, if the file ``schema.sql`` is next to the file + ``app.py`` where the ``Flask`` app is defined, it can be opened + with: + + .. code-block:: python + + with app.open_resource("schema.sql") as f: + conn.executescript(f.read()) + + :param resource: Path to the resource relative to + :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is + supported, valid values are "r" (or "rt") and "rb". + + Note this is a duplicate of the same method in the Flask + class. + + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + return open(os.path.join(self.root_path, resource), mode) + + def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + def create_jinja_environment(self) -> Environment: + """Create the Jinja environment based on :attr:`jinja_options` + and the various Jinja-related methods of the app. Changing + :attr:`jinja_options` after this will have no effect. Also adds + Flask-related globals and filters to the environment. + + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + + if "autoescape" not in options: + options["autoescape"] = self.select_jinja_autoescape + + if "auto_reload" not in options: + auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] + + if auto_reload is None: + auto_reload = self.debug + + options["auto_reload"] = auto_reload + + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=self.url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g, + ) + rv.policies["json.dumps_function"] = self.json.dumps + return rv + + def create_url_adapter(self, request: Request | None) -> MapAdapter | None: + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set + up so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + """ + if request is not None: + # If subdomain matching is disabled (the default), use the + # default subdomain in all cases. This should be the default + # in Werkzeug but it currently does not have that feature. + if not self.subdomain_matching: + subdomain = self.url_map.default_subdomain or None + else: + subdomain = None + + return self.url_map.bind_to_environ( + request.environ, + server_name=self.config["SERVER_NAME"], + subdomain=subdomain, + ) + # We need at the very least the server name to be set for this + # to work. + if self.config["SERVER_NAME"] is not None: + return self.url_map.bind( + self.config["SERVER_NAME"], + script_name=self.config["APPLICATION_ROOT"], + url_scheme=self.config["PREFERRED_URL_SCHEME"], + ) + + return None + + def raise_routing_exception(self, request: Request) -> t.NoReturn: + """Intercept routing exceptions and possibly do something else. + + In debug mode, intercept a routing redirect and replace it with + an error if the body will be discarded. + + With modern Werkzeug this shouldn't occur, since it now uses a + 308 status which tells the browser to resend the method and + body. + + .. versionchanged:: 2.1 + Don't intercept 307 and 308 redirects. + + :meta private: + :internal: + """ + if ( + not self.debug + or not isinstance(request.routing_exception, RequestRedirect) + or request.routing_exception.code in {307, 308} + or request.method in {"GET", "HEAD", "OPTIONS"} + ): + raise request.routing_exception # type: ignore[misc] + + from .debughelpers import FormDataRoutingRedirect + + raise FormDataRoutingRedirect(request) + + def update_template_context(self, context: dict[str, t.Any]) -> None: + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + names: t.Iterable[str | None] = (None,) + + # A template may be rendered outside a request context. + if request: + names = chain(names, reversed(request.blueprints)) + + # The values passed to render_template take precedence. Keep a + # copy to re-apply after all context functions. + orig_ctx = context.copy() + + for name in names: + if name in self.template_context_processors: + for func in self.template_context_processors[name]: + context.update(self.ensure_sync(func)()) + + context.update(orig_ctx) + + def make_shell_context(self) -> dict[str, t.Any]: + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {"app": self, "g": g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + def run( + self, + host: str | None = None, + port: int | None = None, + debug: bool | None = None, + load_dotenv: bool = True, + **options: t.Any, + ) -> None: + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :doc:`/deploying/index` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable + if present. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if present. + :param debug: if given, enable or disable debug mode. See + :attr:`debug`. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param options: the options to be forwarded to the underlying Werkzeug + server. See :func:`werkzeug.serving.run_simple` for more + information. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment + variables from :file:`.env` and :file:`.flaskenv` files. + + The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. + + Threaded mode is enabled by default. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` + variable. + """ + # Ignore this call so that it doesn't start another server if + # the 'flask run' command is used. + if os.environ.get("FLASK_RUN_FROM_CLI") == "true": + if not is_running_from_reloader(): + click.secho( + " * Ignoring a call to 'app.run()' that would block" + " the current 'flask' CLI command.\n" + " Only call 'app.run()' in an 'if __name__ ==" + ' "__main__"\' guard.', + fg="red", + ) + + return + + if get_load_dotenv(load_dotenv): + cli.load_dotenv() + + # if set, env var overrides existing value + if "FLASK_DEBUG" in os.environ: + self.debug = get_debug_flag() + + # debug passed to method overrides all other sources + if debug is not None: + self.debug = bool(debug) + + server_name = self.config.get("SERVER_NAME") + sn_host = sn_port = None + + if server_name: + sn_host, _, sn_port = server_name.partition(":") + + if not host: + if sn_host: + host = sn_host + else: + host = "127.0.0.1" + + if port or port == 0: + port = int(port) + elif sn_port: + port = int(sn_port) + else: + port = 5000 + + options.setdefault("use_reloader", self.debug) + options.setdefault("use_debugger", self.debug) + options.setdefault("threaded", True) + + cli.show_server_banner(self.debug, self.name) + + from werkzeug.serving import run_simple + + try: + run_simple(t.cast(str, host), port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient: + """Creates a test client for this application. For information + about unit testing head over to :doc:`/testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from .testing import FlaskClient as cls + return cls( # type: ignore + self, self.response_class, use_cookies=use_cookies, **kwargs + ) + + def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner: + """Create a CLI runner for testing CLI commands. + See :ref:`testing-cli`. + + Returns an instance of :attr:`test_cli_runner_class`, by default + :class:`~flask.testing.FlaskCliRunner`. The Flask app object is + passed as the first argument. + + .. versionadded:: 1.0 + """ + cls = self.test_cli_runner_class + + if cls is None: + from .testing import FlaskCliRunner as cls + + return cls(self, **kwargs) # type: ignore + + def handle_http_exception( + self, e: HTTPException + ) -> HTTPException | ft.ResponseReturnValue: + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionchanged:: 1.0.3 + ``RoutingException``, used internally for actions such as + slash redirects during routing, is not passed to error + handlers. + + .. versionchanged:: 1.0 + Exceptions are looked up by code *and* by MRO, so + ``HTTPException`` subclasses can be handled with a catch-all + handler for the base ``HTTPException``. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + # RoutingExceptions are used internally to trigger routing + # actions, such as slash redirects raising RequestRedirect. They + # are not raised or handled in user code. + if isinstance(e, RoutingException): + return e + + handler = self._find_error_handler(e, request.blueprints) + if handler is None: + return e + return self.ensure_sync(handler)(e) # type: ignore[no-any-return] + + def handle_user_exception( + self, e: Exception + ) -> HTTPException | ft.ResponseReturnValue: + """This method is called whenever an exception occurs that + should be handled. A special case is :class:`~werkzeug + .exceptions.HTTPException` which is forwarded to the + :meth:`handle_http_exception` method. This function will either + return a response value or reraise the exception with the same + traceback. + + .. versionchanged:: 1.0 + Key errors raised from request data like ``form`` show the + bad key in debug mode rather than a generic bad request + message. + + .. versionadded:: 0.7 + """ + if isinstance(e, BadRequestKeyError) and ( + self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] + ): + e.show_exception = True + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e, request.blueprints) + + if handler is None: + raise + + return self.ensure_sync(handler)(e) # type: ignore[no-any-return] + + def handle_exception(self, e: Exception) -> Response: + """Handle an exception that did not have an error handler + associated with it, or that was raised from an error handler. + This always causes a 500 ``InternalServerError``. + + Always sends the :data:`got_request_exception` signal. + + If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug + mode, the error will be re-raised so that the debugger can + display it. Otherwise, the original exception is logged, and + an :exc:`~werkzeug.exceptions.InternalServerError` is returned. + + If an error handler is registered for ``InternalServerError`` or + ``500``, it will be used. For consistency, the handler will + always receive the ``InternalServerError``. The original + unhandled exception is available as ``e.original_exception``. + + .. versionchanged:: 1.1.0 + Always passes the ``InternalServerError`` instance to the + handler, setting ``original_exception`` to the unhandled + error. + + .. versionchanged:: 1.1.0 + ``after_request`` functions and other finalization is done + even for the default 500 response when there is no handler. + + .. versionadded:: 0.3 + """ + exc_info = sys.exc_info() + got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e) + propagate = self.config["PROPAGATE_EXCEPTIONS"] + + if propagate is None: + propagate = self.testing or self.debug + + if propagate: + # Re-raise if called with an active exception, otherwise + # raise the passed in exception. + if exc_info[1] is e: + raise + + raise e + + self.log_exception(exc_info) + server_error: InternalServerError | ft.ResponseReturnValue + server_error = InternalServerError(original_exception=e) + handler = self._find_error_handler(server_error, request.blueprints) + + if handler is not None: + server_error = self.ensure_sync(handler)(server_error) + + return self.finalize_request(server_error, from_error_handler=True) + + def log_exception( + self, + exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]), + ) -> None: + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error( + f"Exception on {request.path} [{request.method}]", exc_info=exc_info + ) + + def dispatch_request(self) -> ft.ResponseReturnValue: + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = request_ctx.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule: Rule = req.url_rule # type: ignore[assignment] + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if ( + getattr(rule, "provide_automatic_options", False) + and req.method == "OPTIONS" + ): + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment] + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + + def full_dispatch_request(self) -> Response: + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self._got_first_request = True + + try: + request_started.send(self, _async_wrapper=self.ensure_sync) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request( + self, + rv: ft.ResponseReturnValue | HTTPException, + from_error_handler: bool = False, + ) -> Response: + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send( + self, _async_wrapper=self.ensure_sync, response=response + ) + except Exception: + if not from_error_handler: + raise + self.logger.exception( + "Request finalizing failed with an error while handling an error" + ) + return response + + def make_default_options_response(self) -> Response: + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = request_ctx.url_adapter + methods = adapter.allowed_methods() # type: ignore[union-attr] + rv = self.response_class() + rv.allow.update(methods) + return rv + + def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Ensure that the function is synchronous for WSGI workers. + Plain ``def`` functions are returned as-is. ``async def`` + functions are wrapped to run and wait for the response. + + Override this method to change how the app runs async views. + + .. versionadded:: 2.0 + """ + if iscoroutinefunction(func): + return self.async_to_sync(func) + + return func + + def async_to_sync( + self, func: t.Callable[..., t.Coroutine[t.Any, t.Any, t.Any]] + ) -> t.Callable[..., t.Any]: + """Return a sync function that will run the coroutine function. + + .. code-block:: python + + result = app.async_to_sync(func)(*args, **kwargs) + + Override this method to change how the app converts async code + to be synchronously callable. + + .. versionadded:: 2.0 + """ + try: + from asgiref.sync import async_to_sync as asgiref_async_to_sync + except ImportError: + raise RuntimeError( + "Install Flask with the 'async' extra in order to use async views." + ) from None + + return asgiref_async_to_sync(func) + + def url_for( + self, + /, + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, + ) -> str: + """Generate a URL to the given endpoint with the given values. + + This is called by :func:`flask.url_for`, and can be called + directly as well. + + An *endpoint* is the name of a URL rule, usually added with + :meth:`@app.route() `, and usually the same name as the + view function. A route defined in a :class:`~flask.Blueprint` + will prepend the blueprint's name separated by a ``.`` to the + endpoint. + + In some cases, such as email messages, you want URLs to include + the scheme and domain, like ``https://example.com/hello``. When + not in an active request, URLs will be external by default, but + this requires setting :data:`SERVER_NAME` so Flask knows what + domain to use. :data:`APPLICATION_ROOT` and + :data:`PREFERRED_URL_SCHEME` should also be configured as + needed. This config is only used when not in an active request. + + Functions can be decorated with :meth:`url_defaults` to modify + keyword arguments before the URL is built. + + If building fails for some reason, such as an unknown endpoint + or incorrect values, the app's :meth:`handle_url_build_error` + method is called. If that returns a string, that is returned, + otherwise a :exc:`~werkzeug.routing.BuildError` is raised. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it + is external. + :param _external: If given, prefer the URL to be internal + (False) or require it to be external (True). External URLs + include the scheme and domain. When not in an active + request, URLs are external by default. + :param values: Values to use for the variable parts of the URL + rule. Unknown keys are appended as query string arguments, + like ``?a=b&c=d``. + + .. versionadded:: 2.2 + Moved from ``flask.url_for``, which calls this method. + """ + req_ctx = _cv_request.get(None) + + if req_ctx is not None: + url_adapter = req_ctx.url_adapter + blueprint_name = req_ctx.request.blueprint + + # If the endpoint starts with "." and the request matches a + # blueprint, the endpoint is relative to the blueprint. + if endpoint[:1] == ".": + if blueprint_name is not None: + endpoint = f"{blueprint_name}{endpoint}" + else: + endpoint = endpoint[1:] + + # When in a request, generate a URL without scheme and + # domain by default, unless a scheme is given. + if _external is None: + _external = _scheme is not None + else: + app_ctx = _cv_app.get(None) + + # If called by helpers.url_for, an app context is active, + # use its url_adapter. Otherwise, app.url_for was called + # directly, build an adapter. + if app_ctx is not None: + url_adapter = app_ctx.url_adapter + else: + url_adapter = self.create_url_adapter(None) + + if url_adapter is None: + raise RuntimeError( + "Unable to build URLs outside an active request" + " without 'SERVER_NAME' configured. Also configure" + " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" + " needed." + ) + + # When outside a request, generate a URL with scheme and + # domain by default. + if _external is None: + _external = True + + # It is an error to set _scheme when _external=False, in order + # to avoid accidental insecure URLs. + if _scheme is not None and not _external: + raise ValueError("When specifying '_scheme', '_external' must be True.") + + self.inject_url_defaults(endpoint, values) + + try: + rv = url_adapter.build( # type: ignore[union-attr] + endpoint, + values, + method=_method, + url_scheme=_scheme, + force_external=_external, + ) + except BuildError as error: + values.update( + _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external + ) + return self.handle_url_build_error(error, endpoint, values) + + if _anchor is not None: + _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@") + rv = f"{rv}#{_anchor}" + + return rv + + def make_response(self, rv: ft.ResponseReturnValue) -> Response: + """Convert the return value from a view function to an instance of + :attr:`response_class`. + + :param rv: the return value from the view function. The view function + must return a response. Returning ``None``, or the view ending + without returning, is not allowed. The following types are allowed + for ``view_rv``: + + ``str`` + A response object is created with the string encoded to UTF-8 + as the body. + + ``bytes`` + A response object is created with the bytes as the body. + + ``dict`` + A dictionary that will be jsonify'd before being returned. + + ``list`` + A list that will be jsonify'd before being returned. + + ``generator`` or ``iterator`` + A generator that returns ``str`` or ``bytes`` to be + streamed as the response. + + ``tuple`` + Either ``(body, status, headers)``, ``(body, status)``, or + ``(body, headers)``, where ``body`` is any of the other types + allowed here, ``status`` is a string or an integer, and + ``headers`` is a dictionary or a list of ``(key, value)`` + tuples. If ``body`` is a :attr:`response_class` instance, + ``status`` overwrites the exiting value and ``headers`` are + extended. + + :attr:`response_class` + The object is returned unchanged. + + other :class:`~werkzeug.wrappers.Response` class + The object is coerced to :attr:`response_class`. + + :func:`callable` + The function is called as a WSGI application. The result is + used to create a response object. + + .. versionchanged:: 2.2 + A generator will be converted to a streaming response. + A list will be converted to a JSON response. + + .. versionchanged:: 1.1 + A dict will be converted to a JSON response. + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + + status = headers = None + + # unpack tuple returns + if isinstance(rv, tuple): + len_rv = len(rv) + + # a 3-tuple is unpacked directly + if len_rv == 3: + rv, status, headers = rv # type: ignore[misc] + # decide if a 2-tuple has status or headers + elif len_rv == 2: + if isinstance(rv[1], (Headers, dict, tuple, list)): + rv, headers = rv + else: + rv, status = rv # type: ignore[assignment,misc] + # other sized tuples are not allowed + else: + raise TypeError( + "The view function did not return a valid response tuple." + " The tuple must have the form (body, status, headers)," + " (body, status), or (body, headers)." + ) + + # the body must not be None + if rv is None: + raise TypeError( + f"The view function for {request.endpoint!r} did not" + " return a valid response. The function either returned" + " None or ended without a return statement." + ) + + # make sure the body is an instance of the response class + if not isinstance(rv, self.response_class): + if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator): + # let the response class set the status and headers instead of + # waiting to do it manually, so that the class can handle any + # special logic + rv = self.response_class( + rv, + status=status, + headers=headers, # type: ignore[arg-type] + ) + status = headers = None + elif isinstance(rv, (dict, list)): + rv = self.json.response(rv) + elif isinstance(rv, BaseResponse) or callable(rv): + # evaluate a WSGI callable, or coerce a different response + # class to the correct type + try: + rv = self.response_class.force_type( + rv, # type: ignore[arg-type] + request.environ, + ) + except TypeError as e: + raise TypeError( + f"{e}\nThe view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it" + f" was a {type(rv).__name__}." + ).with_traceback(sys.exc_info()[2]) from None + else: + raise TypeError( + "The view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it was a" + f" {type(rv).__name__}." + ) + + rv = t.cast(Response, rv) + # prefer the status if it was provided + if status is not None: + if isinstance(status, (str, bytes, bytearray)): + rv.status = status + else: + rv.status_code = status + + # extend existing headers with provided headers + if headers: + rv.headers.update(headers) # type: ignore[arg-type] + + return rv + + def preprocess_request(self) -> ft.ResponseReturnValue | None: + """Called before the request is dispatched. Calls + :attr:`url_value_preprocessors` registered with the app and the + current blueprint (if any). Then calls :attr:`before_request_funcs` + registered with the app and the blueprint. + + If any :meth:`before_request` handler returns a non-None value, the + value is handled as if it was the return value from the view, and + further request handling is stopped. + """ + names = (None, *reversed(request.blueprints)) + + for name in names: + if name in self.url_value_preprocessors: + for url_func in self.url_value_preprocessors[name]: + url_func(request.endpoint, request.view_args) + + for name in names: + if name in self.before_request_funcs: + for before_func in self.before_request_funcs[name]: + rv = self.ensure_sync(before_func)() + + if rv is not None: + return rv # type: ignore[no-any-return] + + return None + + def process_response(self, response: Response) -> Response: + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = request_ctx._get_current_object() # type: ignore[attr-defined] + + for func in ctx._after_request_functions: + response = self.ensure_sync(func)(response) + + for name in chain(request.blueprints, (None,)): + if name in self.after_request_funcs: + for func in reversed(self.after_request_funcs[name]): + response = self.ensure_sync(func)(response) + + if not self.session_interface.is_null_session(ctx.session): + self.session_interface.save_session(self, ctx.session, response) + + return response + + def do_teardown_request( + self, + exc: BaseException | None = _sentinel, # type: ignore[assignment] + ) -> None: + """Called after the request is dispatched and the response is + returned, right before the request context is popped. + + This calls all functions decorated with + :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` + if a blueprint handled the request. Finally, the + :data:`request_tearing_down` signal is sent. + + This is called by + :meth:`RequestContext.pop() `, + which may be delayed during testing to maintain access to + resources. + + :param exc: An unhandled exception raised while dispatching the + request. Detected from the current exception information if + not passed. Passed to each teardown function. + + .. versionchanged:: 0.9 + Added the ``exc`` argument. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for name in chain(request.blueprints, (None,)): + if name in self.teardown_request_funcs: + for func in reversed(self.teardown_request_funcs[name]): + self.ensure_sync(func)(exc) + + request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def do_teardown_appcontext( + self, + exc: BaseException | None = _sentinel, # type: ignore[assignment] + ) -> None: + """Called right before the application context is popped. + + When handling a request, the application context is popped + after the request context. See :meth:`do_teardown_request`. + + This calls all functions decorated with + :meth:`teardown_appcontext`. Then the + :data:`appcontext_tearing_down` signal is sent. + + This is called by + :meth:`AppContext.pop() `. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for func in reversed(self.teardown_appcontext_funcs): + self.ensure_sync(func)(exc) + + appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def app_context(self) -> AppContext: + """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` + block to push the context, which will make :data:`current_app` + point at this application. + + An application context is automatically pushed by + :meth:`RequestContext.push() ` + when handling a request, and when running a CLI command. Use + this to manually create a context outside of these situations. + + :: + + with app.app_context(): + init_db() + + See :doc:`/appcontext`. + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ: WSGIEnvironment) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` representing a + WSGI environment. Use a ``with`` block to push the context, + which will make :data:`request` point at this request. + + See :doc:`/reqcontext`. + + Typically you should not call this from your own code. A request + context is automatically pushed by the :meth:`wsgi_app` when + handling a request. Use :meth:`test_request_context` to create + an environment and context instead of this method. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` for a WSGI + environment created from the given values. This is mostly useful + during testing, where you may want to run a function that uses + request data without dispatching a full request. + + See :doc:`/reqcontext`. + + Use a ``with`` block to push the context, which will make + :data:`request` point at the request for the created + environment. :: + + with app.test_request_context(...): + generate_report() + + When using the shell, it may be easier to push and pop the + context manually to avoid indentation. :: + + ctx = app.test_request_context(...) + ctx.push() + ... + ctx.pop() + + Takes the same arguments as Werkzeug's + :class:`~werkzeug.test.EnvironBuilder`, with some defaults from + the application. See the linked Werkzeug docs for most of the + available arguments. Flask-specific behavior is listed here. + + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to + :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param data: The request body, either as a string or a dict of + form keys and values. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + from .testing import EnvironBuilder + + builder = EnvironBuilder(self, *args, **kwargs) + + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + """The actual WSGI application. This is not implemented in + :meth:`__call__` so that middlewares can be applied without + losing a reference to the app object. Instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + Teardown events for the request and app contexts are called + even if an unhandled error occurs. Other events may not be + called depending on when an error occurs during dispatch. + See :ref:`callbacks-and-errors`. + + :param environ: A WSGI environment. + :param start_response: A callable accepting a status code, + a list of headers, and an optional exception context to + start the response. + """ + ctx = self.request_context(environ) + error: BaseException | None = None + try: + try: + ctx.push() + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: # noqa: B001 + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if "werkzeug.debug.preserve_context" in environ: + environ["werkzeug.debug.preserve_context"](_cv_app.get()) + environ["werkzeug.debug.preserve_context"](_cv_request.get()) + + if error is not None and self.should_ignore_error(error): + error = None + + ctx.pop(error) + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + """The WSGI server calls the Flask application object as the + WSGI application. This calls :meth:`wsgi_app`, which can be + wrapped to apply middleware. + """ + return self.wsgi_app(environ, start_response) diff --git a/venv/lib/python3.12/site-packages/flask/blueprints.py b/venv/lib/python3.12/site-packages/flask/blueprints.py new file mode 100644 index 0000000..aa9eacf --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/blueprints.py @@ -0,0 +1,129 @@ +from __future__ import annotations + +import os +import typing as t +from datetime import timedelta + +from .cli import AppGroup +from .globals import current_app +from .helpers import send_from_directory +from .sansio.blueprints import Blueprint as SansioBlueprint +from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa +from .sansio.scaffold import _sentinel + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +class Blueprint(SansioBlueprint): + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict[str, t.Any] | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore + ) -> None: + super().__init__( + name, + import_name, + static_folder, + static_url_path, + template_folder, + url_prefix, + subdomain, + url_defaults, + root_path, + cli_group, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for + reading. + + For example, if the file ``schema.sql`` is next to the file + ``app.py`` where the ``Flask`` app is defined, it can be opened + with: + + .. code-block:: python + + with app.open_resource("schema.sql") as f: + conn.executescript(f.read()) + + :param resource: Path to the resource relative to + :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is + supported, valid values are "r" (or "rt") and "rb". + + Note this is a duplicate of the same method in the Flask + class. + + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + return open(os.path.join(self.root_path, resource), mode) diff --git a/venv/lib/python3.12/site-packages/flask/cli.py b/venv/lib/python3.12/site-packages/flask/cli.py new file mode 100644 index 0000000..ecb292a --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/cli.py @@ -0,0 +1,1109 @@ +from __future__ import annotations + +import ast +import collections.abc as cabc +import importlib.metadata +import inspect +import os +import platform +import re +import sys +import traceback +import typing as t +from functools import update_wrapper +from operator import itemgetter +from types import ModuleType + +import click +from click.core import ParameterSource +from werkzeug import run_simple +from werkzeug.serving import is_running_from_reloader +from werkzeug.utils import import_string + +from .globals import current_app +from .helpers import get_debug_flag +from .helpers import get_load_dotenv + +if t.TYPE_CHECKING: + import ssl + + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + from .app import Flask + + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module: ModuleType) -> Flask: + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in ("app", "application"): + app = getattr(module, attr_name, None) + + if isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + elif len(matches) > 1: + raise NoAppException( + "Detected multiple Flask applications in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify the correct one." + ) + + # Search for app factory functions. + for attr_name in ("create_app", "make_app"): + app_factory = getattr(module, attr_name, None) + + if inspect.isfunction(app_factory): + try: + app = app_factory() + + if isinstance(app, Flask): + return app + except TypeError as e: + if not _called_with_wrong_args(app_factory): + raise + + raise NoAppException( + f"Detected factory '{attr_name}' in module '{module.__name__}'," + " but could not call it without arguments. Use" + f" '{module.__name__}:{attr_name}(args)'" + " to specify arguments." + ) from e + + raise NoAppException( + "Failed to find Flask application or factory in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify one." + ) + + +def _called_with_wrong_args(f: t.Callable[..., Flask]) -> bool: + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the factory raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def find_app_by_string(module: ModuleType, app_name: str) -> Flask: + """Check if the given string is a variable name or a function. Call + a function to get the app instance, or return the variable directly. + """ + from . import Flask + + # Parse app_name as a single expression to determine if it's a valid + # attribute name or function call. + try: + expr = ast.parse(app_name.strip(), mode="eval").body + except SyntaxError: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) from None + + if isinstance(expr, ast.Name): + name = expr.id + args = [] + kwargs = {} + elif isinstance(expr, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expr.func, ast.Name): + raise NoAppException( + f"Function reference must be a simple name: {app_name!r}." + ) + + name = expr.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expr.args] + kwargs = { + kw.arg: ast.literal_eval(kw.value) + for kw in expr.keywords + if kw.arg is not None + } + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise NoAppException( + f"Failed to parse arguments as literal values: {app_name!r}." + ) from None + else: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) + + try: + attr = getattr(module, name) + except AttributeError as e: + raise NoAppException( + f"Failed to find attribute {name!r} in {module.__name__!r}." + ) from e + + # If the attribute is a function, call it with any args and kwargs + # to get the real application. + if inspect.isfunction(attr): + try: + app = attr(*args, **kwargs) + except TypeError as e: + if not _called_with_wrong_args(attr): + raise + + raise NoAppException( + f"The factory {app_name!r} in module" + f" {module.__name__!r} could not be called with the" + " specified arguments." + ) from e + else: + app = attr + + if isinstance(app, Flask): + return app + + raise NoAppException( + "A valid Flask application was not obtained from" + f" '{module.__name__}:{app_name}'." + ) + + +def prepare_import(path: str) -> str: + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + path = os.path.realpath(path) + + fname, ext = os.path.splitext(path) + if ext == ".py": + path = fname + + if os.path.basename(path) == "__init__": + path = os.path.dirname(path) + + module_name = [] + + # move up until outside package structure (no __init__.py) + while True: + path, name = os.path.split(path) + module_name.append(name) + + if not os.path.exists(os.path.join(path, "__init__.py")): + break + + if sys.path[0] != path: + sys.path.insert(0, path) + + return ".".join(module_name[::-1]) + + +@t.overload +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: t.Literal[True] = True +) -> Flask: ... + + +@t.overload +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: t.Literal[False] = ... +) -> Flask | None: ... + + +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: bool = True +) -> Flask | None: + try: + __import__(module_name) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[2].tb_next: # type: ignore[union-attr] + raise NoAppException( + f"While importing {module_name!r}, an ImportError was" + f" raised:\n\n{traceback.format_exc()}" + ) from None + elif raise_if_not_found: + raise NoAppException(f"Could not import {module_name!r}.") from None + else: + return None + + module = sys.modules[module_name] + + if app_name is None: + return find_best_app(module) + else: + return find_app_by_string(module, app_name) + + +def get_version(ctx: click.Context, param: click.Parameter, value: t.Any) -> None: + if not value or ctx.resilient_parsing: + return + + flask_version = importlib.metadata.version("flask") + werkzeug_version = importlib.metadata.version("werkzeug") + + click.echo( + f"Python {platform.python_version()}\n" + f"Flask {flask_version}\n" + f"Werkzeug {werkzeug_version}", + color=ctx.color, + ) + ctx.exit() + + +version_option = click.Option( + ["--version"], + help="Show the Flask version.", + expose_value=False, + callback=get_version, + is_flag=True, + is_eager=True, +) + + +class ScriptInfo: + """Helper object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + """ + + def __init__( + self, + app_import_path: str | None = None, + create_app: t.Callable[..., Flask] | None = None, + set_debug_flag: bool = True, + ) -> None: + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data: dict[t.Any, t.Any] = {} + self.set_debug_flag = set_debug_flag + self._loaded_app: Flask | None = None + + def load_app(self) -> Flask: + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + if self._loaded_app is not None: + return self._loaded_app + + if self.create_app is not None: + app: Flask | None = self.create_app() + else: + if self.app_import_path: + path, name = ( + re.split(r":(?![\\/])", self.app_import_path, maxsplit=1) + [None] + )[:2] + import_name = prepare_import(path) + app = locate_app(import_name, name) + else: + for path in ("wsgi.py", "app.py"): + import_name = prepare_import(path) + app = locate_app(import_name, None, raise_if_not_found=False) + + if app is not None: + break + + if app is None: + raise NoAppException( + "Could not locate a Flask application. Use the" + " 'flask --app' option, 'FLASK_APP' environment" + " variable, or a 'wsgi.py' or 'app.py' file in the" + " current directory." + ) + + if self.set_debug_flag: + # Update the app's debug flag through the descriptor so that + # other values repopulate as well. + app.debug = get_debug_flag() + + self._loaded_app = app + return app + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def with_appcontext(f: F) -> F: + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. + + Custom commands (and their options) registered under ``app.cli`` or + ``blueprint.cli`` will always have an app context available, this + decorator is not required in that case. + + .. versionchanged:: 2.2 + The app context is active for subcommands as well as the + decorated callback. The app context is always available to + ``app.cli`` command and parameter callbacks. + """ + + @click.pass_context + def decorator(ctx: click.Context, /, *args: t.Any, **kwargs: t.Any) -> t.Any: + if not current_app: + app = ctx.ensure_object(ScriptInfo).load_app() + ctx.with_resource(app.app_context()) + + return ctx.invoke(f, *args, **kwargs) + + return update_wrapper(decorator, f) # type: ignore[return-value] + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command( # type: ignore[override] + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], click.Command]: + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop("with_appcontext", True) + + def decorator(f: t.Callable[..., t.Any]) -> click.Command: + if wrap_for_ctx: + f = with_appcontext(f) + return super(AppGroup, self).command(*args, **kwargs)(f) # type: ignore[no-any-return] + + return decorator + + def group( # type: ignore[override] + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], click.Group]: + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault("cls", AppGroup) + return super().group(*args, **kwargs) # type: ignore[no-any-return] + + +def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None: + if value is None: + return None + + info = ctx.ensure_object(ScriptInfo) + info.app_import_path = value + return value + + +# This option is eager so the app will be available if --help is given. +# --help is also eager, so --app must be before it in the param list. +# no_args_is_help bypasses eager processing, so this option must be +# processed manually in that case to ensure FLASK_APP gets picked up. +_app_option = click.Option( + ["-A", "--app"], + metavar="IMPORT", + help=( + "The Flask application or factory function to load, in the form 'module:name'." + " Module can be a dotted import or file path. Name is not required if it is" + " 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to" + " pass arguments." + ), + is_eager=True, + expose_value=False, + callback=_set_app, +) + + +def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None: + # If the flag isn't provided, it will default to False. Don't use + # that, let debug be set by env in that case. + source = ctx.get_parameter_source(param.name) # type: ignore[arg-type] + + if source is not None and source in ( + ParameterSource.DEFAULT, + ParameterSource.DEFAULT_MAP, + ): + return None + + # Set with env var instead of ScriptInfo.load so that it can be + # accessed early during a factory function. + os.environ["FLASK_DEBUG"] = "1" if value else "0" + return value + + +_debug_option = click.Option( + ["--debug/--no-debug"], + help="Set debug mode.", + expose_value=False, + callback=_set_debug, +) + + +def _env_file_callback( + ctx: click.Context, param: click.Option, value: str | None +) -> str | None: + if value is None: + return None + + import importlib + + try: + importlib.import_module("dotenv") + except ImportError: + raise click.BadParameter( + "python-dotenv must be installed to load an env file.", + ctx=ctx, + param=param, + ) from None + + # Don't check FLASK_SKIP_DOTENV, that only disables automatically + # loading .env and .flaskenv files. + load_dotenv(value) + return value + + +# This option is eager so env vars are loaded as early as possible to be +# used by other options. +_env_file_option = click.Option( + ["-e", "--env-file"], + type=click.Path(exists=True, dir_okay=False), + help="Load environment variables from this file. python-dotenv must be installed.", + is_eager=True, + expose_value=False, + callback=_env_file_callback, +) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands will be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info and + returns the loaded app. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param set_debug_flag: Set the app's debug flag. + + .. versionchanged:: 2.2 + Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. + + .. versionchanged:: 2.2 + An app context is pushed when running ``app.cli`` commands, so + ``@with_appcontext`` is no longer required for those commands. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment variables + from :file:`.env` and :file:`.flaskenv` files. + """ + + def __init__( + self, + add_default_commands: bool = True, + create_app: t.Callable[..., Flask] | None = None, + add_version_option: bool = True, + load_dotenv: bool = True, + set_debug_flag: bool = True, + **extra: t.Any, + ) -> None: + params = list(extra.pop("params", None) or ()) + # Processing is done with option callbacks instead of a group + # callback. This allows users to make a custom group callback + # without losing the behavior. --env-file must come first so + # that it is eagerly evaluated before --app. + params.extend((_env_file_option, _app_option, _debug_option)) + + if add_version_option: + params.append(version_option) + + if "context_settings" not in extra: + extra["context_settings"] = {} + + extra["context_settings"].setdefault("auto_envvar_prefix", "FLASK") + + super().__init__(params=params, **extra) + + self.create_app = create_app + self.load_dotenv = load_dotenv + self.set_debug_flag = set_debug_flag + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + self.add_command(routes_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self) -> None: + if self._loaded_plugin_commands: + return + + if sys.version_info >= (3, 10): + from importlib import metadata + else: + # Use a backport on Python < 3.10. We technically have + # importlib.metadata on 3.8+, but the API changed in 3.10, + # so use the backport for consistency. + import importlib_metadata as metadata + + for ep in metadata.entry_points(group="flask.commands"): + self.add_command(ep.load(), ep.name) + + self._loaded_plugin_commands = True + + def get_command(self, ctx: click.Context, name: str) -> click.Command | None: + self._load_plugin_commands() + # Look up built-in and plugin commands, which should be + # available even if the app fails to load. + rv = super().get_command(ctx, name) + + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + + # Look up commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + app = info.load_app() + except NoAppException as e: + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + return None + + # Push an app context for the loaded app unless it is already + # active somehow. This makes the context available to parameter + # and command callbacks without needing @with_appcontext. + if not current_app or current_app._get_current_object() is not app: # type: ignore[attr-defined] + ctx.with_resource(app.app_context()) + + return app.cli.get_command(ctx, name) + + def list_commands(self, ctx: click.Context) -> list[str]: + self._load_plugin_commands() + # Start with the built-in and plugin commands. + rv = set(super().list_commands(ctx)) + info = ctx.ensure_object(ScriptInfo) + + # Add commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except NoAppException as e: + # When an app couldn't be loaded, show the error message + # without the traceback. + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + except Exception: + # When any other errors occurred during loading, show the + # full traceback. + click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") + + return sorted(rv) + + def make_context( + self, + info_name: str | None, + args: list[str], + parent: click.Context | None = None, + **extra: t.Any, + ) -> click.Context: + # Set a flag to tell app.run to become a no-op. If app.run was + # not in a __name__ == __main__ guard, it would start the server + # when importing, blocking whatever command is being called. + os.environ["FLASK_RUN_FROM_CLI"] = "true" + + # Attempt to load .env and .flask env files. The --env-file + # option can cause another file to be loaded. + if get_load_dotenv(self.load_dotenv): + load_dotenv() + + if "obj" not in extra and "obj" not in self.context_settings: + extra["obj"] = ScriptInfo( + create_app=self.create_app, set_debug_flag=self.set_debug_flag + ) + + return super().make_context(info_name, args, parent=parent, **extra) + + def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: + if not args and self.no_args_is_help: + # Attempt to load --env-file and --app early in case they + # were given as env vars. Otherwise no_args_is_help will not + # see commands from app.cli. + _env_file_option.handle_parse_result(ctx, {}, []) + _app_option.handle_parse_result(ctx, {}, []) + + return super().parse_args(ctx, args) + + +def _path_is_ancestor(path: str, other: str) -> bool: + """Take ``other`` and remove the length of ``path`` from it. Then join it + to ``path``. If it is the original value, ``path`` is an ancestor of + ``other``.""" + return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other + + +def load_dotenv(path: str | os.PathLike[str] | None = None) -> bool: + """Load "dotenv" files in order of precedence to set environment variables. + + If an env var is already set it is not overwritten, so earlier files in the + list are preferred over later files. + + This is a no-op if `python-dotenv`_ is not installed. + + .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme + + :param path: Load the file at this location instead of searching. + :return: ``True`` if a file was loaded. + + .. versionchanged:: 2.0 + The current directory is not changed to the location of the + loaded file. + + .. versionchanged:: 2.0 + When loading the env files, set the default encoding to UTF-8. + + .. versionchanged:: 1.1.0 + Returns ``False`` when python-dotenv is not installed, or when + the given path isn't a file. + + .. versionadded:: 1.0 + """ + try: + import dotenv + except ImportError: + if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): + click.secho( + " * Tip: There are .env or .flaskenv files present." + ' Do "pip install python-dotenv" to use them.', + fg="yellow", + err=True, + ) + + return False + + # Always return after attempting to load a given path, don't load + # the default files. + if path is not None: + if os.path.isfile(path): + return dotenv.load_dotenv(path, encoding="utf-8") + + return False + + loaded = False + + for name in (".env", ".flaskenv"): + path = dotenv.find_dotenv(name, usecwd=True) + + if not path: + continue + + dotenv.load_dotenv(path, encoding="utf-8") + loaded = True + + return loaded # True if at least one file was located and loaded. + + +def show_server_banner(debug: bool, app_import_path: str | None) -> None: + """Show extra startup messages the first time the server is run, + ignoring the reloader. + """ + if is_running_from_reloader(): + return + + if app_import_path is not None: + click.echo(f" * Serving Flask app '{app_import_path}'") + + if debug is not None: + click.echo(f" * Debug mode: {'on' if debug else 'off'}") + + +class CertParamType(click.ParamType): + """Click option type for the ``--cert`` option. Allows either an + existing file, the string ``'adhoc'``, or an import for a + :class:`~ssl.SSLContext` object. + """ + + name = "path" + + def __init__(self) -> None: + self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) + + def convert( + self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None + ) -> t.Any: + try: + import ssl + except ImportError: + raise click.BadParameter( + 'Using "--cert" requires Python to be compiled with SSL support.', + ctx, + param, + ) from None + + try: + return self.path_type(value, param, ctx) + except click.BadParameter: + value = click.STRING(value, param, ctx).lower() + + if value == "adhoc": + try: + import cryptography # noqa: F401 + except ImportError: + raise click.BadParameter( + "Using ad-hoc certificates requires the cryptography library.", + ctx, + param, + ) from None + + return value + + obj = import_string(value, silent=True) + + if isinstance(obj, ssl.SSLContext): + return obj + + raise + + +def _validate_key(ctx: click.Context, param: click.Parameter, value: t.Any) -> t.Any: + """The ``--key`` option must be specified when ``--cert`` is a file. + Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. + """ + cert = ctx.params.get("cert") + is_adhoc = cert == "adhoc" + + try: + import ssl + except ImportError: + is_context = False + else: + is_context = isinstance(cert, ssl.SSLContext) + + if value is not None: + if is_adhoc: + raise click.BadParameter( + 'When "--cert" is "adhoc", "--key" is not used.', ctx, param + ) + + if is_context: + raise click.BadParameter( + 'When "--cert" is an SSLContext object, "--key" is not used.', + ctx, + param, + ) + + if not cert: + raise click.BadParameter('"--cert" must also be specified.', ctx, param) + + ctx.params["cert"] = cert, value + + else: + if cert and not (is_adhoc or is_context): + raise click.BadParameter('Required when using "--cert".', ctx, param) + + return value + + +class SeparatedPathType(click.Path): + """Click option type that accepts a list of values separated by the + OS's path separator (``:``, ``;`` on Windows). Each value is + validated as a :class:`click.Path` type. + """ + + def convert( + self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None + ) -> t.Any: + items = self.split_envvar_value(value) + # can't call no-arg super() inside list comprehension until Python 3.12 + super_convert = super().convert + return [super_convert(item, param, ctx) for item in items] + + +@click.command("run", short_help="Run a development server.") +@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") +@click.option("--port", "-p", default=5000, help="The port to bind to.") +@click.option( + "--cert", + type=CertParamType(), + help="Specify a certificate file to use HTTPS.", + is_eager=True, +) +@click.option( + "--key", + type=click.Path(exists=True, dir_okay=False, resolve_path=True), + callback=_validate_key, + expose_value=False, + help="The key file to use when specifying a certificate.", +) +@click.option( + "--reload/--no-reload", + default=None, + help="Enable or disable the reloader. By default the reloader " + "is active if debug is enabled.", +) +@click.option( + "--debugger/--no-debugger", + default=None, + help="Enable or disable the debugger. By default the debugger " + "is active if debug is enabled.", +) +@click.option( + "--with-threads/--without-threads", + default=True, + help="Enable or disable multithreading.", +) +@click.option( + "--extra-files", + default=None, + type=SeparatedPathType(), + help=( + "Extra files that trigger a reload on change. Multiple paths" + f" are separated by {os.path.pathsep!r}." + ), +) +@click.option( + "--exclude-patterns", + default=None, + type=SeparatedPathType(), + help=( + "Files matching these fnmatch patterns will not trigger a reload" + " on change. Multiple patterns are separated by" + f" {os.path.pathsep!r}." + ), +) +@pass_script_info +def run_command( + info: ScriptInfo, + host: str, + port: int, + reload: bool, + debugger: bool, + with_threads: bool, + cert: ssl.SSLContext | tuple[str, str | None] | t.Literal["adhoc"] | None, + extra_files: list[str] | None, + exclude_patterns: list[str] | None, +) -> None: + """Run a local development server. + + This server is for development purposes only. It does not provide + the stability, security, or performance of production WSGI servers. + + The reloader and debugger are enabled by default with the '--debug' + option. + """ + try: + app: WSGIApplication = info.load_app() + except Exception as e: + if is_running_from_reloader(): + # When reloading, print out the error immediately, but raise + # it later so the debugger or server can handle it. + traceback.print_exc() + err = e + + def app( + environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + raise err from None + + else: + # When not reloading, raise the error immediately so the + # command fails. + raise e from None + + debug = get_debug_flag() + + if reload is None: + reload = debug + + if debugger is None: + debugger = debug + + show_server_banner(debug, info.app_import_path) + + run_simple( + host, + port, + app, + use_reloader=reload, + use_debugger=debugger, + threaded=with_threads, + ssl_context=cert, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + ) + + +run_command.params.insert(0, _debug_option) + + +@click.command("shell", short_help="Run a shell in the app context.") +@with_appcontext +def shell_command() -> None: + """Run an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to its configuration. + + This is useful for executing small snippets of management code + without having to manually configure the application. + """ + import code + + banner = ( + f"Python {sys.version} on {sys.platform}\n" + f"App: {current_app.import_name}\n" + f"Instance: {current_app.instance_path}" + ) + ctx: dict[str, t.Any] = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup) as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(current_app.make_shell_context()) + + # Site, customize, or startup script can set a hook to call when + # entering interactive mode. The default one sets up readline with + # tab and history completion. + interactive_hook = getattr(sys, "__interactivehook__", None) + + if interactive_hook is not None: + try: + import readline + from rlcompleter import Completer + except ImportError: + pass + else: + # rlcompleter uses __main__.__dict__ by default, which is + # flask.__main__. Use the shell context instead. + readline.set_completer(Completer(ctx).complete) + + interactive_hook() + + code.interact(banner=banner, local=ctx) + + +@click.command("routes", short_help="Show the routes for the app.") +@click.option( + "--sort", + "-s", + type=click.Choice(("endpoint", "methods", "domain", "rule", "match")), + default="endpoint", + help=( + "Method to sort routes by. 'match' is the order that Flask will match routes" + " when dispatching a request." + ), +) +@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") +@with_appcontext +def routes_command(sort: str, all_methods: bool) -> None: + """Show all registered routes with endpoints and methods.""" + rules = list(current_app.url_map.iter_rules()) + + if not rules: + click.echo("No routes were registered.") + return + + ignored_methods = set() if all_methods else {"HEAD", "OPTIONS"} + host_matching = current_app.url_map.host_matching + has_domain = any(rule.host if host_matching else rule.subdomain for rule in rules) + rows = [] + + for rule in rules: + row = [ + rule.endpoint, + ", ".join(sorted((rule.methods or set()) - ignored_methods)), + ] + + if has_domain: + row.append((rule.host if host_matching else rule.subdomain) or "") + + row.append(rule.rule) + rows.append(row) + + headers = ["Endpoint", "Methods"] + sorts = ["endpoint", "methods"] + + if has_domain: + headers.append("Host" if host_matching else "Subdomain") + sorts.append("domain") + + headers.append("Rule") + sorts.append("rule") + + try: + rows.sort(key=itemgetter(sorts.index(sort))) + except ValueError: + pass + + rows.insert(0, headers) + widths = [max(len(row[i]) for row in rows) for i in range(len(headers))] + rows.insert(1, ["-" * w for w in widths]) + template = " ".join(f"{{{i}:<{w}}}" for i, w in enumerate(widths)) + + for row in rows: + click.echo(template.format(*row)) + + +cli = FlaskGroup( + name="flask", + help="""\ +A general utility script for Flask applications. + +An application to load must be given with the '--app' option, +'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file +in the current directory. +""", +) + + +def main() -> None: + cli.main() + + +if __name__ == "__main__": + main() diff --git a/venv/lib/python3.12/site-packages/flask/config.py b/venv/lib/python3.12/site-packages/flask/config.py new file mode 100644 index 0000000..7e3ba17 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/config.py @@ -0,0 +1,370 @@ +from __future__ import annotations + +import errno +import json +import os +import types +import typing as t + +from werkzeug.utils import import_string + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .sansio.app import App + + +T = t.TypeVar("T") + + +class ConfigAttribute(t.Generic[T]): + """Makes an attribute forward to the config""" + + def __init__( + self, name: str, get_converter: t.Callable[[t.Any], T] | None = None + ) -> None: + self.__name__ = name + self.get_converter = get_converter + + @t.overload + def __get__(self, obj: None, owner: None) -> te.Self: ... + + @t.overload + def __get__(self, obj: App, owner: type[App]) -> T: ... + + def __get__(self, obj: App | None, owner: type[App] | None = None) -> T | te.Self: + if obj is None: + return self + + rv = obj.config[self.__name__] + + if self.get_converter is not None: + rv = self.get_converter(rv) + + return rv # type: ignore[no-any-return] + + def __set__(self, obj: App, value: t.Any) -> None: + obj.config[self.__name__] = value + + +class Config(dict): # type: ignore[type-arg] + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__( + self, + root_path: str | os.PathLike[str], + defaults: dict[str, t.Any] | None = None, + ) -> None: + super().__init__(defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name: str, silent: bool = False) -> bool: + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError( + f"The environment variable {variable_name!r} is not set" + " and as such configuration could not be loaded. Set" + " this variable and make it point to a configuration" + " file" + ) + return self.from_pyfile(rv, silent=silent) + + def from_prefixed_env( + self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads + ) -> bool: + """Load any environment variables that start with ``FLASK_``, + dropping the prefix from the env key for the config key. Values + are passed through a loading function to attempt to convert them + to more specific types than strings. + + Keys are loaded in :func:`sorted` order. + + The default loading function attempts to parse values as any + valid JSON type, including dicts and lists. + + Specific items in nested dicts can be set by separating the + keys with double underscores (``__``). If an intermediate key + doesn't exist, it will be initialized to an empty dict. + + :param prefix: Load env vars that start with this prefix, + separated with an underscore (``_``). + :param loads: Pass each string value to this function and use + the returned value as the config value. If any error is + raised it is ignored and the value remains a string. The + default is :func:`json.loads`. + + .. versionadded:: 2.1 + """ + prefix = f"{prefix}_" + len_prefix = len(prefix) + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + # Change to key.removeprefix(prefix) on Python >= 3.9. + key = key[len_prefix:] + + if "__" not in key: + # A non-nested key, set directly. + self[key] = value + continue + + # Traverse nested dictionaries with keys separated by "__". + current = self + *parts, tail = key.split("__") + + for part in parts: + # If an intermediate dict does not exist, create it. + if part not in current: + current[part] = {} + + current = current[part] + + current[tail] = value + + return True + + def from_pyfile( + self, filename: str | os.PathLike[str], silent: bool = False + ) -> bool: + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType("config") + d.__file__ = filename + try: + with open(filename, mode="rb") as config_file: + exec(compile(config_file.read(), filename, "exec"), d.__dict__) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): + return False + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + self.from_object(d) + return True + + def from_object(self, obj: object | str) -> None: + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + Nothing is done to the object before loading. If the object is a + class and has ``@property`` attributes, it needs to be + instantiated before being passed to this method. + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, str): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_file( + self, + filename: str | os.PathLike[str], + load: t.Callable[[t.IO[t.Any]], t.Mapping[str, t.Any]], + silent: bool = False, + text: bool = True, + ) -> bool: + """Update the values in the config from a file that is loaded + using the ``load`` parameter. The loaded data is passed to the + :meth:`from_mapping` method. + + .. code-block:: python + + import json + app.config.from_file("config.json", load=json.load) + + import tomllib + app.config.from_file("config.toml", load=tomllib.load, text=False) + + :param filename: The path to the data file. This can be an + absolute path or relative to the config root path. + :param load: A callable that takes a file handle and returns a + mapping of loaded data from the file. + :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` + implements a ``read`` method. + :param silent: Ignore the file if it doesn't exist. + :param text: Open the file in text or binary mode. + :return: ``True`` if the file was loaded successfully. + + .. versionchanged:: 2.3 + The ``text`` parameter was added. + + .. versionadded:: 2.0 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename, "r" if text else "rb") as f: + obj = load(f) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + + return self.from_mapping(obj) + + def from_mapping( + self, mapping: t.Mapping[str, t.Any] | None = None, **kwargs: t.Any + ) -> bool: + """Updates the config like :meth:`update` ignoring items with + non-upper keys. + + :return: Always returns ``True``. + + .. versionadded:: 0.11 + """ + mappings: dict[str, t.Any] = {} + if mapping is not None: + mappings.update(mapping) + mappings.update(kwargs) + for key, value in mappings.items(): + if key.isupper(): + self[key] = value + return True + + def get_namespace( + self, namespace: str, lowercase: bool = True, trim_namespace: bool = True + ) -> dict[str, t.Any]: + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in self.items(): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace) :] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self) -> str: + return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/venv/lib/python3.12/site-packages/flask/ctx.py b/venv/lib/python3.12/site-packages/flask/ctx.py new file mode 100644 index 0000000..9b164d3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/ctx.py @@ -0,0 +1,449 @@ +from __future__ import annotations + +import contextvars +import sys +import typing as t +from functools import update_wrapper +from types import TracebackType + +from werkzeug.exceptions import HTTPException + +from . import typing as ft +from .globals import _cv_app +from .globals import _cv_request +from .signals import appcontext_popped +from .signals import appcontext_pushed + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIEnvironment + + from .app import Flask + from .sessions import SessionMixin + from .wrappers import Request + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals: + """A plain object. Used as a namespace for storing data during an + application context. + + Creating an app context automatically creates this object, which is + made available as the :data:`g` proxy. + + .. describe:: 'key' in g + + Check whether an attribute is present. + + .. versionadded:: 0.10 + + .. describe:: iter(g) + + Return an iterator over the attribute names. + + .. versionadded:: 0.10 + """ + + # Define attr methods to let mypy know this is a namespace object + # that has arbitrary attributes. + + def __getattr__(self, name: str) -> t.Any: + try: + return self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + self.__dict__[name] = value + + def __delattr__(self, name: str) -> None: + try: + del self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def get(self, name: str, default: t.Any | None = None) -> t.Any: + """Get an attribute by name, or a default value. Like + :meth:`dict.get`. + + :param name: Name of attribute to get. + :param default: Value to return if the attribute is not present. + + .. versionadded:: 0.10 + """ + return self.__dict__.get(name, default) + + def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: + """Get and remove an attribute by name. Like :meth:`dict.pop`. + + :param name: Name of attribute to pop. + :param default: Value to return if the attribute is not present, + instead of raising a ``KeyError``. + + .. versionadded:: 0.11 + """ + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name: str, default: t.Any = None) -> t.Any: + """Get the value of an attribute if it is present, otherwise + set and return a default value. Like :meth:`dict.setdefault`. + + :param name: Name of attribute to get. + :param default: Value to set and return if the attribute is not + present. + + .. versionadded:: 0.11 + """ + return self.__dict__.setdefault(name, default) + + def __contains__(self, item: str) -> bool: + return item in self.__dict__ + + def __iter__(self) -> t.Iterator[str]: + return iter(self.__dict__) + + def __repr__(self) -> str: + ctx = _cv_app.get(None) + if ctx is not None: + return f"" + return object.__repr__(self) + + +def after_this_request( + f: ft.AfterRequestCallable[t.Any], +) -> ft.AfterRequestCallable[t.Any]: + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'after_this_request' can only be used when a request" + " context is active, such as in a view function." + ) + + ctx._after_request_functions.append(f) + return f + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def copy_current_request_context(f: F) -> F: + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. The current session is also + included in the copied request context. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request or + # flask.session like you would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'copy_current_request_context' can only be used when a" + " request context is active, such as in a view function." + ) + + ctx = ctx.copy() + + def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any: + with ctx: # type: ignore[union-attr] + return ctx.app.ensure_sync(f)(*args, **kwargs) # type: ignore[union-attr] + + return update_wrapper(wrapper, f) # type: ignore[return-value] + + +def has_request_context() -> bool: + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g`) for truthness:: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _cv_request.get(None) is not None + + +def has_app_context() -> bool: + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _cv_app.get(None) is not None + + +class AppContext: + """The app context contains application-specific information. An app + context is created and pushed at the beginning of each request if + one is not already active. An app context is also pushed when + running CLI commands. + """ + + def __init__(self, app: Flask) -> None: + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g: _AppCtxGlobals = app.app_ctx_globals_class() + self._cv_tokens: list[contextvars.Token[AppContext]] = [] + + def push(self) -> None: + """Binds the app context to the current context.""" + self._cv_tokens.append(_cv_app.set(self)) + appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync) + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the app context.""" + try: + if len(self._cv_tokens) == 1: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + ctx = _cv_app.get() + _cv_app.reset(self._cv_tokens.pop()) + + if ctx is not self: + raise AssertionError( + f"Popped wrong app context. ({ctx!r} instead of {self!r})" + ) + + appcontext_popped.send(self.app, _async_wrapper=self.app.ensure_sync) + + def __enter__(self) -> AppContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + +class RequestContext: + """The request context contains per-request information. The Flask + app creates and pushes it at the beginning of the request, then pops + it at the end of the request. It will create the URL adapter and + request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the + request. When using the interactive debugger, the context will be + restored so ``request`` is still accessible. Similarly, the test + client can preserve the context after the request ends. However, + teardown functions may already have closed some resources such as + database connections. + """ + + def __init__( + self, + app: Flask, + environ: WSGIEnvironment, + request: Request | None = None, + session: SessionMixin | None = None, + ) -> None: + self.app = app + if request is None: + request = app.request_class(environ) + request.json_module = app.json + self.request: Request = request + self.url_adapter = None + try: + self.url_adapter = app.create_url_adapter(self.request) + except HTTPException as e: + self.request.routing_exception = e + self.flashes: list[tuple[str, str]] | None = None + self.session: SessionMixin | None = session + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions: list[ft.AfterRequestCallable[t.Any]] = [] + + self._cv_tokens: list[ + tuple[contextvars.Token[RequestContext], AppContext | None] + ] = [] + + def copy(self) -> RequestContext: + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + + .. versionchanged:: 1.1 + The current session object is used instead of reloading the original + data. This prevents `flask.session` pointing to an out-of-date object. + """ + return self.__class__( + self.app, + environ=self.request.environ, + request=self.request, + session=self.session, + ) + + def match_request(self) -> None: + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + result = self.url_adapter.match(return_rule=True) # type: ignore + self.request.url_rule, self.request.view_args = result # type: ignore + except HTTPException as e: + self.request.routing_exception = e + + def push(self) -> None: + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _cv_app.get(None) + + if app_ctx is None or app_ctx.app is not self.app: + app_ctx = self.app.app_context() + app_ctx.push() + else: + app_ctx = None + + self._cv_tokens.append((_cv_request.set(self), app_ctx)) + + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + # Only open a new session if this is the first time the request was + # pushed, otherwise stream_with_context loses the session. + if self.session is None: + session_interface = self.app.session_interface + self.session = session_interface.open_session(self.app, self.request) + + if self.session is None: + self.session = session_interface.make_null_session(self.app) + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + clear_request = len(self._cv_tokens) == 1 + + try: + if clear_request: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + request_close = getattr(self.request, "close", None) + if request_close is not None: + request_close() + finally: + ctx = _cv_request.get() + token, app_ctx = self._cv_tokens.pop() + _cv_request.reset(token) + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + ctx.request.environ["werkzeug.request"] = None + + if app_ctx is not None: + app_ctx.pop(exc) + + if ctx is not self: + raise AssertionError( + f"Popped wrong request context. ({ctx!r} instead of {self!r})" + ) + + def __enter__(self) -> RequestContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + def __repr__(self) -> str: + return ( + f"<{type(self).__name__} {self.request.url!r}" + f" [{self.request.method}] of {self.app.name}>" + ) diff --git a/venv/lib/python3.12/site-packages/flask/debughelpers.py b/venv/lib/python3.12/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..2c8c4c4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/debughelpers.py @@ -0,0 +1,178 @@ +from __future__ import annotations + +import typing as t + +from jinja2.loaders import BaseLoader +from werkzeug.routing import RequestRedirect + +from .blueprints import Blueprint +from .globals import request_ctx +from .sansio.app import App + +if t.TYPE_CHECKING: + from .sansio.scaffold import Scaffold + from .wrappers import Request + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request: Request, key: str) -> None: + form_matches = request.form.getlist(key) + buf = [ + f"You tried to access the file {key!r} in the request.files" + " dictionary but it does not exist. The mimetype for the" + f" request is {request.mimetype!r} instead of" + " 'multipart/form-data' which means that no file contents" + " were transmitted. To fix this error you should provide" + ' enctype="multipart/form-data" in your form.' + ] + if form_matches: + names = ", ".join(repr(x) for x in form_matches) + buf.append( + "\n\nThe browser instead transmitted some file names. " + f"This was submitted: {names}" + ) + self.msg = "".join(buf) + + def __str__(self) -> str: + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised in debug mode if a routing redirect + would cause the browser to drop the method or body. This happens + when method is not GET, HEAD or OPTIONS and the status code is not + 307 or 308. + """ + + def __init__(self, request: Request) -> None: + exc = request.routing_exception + assert isinstance(exc, RequestRedirect) + buf = [ + f"A request was sent to '{request.url}', but routing issued" + f" a redirect to the canonical URL '{exc.new_url}'." + ] + + if f"{request.base_url}/" == exc.new_url.partition("?")[0]: + buf.append( + " The URL was defined with a trailing slash. Flask" + " will redirect to the URL with a trailing slash if it" + " was accessed without one." + ) + + buf.append( + " Send requests to the canonical URL, or use 307 or 308 for" + " routing redirects. Otherwise, browsers will drop form" + " data.\n\n" + "This exception is only raised in debug mode." + ) + super().__init__("".join(buf)) + + +def attach_enctype_error_multidict(request: Request) -> None: + """Patch ``request.files.__getitem__`` to raise a descriptive error + about ``enctype=multipart/form-data``. + + :param request: The request to patch. + :meta private: + """ + oldcls = request.files.__class__ + + class newcls(oldcls): # type: ignore[valid-type, misc] + def __getitem__(self, key: str) -> t.Any: + try: + return super().__getitem__(key) + except KeyError as e: + if key not in request.form: + raise + + raise DebugFilesKeyError(request, key).with_traceback( + e.__traceback__ + ) from None + + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]: + yield f"class: {type(loader).__module__}.{type(loader).__name__}" + for key, value in sorted(loader.__dict__.items()): + if key.startswith("_"): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, str) for x in value): + continue + yield f"{key}:" + for item in value: + yield f" - {item}" + continue + elif not isinstance(value, (str, int, float, bool)): + continue + yield f"{key}: {value!r}" + + +def explain_template_loading_attempts( + app: App, + template: str, + attempts: list[ + tuple[ + BaseLoader, + Scaffold, + tuple[str, str | None, t.Callable[[], bool] | None] | None, + ] + ], +) -> None: + """This should help developers understand what failed""" + info = [f"Locating template {template!r}:"] + total_found = 0 + blueprint = None + if request_ctx and request_ctx.request.blueprint is not None: + blueprint = request_ctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, App): + src_info = f"application {srcobj.import_name!r}" + elif isinstance(srcobj, Blueprint): + src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" + else: + src_info = repr(srcobj) + + info.append(f"{idx + 1:5}: trying loader of {src_info}") + + for line in _dump_loader_info(loader): + info.append(f" {line}") + + if triple is None: + detail = "no match" + else: + detail = f"found ({triple[1] or ''!r})" + total_found += 1 + info.append(f" -> {detail}") + + seems_fishy = False + if total_found == 0: + info.append("Error: the template could not be found.") + seems_fishy = True + elif total_found > 1: + info.append("Warning: multiple loaders returned a match for the template.") + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append( + " The template was looked up from an endpoint that belongs" + f" to the blueprint {blueprint!r}." + ) + info.append(" Maybe you did not place a template in the right folder?") + info.append(" See https://flask.palletsprojects.com/blueprints/#templates") + + app.logger.info("\n".join(info)) diff --git a/venv/lib/python3.12/site-packages/flask/globals.py b/venv/lib/python3.12/site-packages/flask/globals.py new file mode 100644 index 0000000..e2c410c --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/globals.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import typing as t +from contextvars import ContextVar + +from werkzeug.local import LocalProxy + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .ctx import _AppCtxGlobals + from .ctx import AppContext + from .ctx import RequestContext + from .sessions import SessionMixin + from .wrappers import Request + + +_no_app_msg = """\ +Working outside of application context. + +This typically means that you attempted to use functionality that needed +the current application. To solve this, set up an application context +with app.app_context(). See the documentation for more information.\ +""" +_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx") +app_ctx: AppContext = LocalProxy( # type: ignore[assignment] + _cv_app, unbound_message=_no_app_msg +) +current_app: Flask = LocalProxy( # type: ignore[assignment] + _cv_app, "app", unbound_message=_no_app_msg +) +g: _AppCtxGlobals = LocalProxy( # type: ignore[assignment] + _cv_app, "g", unbound_message=_no_app_msg +) + +_no_req_msg = """\ +Working outside of request context. + +This typically means that you attempted to use functionality that needed +an active HTTP request. Consult the documentation on testing for +information about how to avoid this problem.\ +""" +_cv_request: ContextVar[RequestContext] = ContextVar("flask.request_ctx") +request_ctx: RequestContext = LocalProxy( # type: ignore[assignment] + _cv_request, unbound_message=_no_req_msg +) +request: Request = LocalProxy( # type: ignore[assignment] + _cv_request, "request", unbound_message=_no_req_msg +) +session: SessionMixin = LocalProxy( # type: ignore[assignment] + _cv_request, "session", unbound_message=_no_req_msg +) diff --git a/venv/lib/python3.12/site-packages/flask/helpers.py b/venv/lib/python3.12/site-packages/flask/helpers.py new file mode 100644 index 0000000..359a842 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/helpers.py @@ -0,0 +1,621 @@ +from __future__ import annotations + +import importlib.util +import os +import sys +import typing as t +from datetime import datetime +from functools import lru_cache +from functools import update_wrapper + +import werkzeug.utils +from werkzeug.exceptions import abort as _wz_abort +from werkzeug.utils import redirect as _wz_redirect +from werkzeug.wrappers import Response as BaseResponse + +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .globals import request_ctx +from .globals import session +from .signals import message_flashed + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +def get_debug_flag() -> bool: + """Get whether debug mode should be enabled for the app, indicated by the + :envvar:`FLASK_DEBUG` environment variable. The default is ``False``. + """ + val = os.environ.get("FLASK_DEBUG") + return bool(val and val.lower() not in {"0", "false", "no"}) + + +def get_load_dotenv(default: bool = True) -> bool: + """Get whether the user has disabled loading default dotenv files by + setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load + the files. + + :param default: What to return if the env var isn't set. + """ + val = os.environ.get("FLASK_SKIP_DOTENV") + + if not val: + return default + + return val.lower() in ("0", "false", "no") + + +def stream_with_context( + generator_or_function: t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]], +) -> t.Iterator[t.AnyStr]: + """Request contexts disappear when the response is started on the server. + This is done for efficiency reasons and to make it less likely to encounter + memory leaks with badly written WSGI middlewares. The downside is that if + you are using streamed responses, the generator cannot access request bound + information any more. + + This function however can help you keep the context around for longer:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + @stream_with_context + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(generate()) + + Alternatively it can also be used around a specific generator:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) # type: ignore[arg-type] + except TypeError: + + def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: + gen = generator_or_function(*args, **kwargs) # type: ignore[operator] + return stream_with_context(gen) + + return update_wrapper(decorator, generator_or_function) # type: ignore[arg-type] + + def generator() -> t.Iterator[t.AnyStr | None]: + ctx = _cv_request.get(None) + if ctx is None: + raise RuntimeError( + "'stream_with_context' can only be used when a request" + " context is active, such as in a view function." + ) + with ctx: + # Dummy sentinel. Has to be inside the context block or we're + # not actually keeping the context around. + yield None + + # The try/finally is here so that if someone passes a WSGI level + # iterator in we're still running the cleanup logic. Generators + # don't need that because they are closed on their destruction + # automatically. + try: + yield from gen + finally: + if hasattr(gen, "close"): + gen.close() + + # The trick is to start the generator. Then the code execution runs until + # the first dummy None is yielded at which point the context was already + # pushed. This item is discarded. Then when the iteration continues the + # real generator is executed. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g # type: ignore[return-value] + + +def make_response(*args: t.Any) -> Response: + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) + + +def url_for( + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, +) -> str: + """Generate a URL to the given endpoint with the given values. + + This requires an active request or application context, and calls + :meth:`current_app.url_for() `. See that method + for full documentation. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it is + external. + :param _external: If given, prefer the URL to be internal (False) or + require it to be external (True). External URLs include the + scheme and domain. When not in an active request, URLs are + external by default. + :param values: Values to use for the variable parts of the URL rule. + Unknown keys are appended as query string arguments, like + ``?a=b&c=d``. + + .. versionchanged:: 2.2 + Calls ``current_app.url_for``, allowing an app to override the + behavior. + + .. versionchanged:: 0.10 + The ``_scheme`` parameter was added. + + .. versionchanged:: 0.9 + The ``_anchor`` and ``_method`` parameters were added. + + .. versionchanged:: 0.9 + Calls ``app.handle_url_build_error`` on build errors. + """ + return current_app.url_for( + endpoint, + _anchor=_anchor, + _method=_method, + _scheme=_scheme, + _external=_external, + **values, + ) + + +def redirect( + location: str, code: int = 302, Response: type[BaseResponse] | None = None +) -> BaseResponse: + """Create a redirect response object. + + If :data:`~flask.current_app` is available, it will use its + :meth:`~flask.Flask.redirect` method, otherwise it will use + :func:`werkzeug.utils.redirect`. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + :param Response: The response class to use. Not used when + ``current_app`` is active, which uses ``app.response_class``. + + .. versionadded:: 2.2 + Calls ``current_app.redirect`` if available instead of always + using Werkzeug's default ``redirect``. + """ + if current_app: + return current_app.redirect(location, code=code) + + return _wz_redirect(location, code=code, Response=Response) + + +def abort(code: int | BaseResponse, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + """Raise an :exc:`~werkzeug.exceptions.HTTPException` for the given + status code. + + If :data:`~flask.current_app` is available, it will call its + :attr:`~flask.Flask.aborter` object, otherwise it will use + :func:`werkzeug.exceptions.abort`. + + :param code: The status code for the exception, which must be + registered in ``app.aborter``. + :param args: Passed to the exception. + :param kwargs: Passed to the exception. + + .. versionadded:: 2.2 + Calls ``current_app.aborter`` if available instead of always + using Werkzeug's default ``abort``. + """ + if current_app: + current_app.aborter(code, *args, **kwargs) + + _wz_abort(code, *args, **kwargs) + + +def get_template_attribute(template_name: str, attribute: str) -> t.Any: + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, attribute) + + +def flash(message: str, category: str = "message") -> None: + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get("_flashes", []) + flashes.append((category, message)) + session["_flashes"] = flashes + app = current_app._get_current_object() # type: ignore + message_flashed.send( + app, + _async_wrapper=app.ensure_sync, + message=message, + category=category, + ) + + +def get_flashed_messages( + with_categories: bool = False, category_filter: t.Iterable[str] = () +) -> list[str] | list[tuple[str, str]]: + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :doc:`/patterns/flashing` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: filter of categories to limit return values. Only + categories in the list will be returned. + """ + flashes = request_ctx.flashes + if flashes is None: + flashes = session.pop("_flashes") if "_flashes" in session else [] + request_ctx.flashes = flashes + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]: + if kwargs.get("max_age") is None: + kwargs["max_age"] = current_app.get_send_file_max_age + + kwargs.update( + environ=request.environ, + use_x_sendfile=current_app.config["USE_X_SENDFILE"], + response_class=current_app.response_class, + _root_path=current_app.root_path, # type: ignore + ) + return kwargs + + +def send_file( + path_or_file: os.PathLike[t.AnyStr] | str | t.BinaryIO, + mimetype: str | None = None, + as_attachment: bool = False, + download_name: str | None = None, + conditional: bool = True, + etag: bool | str = True, + last_modified: datetime | int | float | None = None, + max_age: None | (int | t.Callable[[str | None], int | None]) = None, +) -> Response: + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve + user-requested paths from within a directory. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, configuring Flask with + ``USE_X_SENDFILE = True`` will tell the server to send the given + path, which is much more efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + + .. versionchanged:: 2.0 + ``download_name`` replaces the ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces the ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces the ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + Passing a file-like object that inherits from + :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather + than sending an empty file. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionchanged:: 1.1 + ``filename`` may be a :class:`~os.PathLike` object. + + .. versionchanged:: 1.1 + Passing a :class:`~io.BytesIO` object supports range requests. + + .. versionchanged:: 1.0.3 + Filenames are encoded with ASCII instead of Latin-1 for broader + compatibility with WSGI servers. + + .. versionchanged:: 1.0 + UTF-8 filenames as specified in :rfc:`2231` are supported. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file + objects. If you want to use automatic MIME and etag support, + pass a filename via ``filename_or_fp`` or + ``attachment_filename``. + + .. versionchanged:: 0.12 + ``attachment_filename`` is preferred over ``filename`` for MIME + detection. + + .. versionchanged:: 0.9 + ``cache_timeout`` defaults to + :meth:`Flask.get_send_file_max_age`. + + .. versionchanged:: 0.7 + MIME guessing and etag support for file-like objects was + removed because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. + + .. versionchanged:: 0.5 + The ``add_etags``, ``cache_timeout`` and ``conditional`` + parameters were added. The default behavior is to add etags. + + .. versionadded:: 0.2 + """ + return werkzeug.utils.send_file( # type: ignore[return-value] + **_prepare_send_file_kwargs( + path_or_file=path_or_file, + environ=request.environ, + mimetype=mimetype, + as_attachment=as_attachment, + download_name=download_name, + conditional=conditional, + etag=etag, + last_modified=last_modified, + max_age=max_age, + ) + ) + + +def send_from_directory( + directory: os.PathLike[str] | str, + path: os.PathLike[str] | str, + **kwargs: t.Any, +) -> Response: + """Send a file from within a directory using :func:`send_file`. + + .. code-block:: python + + @app.route("/uploads/") + def download_file(name): + return send_from_directory( + app.config['UPLOAD_FOLDER'], name, as_attachment=True + ) + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under, + relative to the current application's root path. + :param path: The path to the file to send, relative to + ``directory``. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionchanged:: 2.0 + ``path`` replaces the ``filename`` parameter. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionadded:: 0.5 + """ + return werkzeug.utils.send_from_directory( # type: ignore[return-value] + directory, path, **_prepare_send_file_kwargs(**kwargs) + ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + try: + spec = importlib.util.find_spec(import_name) + + if spec is None: + raise ValueError + except (ImportError, ValueError): + loader = None + else: + loader = spec.loader + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None: + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) # type: ignore[no-any-return] + + +@lru_cache(maxsize=None) +def _split_blueprint_path(name: str) -> list[str]: + out: list[str] = [name] + + if "." in name: + out.extend(_split_blueprint_path(name.rpartition(".")[0])) + + return out diff --git a/venv/lib/python3.12/site-packages/flask/json/__init__.py b/venv/lib/python3.12/site-packages/flask/json/__init__.py new file mode 100644 index 0000000..c0941d0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/json/__init__.py @@ -0,0 +1,170 @@ +from __future__ import annotations + +import json as _json +import typing as t + +from ..globals import current_app +from .provider import _default + +if t.TYPE_CHECKING: # pragma: no cover + from ..wrappers import Response + + +def dumps(obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dumps() ` + method, otherwise it will use :func:`json.dumps`. + + :param obj: The data to serialize. + :param kwargs: Arguments passed to the ``dumps`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dumps``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.dumps(obj, **kwargs) + + kwargs.setdefault("default", _default) + return _json.dumps(obj, **kwargs) + + +def dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dump() ` + method, otherwise it will use :func:`json.dump`. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: Arguments passed to the ``dump`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dump``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + Writing to a binary file, and the ``encoding`` argument, will be + removed in Flask 2.1. + """ + if current_app: + current_app.json.dump(obj, fp, **kwargs) + else: + kwargs.setdefault("default", _default) + _json.dump(obj, fp, **kwargs) + + +def loads(s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.loads() ` + method, otherwise it will use :func:`json.loads`. + + :param s: Text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``loads`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.loads``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The data must be a + string or UTF-8 bytes. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.loads(s, **kwargs) + + return _json.loads(s, **kwargs) + + +def load(fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.load() ` + method, otherwise it will use :func:`json.load`. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``load`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.load``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The file must be text + mode, or binary mode with UTF-8 bytes. + """ + if current_app: + return current_app.json.load(fp, **kwargs) + + return _json.load(fp, **kwargs) + + +def jsonify(*args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. A dict or list returned from a view will be converted to a + JSON response automatically without needing to call this. + + This requires an active request or application context, and calls + :meth:`app.json.response() `. + + In debug mode, the output is formatted with indentation to make it + easier to read. This may also be controlled by the provider. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + + .. versionchanged:: 2.2 + Calls ``current_app.json.response``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 0.11 + Added support for serializing top-level arrays. This was a + security risk in ancient browsers. See :ref:`security-json`. + + .. versionadded:: 0.2 + """ + return current_app.json.response(*args, **kwargs) # type: ignore[return-value] diff --git a/venv/lib/python3.12/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14eb133413da0b545af21b009676c298eaf768bd GIT binary patch literal 6701 zcmd5=&u<&Y72c&NX)Ri!?Zk~^*YPBliZYd#vK+esV>mJVBXNr=L8SDDih>++htf*R zU1oMEm4;CSMS#LRG`_`0AB@07f&Ll2^dcew1h6(>H0{BM0tJ*_eCqdRc9;4URd$uY z1h_l9GxKKV?VE4D_x*Kvc*wx-)xZ3!{`bR%@g+SZzl<)JYagTVso@xo=@|`k)-YknLclw;HH_#ZI9YkHfGvHZ`eY5*aL-a2^pP1|2{uUX zXNR2;XCLk(PTm>9J?|WFa=0IG4m$gBKiJL`4m~0x1+$yuz8^$9asxk{dPEbYm$jCZ z!jH8wK)LZY1u!#<$MwQ90ABCJ@m}{S*@Tn0c?+wYKwB17Ni?kAj zh3xt#UA|$|P1m?#-ZlSVPUF5XxV4RAMpp9nPl=C>2y@WC|82LB;aB?%V_Ha;d+v3? z93FATL-wQTcc<*3A%@?zIxErZQsp;wkB5u)I_FfF8#2DcU5{5iG0xnGExVq_TA@HW zRQ*d05zUt>aHYKv2EOgI8qM(g1$JIrQ}3EGSaKa9Z5sEz{sH+mzrGi1`DbSB{nl3uP+K%n5@{=bJWcim${q^OYEYYYc=rw zL)PSBC>(|!7?)KlYDyI>yV3LnHBpfh4`$nJNyrePRGa7ioN!7dHff(xBakO)0u^!u z45$G`BqUpgyQOFZOTyXF&SYxm68F3imezfUb*`;c#u*v}%dS7ixX&;i%^&uqgpX4z zw4kb(=SyxNcN}=a?hRe4Aq2uw#St~P!9Dx3zN1C2lgqx8wUEY<#MtSE%d|Z)8-aaqZZt-+L0TaR`rKK>as8}RX!r@_Y?W<3Lh z%n(AFMmuvOvv(M|*><6in_r8Q2or}bOL$v{dfoLz9GKq(cJ3NFp9(pj4mj&gfF`4b zv!E$_KmhF#@`(ZfY#N(Q&j&5fQAYzo&j&MCPraUQtz^HG2eChwa2h%BAw%eJQbbtE4To1Y=Ru?xmD{( z$2ziV9q(AjZ`bZjcC3ke-}&5{cxa8RS}%627jGBt{`?EezHbeGGIVq3)|uOxjs?v5 z+!~XIV5yc8Ej*-va~%&G0O$WEWKl}Tc0saCJ^}|^7AfiYHfWX?aA$WkOSODruu#1= zp#`YZ3>}cz`)YfG2t*=$LW-pgKdTfgp50zktaR^f*rGd9pB|rWw8Dr`lc!cR+uHIS zRQ+}=_1h;)g{`DC(*7M0nPK7WdwS1dkiMMY;9)ygp)G#?GvgqJ0w(-_C$&=Pl!^A7$zu1 zDO75x5jcP}DFDVV$q0jQ_J5L26Tk0Zo8HNxOt>Z7(+^^Vt=sC5;f{@?8{Hec z4WTAf2@fqs2A&675Km~BR1(w9xq>|b3(WvoJroD-kvkSe8$y7yE>2>7Lxs;cgR;r0 zP|P#~Lo(_kHAuBBF5@^GM`AD)_<~?E>`7yZ92G+?I+8TTLf|s;JfvtXmGGvlR_)^k z6jB%3n63}8V?oznXfoTdZmGtmu^4H95#s%IsR zhwzo9klF&=-9a+z*4y$W^!h#i;mf#uWPJ6OY3zStHFvC&JGPn|?c_%9I4ilc_aHc( zUCEwR%nqq3WuA}wBm1J?R<`8{yyy;SFzfb#8W$|pNL8rAK%)99pm&I;+{#P#HrzI*YE4D06BG(_3vOO^>6go&)8`y2PkNqJH5}cc@&h zw}AAbT$W&l+JWlK>ka^~@ol?i)E%7jf+}D{OO93o8(L!=p83UlSIU>(xpL{p*QVa? zTFVj$im$1L(AuBM#udF*2PXOakB0K4V&0Ff^MJmVCoaezpo&hq@O51N-DjHS1LKu1 zjpzSn9Qvp6@&n_ghke=Kz4_ZWA7oFi4V*B)w|3b)hU@w7nxktMj+vuhooD7bW%<83 C2uZ>K literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/json/__pycache__/provider.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/json/__pycache__/provider.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95c800b44fde9876b068b8060743fb91e2a65f06 GIT binary patch literal 9268 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 to an instance of the class. + + :param app: An application instance. This will be stored as a + :class:`weakref.proxy` on the :attr:`_app` attribute. + + .. versionadded:: 2.2 + """ + + def __init__(self, app: App) -> None: + self._app: App = weakref.proxy(app) + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + :param obj: The data to serialize. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: May be passed to the underlying JSON library. + """ + fp.write(self.dumps(obj, **kwargs)) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + :param s: Text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + return self.loads(fp.read(), **kwargs) + + def _prepare_response_obj( + self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] + ) -> t.Any: + if args and kwargs: + raise TypeError("app.json.response() takes either args or kwargs, not both") + + if not args and not kwargs: + return None + + if len(args) == 1: + return args[0] + + return args or kwargs + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. + + The :func:`~flask.json.jsonify` function calls this method for + the current application. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + return self._app.response_class(self.dumps(obj), mimetype="application/json") + + +def _default(o: t.Any) -> t.Any: + if isinstance(o, date): + return http_date(o) + + if isinstance(o, (decimal.Decimal, uuid.UUID)): + return str(o) + + if dataclasses and dataclasses.is_dataclass(o): + return dataclasses.asdict(o) + + if hasattr(o, "__html__"): + return str(o.__html__()) + + raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable") + + +class DefaultJSONProvider(JSONProvider): + """Provide JSON operations using Python's built-in :mod:`json` + library. Serializes the following additional data types: + + - :class:`datetime.datetime` and :class:`datetime.date` are + serialized to :rfc:`822` strings. This is the same as the HTTP + date format. + - :class:`uuid.UUID` is serialized to a string. + - :class:`dataclasses.dataclass` is passed to + :func:`dataclasses.asdict`. + - :class:`~markupsafe.Markup` (or any object with a ``__html__`` + method) will call the ``__html__`` method to get a string. + """ + + default: t.Callable[[t.Any], t.Any] = staticmethod(_default) # type: ignore[assignment] + """Apply this function to any object that :meth:`json.dumps` does + not know how to serialize. It should return a valid JSON type or + raise a ``TypeError``. + """ + + ensure_ascii = True + """Replace non-ASCII characters with escape sequences. This may be + more compatible with some clients, but can be disabled for better + performance and size. + """ + + sort_keys = True + """Sort the keys in any serialized dicts. This may be useful for + some caching situations, but can be disabled for better performance. + When enabled, keys must all be strings, they are not converted + before sorting. + """ + + compact: bool | None = None + """If ``True``, or ``None`` out of debug mode, the :meth:`response` + output will not add indentation, newlines, or spaces. If ``False``, + or ``None`` in debug mode, it will use a non-compact representation. + """ + + mimetype = "application/json" + """The mimetype set in :meth:`response`.""" + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON to a string. + + Keyword arguments are passed to :func:`json.dumps`. Sets some + parameter defaults from the :attr:`default`, + :attr:`ensure_ascii`, and :attr:`sort_keys` attributes. + + :param obj: The data to serialize. + :param kwargs: Passed to :func:`json.dumps`. + """ + kwargs.setdefault("default", self.default) + kwargs.setdefault("ensure_ascii", self.ensure_ascii) + kwargs.setdefault("sort_keys", self.sort_keys) + return json.dumps(obj, **kwargs) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON from a string or bytes. + + :param s: Text or UTF-8 bytes. + :param kwargs: Passed to :func:`json.loads`. + """ + return json.loads(s, **kwargs) + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with it. The response mimetype + will be "application/json" and can be changed with + :attr:`mimetype`. + + If :attr:`compact` is ``False`` or debug mode is enabled, the + output will be formatted to be easier to read. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + dump_args: dict[str, t.Any] = {} + + if (self.compact is None and self._app.debug) or self.compact is False: + dump_args.setdefault("indent", 2) + else: + dump_args.setdefault("separators", (",", ":")) + + return self._app.response_class( + f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype + ) diff --git a/venv/lib/python3.12/site-packages/flask/json/tag.py b/venv/lib/python3.12/site-packages/flask/json/tag.py new file mode 100644 index 0000000..8dc3629 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/json/tag.py @@ -0,0 +1,327 @@ +""" +Tagged JSON +~~~~~~~~~~~ + +A compact representation for lossless serialization of non-standard JSON +types. :class:`~flask.sessions.SecureCookieSessionInterface` uses this +to serialize the session data, but it may be useful in other places. It +can be extended to support other types. + +.. autoclass:: TaggedJSONSerializer + :members: + +.. autoclass:: JSONTag + :members: + +Let's see an example that adds support for +:class:`~collections.OrderedDict`. Dicts don't have an order in JSON, so +to handle this we will dump the items as a list of ``[key, value]`` +pairs. Subclass :class:`JSONTag` and give it the new key ``' od'`` to +identify the type. The session serializer processes dicts first, so +insert the new tag at the front of the order since ``OrderedDict`` must +be processed before ``dict``. + +.. code-block:: python + + from flask.json.tag import JSONTag + + class TagOrderedDict(JSONTag): + __slots__ = ('serializer',) + key = ' od' + + def check(self, value): + return isinstance(value, OrderedDict) + + def to_json(self, value): + return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] + + def to_python(self, value): + return OrderedDict(value) + + app.session_interface.serializer.register(TagOrderedDict, index=0) +""" + +from __future__ import annotations + +import typing as t +from base64 import b64decode +from base64 import b64encode +from datetime import datetime +from uuid import UUID + +from markupsafe import Markup +from werkzeug.http import http_date +from werkzeug.http import parse_date + +from ..json import dumps +from ..json import loads + + +class JSONTag: + """Base class for defining type tags for :class:`TaggedJSONSerializer`.""" + + __slots__ = ("serializer",) + + #: The tag to mark the serialized object with. If empty, this tag is + #: only used as an intermediate step during tagging. + key: str = "" + + def __init__(self, serializer: TaggedJSONSerializer) -> None: + """Create a tagger for the given serializer.""" + self.serializer = serializer + + def check(self, value: t.Any) -> bool: + """Check if the given value should be tagged by this tag.""" + raise NotImplementedError + + def to_json(self, value: t.Any) -> t.Any: + """Convert the Python object to an object that is a valid JSON type. + The tag will be added later.""" + raise NotImplementedError + + def to_python(self, value: t.Any) -> t.Any: + """Convert the JSON representation back to the correct type. The tag + will already be removed.""" + raise NotImplementedError + + def tag(self, value: t.Any) -> dict[str, t.Any]: + """Convert the value to a valid JSON type and add the tag structure + around it.""" + return {self.key: self.to_json(value)} + + +class TagDict(JSONTag): + """Tag for 1-item dicts whose only key matches a registered tag. + + Internally, the dict key is suffixed with `__`, and the suffix is removed + when deserializing. + """ + + __slots__ = () + key = " di" + + def check(self, value: t.Any) -> bool: + return ( + isinstance(value, dict) + and len(value) == 1 + and next(iter(value)) in self.serializer.tags + ) + + def to_json(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {f"{key}__": self.serializer.tag(value[key])} + + def to_python(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {key[:-2]: value[key]} + + +class PassDict(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, dict) + + def to_json(self, value: t.Any) -> t.Any: + # JSON objects may only have string keys, so don't bother tagging the + # key here. + return {k: self.serializer.tag(v) for k, v in value.items()} + + tag = to_json + + +class TagTuple(JSONTag): + __slots__ = () + key = " t" + + def check(self, value: t.Any) -> bool: + return isinstance(value, tuple) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + def to_python(self, value: t.Any) -> t.Any: + return tuple(value) + + +class PassList(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, list) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + tag = to_json + + +class TagBytes(JSONTag): + __slots__ = () + key = " b" + + def check(self, value: t.Any) -> bool: + return isinstance(value, bytes) + + def to_json(self, value: t.Any) -> t.Any: + return b64encode(value).decode("ascii") + + def to_python(self, value: t.Any) -> t.Any: + return b64decode(value) + + +class TagMarkup(JSONTag): + """Serialize anything matching the :class:`~markupsafe.Markup` API by + having a ``__html__`` method to the result of that method. Always + deserializes to an instance of :class:`~markupsafe.Markup`.""" + + __slots__ = () + key = " m" + + def check(self, value: t.Any) -> bool: + return callable(getattr(value, "__html__", None)) + + def to_json(self, value: t.Any) -> t.Any: + return str(value.__html__()) + + def to_python(self, value: t.Any) -> t.Any: + return Markup(value) + + +class TagUUID(JSONTag): + __slots__ = () + key = " u" + + def check(self, value: t.Any) -> bool: + return isinstance(value, UUID) + + def to_json(self, value: t.Any) -> t.Any: + return value.hex + + def to_python(self, value: t.Any) -> t.Any: + return UUID(value) + + +class TagDateTime(JSONTag): + __slots__ = () + key = " d" + + def check(self, value: t.Any) -> bool: + return isinstance(value, datetime) + + def to_json(self, value: t.Any) -> t.Any: + return http_date(value) + + def to_python(self, value: t.Any) -> t.Any: + return parse_date(value) + + +class TaggedJSONSerializer: + """Serializer that uses a tag system to compactly represent objects that + are not JSON types. Passed as the intermediate serializer to + :class:`itsdangerous.Serializer`. + + The following extra types are supported: + + * :class:`dict` + * :class:`tuple` + * :class:`bytes` + * :class:`~markupsafe.Markup` + * :class:`~uuid.UUID` + * :class:`~datetime.datetime` + """ + + __slots__ = ("tags", "order") + + #: Tag classes to bind when creating the serializer. Other tags can be + #: added later using :meth:`~register`. + default_tags = [ + TagDict, + PassDict, + TagTuple, + PassList, + TagBytes, + TagMarkup, + TagUUID, + TagDateTime, + ] + + def __init__(self) -> None: + self.tags: dict[str, JSONTag] = {} + self.order: list[JSONTag] = [] + + for cls in self.default_tags: + self.register(cls) + + def register( + self, + tag_class: type[JSONTag], + force: bool = False, + index: int | None = None, + ) -> None: + """Register a new tag with this serializer. + + :param tag_class: tag class to register. Will be instantiated with this + serializer instance. + :param force: overwrite an existing tag. If false (default), a + :exc:`KeyError` is raised. + :param index: index to insert the new tag in the tag order. Useful when + the new tag is a special case of an existing tag. If ``None`` + (default), the tag is appended to the end of the order. + + :raise KeyError: if the tag key is already registered and ``force`` is + not true. + """ + tag = tag_class(self) + key = tag.key + + if key: + if not force and key in self.tags: + raise KeyError(f"Tag '{key}' is already registered.") + + self.tags[key] = tag + + if index is None: + self.order.append(tag) + else: + self.order.insert(index, tag) + + def tag(self, value: t.Any) -> t.Any: + """Convert a value to a tagged representation if necessary.""" + for tag in self.order: + if tag.check(value): + return tag.tag(value) + + return value + + def untag(self, value: dict[str, t.Any]) -> t.Any: + """Convert a tagged representation back to the original type.""" + if len(value) != 1: + return value + + key = next(iter(value)) + + if key not in self.tags: + return value + + return self.tags[key].to_python(value[key]) + + def _untag_scan(self, value: t.Any) -> t.Any: + if isinstance(value, dict): + # untag each item recursively + value = {k: self._untag_scan(v) for k, v in value.items()} + # untag the dict itself + value = self.untag(value) + elif isinstance(value, list): + # untag each item recursively + value = [self._untag_scan(item) for item in value] + + return value + + def dumps(self, value: t.Any) -> str: + """Tag the value and dump it to a compact JSON string.""" + return dumps(self.tag(value), separators=(",", ":")) + + def loads(self, value: str) -> t.Any: + """Load data from a JSON string and deserialized any tagged objects.""" + return self._untag_scan(loads(value)) diff --git a/venv/lib/python3.12/site-packages/flask/logging.py b/venv/lib/python3.12/site-packages/flask/logging.py new file mode 100644 index 0000000..0cb8f43 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/logging.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +import logging +import sys +import typing as t + +from werkzeug.local import LocalProxy + +from .globals import request + +if t.TYPE_CHECKING: # pragma: no cover + from .sansio.app import App + + +@LocalProxy +def wsgi_errors_stream() -> t.TextIO: + """Find the most appropriate error stream for the application. If a request + is active, log to ``wsgi.errors``, otherwise use ``sys.stderr``. + + If you configure your own :class:`logging.StreamHandler`, you may want to + use this for the stream. If you are using file or dict configuration and + can't import this directly, you can refer to it as + ``ext://flask.logging.wsgi_errors_stream``. + """ + if request: + return request.environ["wsgi.errors"] # type: ignore[no-any-return] + + return sys.stderr + + +def has_level_handler(logger: logging.Logger) -> bool: + """Check if there is a handler in the logging chain that will handle the + given logger's :meth:`effective level <~logging.Logger.getEffectiveLevel>`. + """ + level = logger.getEffectiveLevel() + current = logger + + while current: + if any(handler.level <= level for handler in current.handlers): + return True + + if not current.propagate: + break + + current = current.parent # type: ignore + + return False + + +#: Log messages to :func:`~flask.logging.wsgi_errors_stream` with the format +#: ``[%(asctime)s] %(levelname)s in %(module)s: %(message)s``. +default_handler = logging.StreamHandler(wsgi_errors_stream) # type: ignore +default_handler.setFormatter( + logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s") +) + + +def create_logger(app: App) -> logging.Logger: + """Get the Flask app's logger and configure it if needed. + + The logger name will be the same as + :attr:`app.import_name `. + + When :attr:`~flask.Flask.debug` is enabled, set the logger level to + :data:`logging.DEBUG` if it is not set. + + If there is no handler for the logger's effective level, add a + :class:`~logging.StreamHandler` for + :func:`~flask.logging.wsgi_errors_stream` with a basic format. + """ + logger = logging.getLogger(app.name) + + if app.debug and not logger.level: + logger.setLevel(logging.DEBUG) + + if not has_level_handler(logger): + logger.addHandler(default_handler) + + return logger diff --git a/venv/lib/python3.12/site-packages/flask/py.typed b/venv/lib/python3.12/site-packages/flask/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/flask/sansio/README.md b/venv/lib/python3.12/site-packages/flask/sansio/README.md new file mode 100644 index 0000000..623ac19 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/sansio/README.md @@ -0,0 +1,6 @@ +# Sansio + +This folder contains code that can be used by alternative Flask +implementations, for example Quart. The code therefore cannot do any +IO, nor be part of a likely IO path. Finally this code cannot use the +Flask globals. diff --git a/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..950ce43127a04871be78af5ed2834638db104922 GIT binary patch literal 33595 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c73d01376278e433d9e86d4be6124cd0c4b6843 GIT binary patch literal 31192 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

kmCu6=UXzSWZb*IhURy!g^vQ#YqFw$00%(_5dD zw>}3}RqPvb!Dp3|$9XHr~QrgGCpDFwQ(bfK(nzU)Tr zLT#$P>-LWH&ZF|qqpM}du9s%&TNiuZ+H-SH#@4uWF}>x8yyXb`(11SF{JrZm&$~Y4 V=>GAj<$!}Pn|FM|(UUF5{{=c_Q)2)C literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/scaffold.cpython-312.pyc b/venv/lib/python3.12/site-packages/flask/sansio/__pycache__/scaffold.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5bbf8f3fd71118fc69d2bbcd5acaf1b2c4911f4 GIT binary patch literal 30497 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 timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class App(Scaffold): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + #: The class of the object assigned to :attr:`aborter`, created by + #: :meth:`create_aborter`. That object is called by + #: :func:`flask.abort` to raise HTTP errors, and can be + #: called directly as well. + #: + #: Defaults to :class:`werkzeug.exceptions.Aborter`. + #: + #: .. versionadded:: 2.2 + aborter_class = Aborter + + #: The class that is used for the Jinja environment. + #: + #: .. versionadded:: 0.11 + jinja_environment = Environment + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on unexpected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is now application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + #: The class that is used for the ``config`` attribute of this app. + #: Defaults to :class:`~flask.Config`. + #: + #: Example use cases for a custom class: + #: + #: 1. Default values for certain config options. + #: 2. Access to config values through attributes in addition to keys. + #: + #: .. versionadded:: 0.11 + config_class = Config + + #: The testing flag. Set this to ``True`` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate test helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: ``TESTING`` configuration key. Defaults to ``False``. + testing = ConfigAttribute[bool]("TESTING") + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. + secret_key = ConfigAttribute[t.Union[str, bytes, None]]("SECRET_KEY") + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute[timedelta]( + "PERMANENT_SESSION_LIFETIME", + get_converter=_make_timedelta, # type: ignore[arg-type] + ) + + json_provider_class: type[JSONProvider] = DefaultJSONProvider + """A subclass of :class:`~flask.json.provider.JSONProvider`. An + instance is created and assigned to :attr:`app.json` when creating + the app. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses + Python's built-in :mod:`json` library. A different provider can use + a different JSON library. + + .. versionadded:: 2.2 + """ + + #: Options that are passed to the Jinja environment in + #: :meth:`create_jinja_environment`. Changing these options after + #: the environment is created (accessing :attr:`jinja_env`) will + #: have no effect. + #: + #: .. versionchanged:: 1.1.0 + #: This is a ``dict`` instead of an ``ImmutableDict`` to allow + #: easier configuration. + #: + jinja_options: dict[str, t.Any] = {} + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: The map object to use for storing the URL rules and routing + #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. + #: + #: .. versionadded:: 1.1.0 + url_map_class = Map + + #: The :meth:`test_client` method creates an instance of this test + #: client class. Defaults to :class:`~flask.testing.FlaskClient`. + #: + #: .. versionadded:: 0.7 + test_client_class: type[FlaskClient] | None = None + + #: The :class:`~click.testing.CliRunner` subclass, by default + #: :class:`~flask.testing.FlaskCliRunner` that is used by + #: :meth:`test_cli_runner`. Its ``__init__`` method should take a + #: Flask app object as the first argument. + #: + #: .. versionadded:: 1.0 + test_cli_runner_class: type[FlaskCliRunner] | None = None + + default_config: dict[str, t.Any] + response_class: type[Response] + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike[str] | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike[str] | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: An instance of :attr:`aborter_class` created by + #: :meth:`make_aborter`. This is called by :func:`flask.abort` + #: to raise HTTP errors, and can be called directly as well. + #: + #: .. versionadded:: 2.2 + #: Moved from ``flask.abort``, which calls this object. + self.aborter = self.make_aborter() + + self.json: JSONProvider = self.json_provider_class(self) + """Provides access to JSON methods. Functions in ``flask.json`` + will call methods on this provider when the application context + is active. Used for handling JSON requests and responses. + + An instance of :attr:`json_provider_class`. Can be customized by + changing that attribute on a subclass, or by assigning to this + attribute afterwards. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, + uses Python's built-in :mod:`json` library. A different provider + can use a different JSON library. + + .. versionadded:: 2.2 + """ + + #: A list of functions that are called by + #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function is called + #: with ``error``, ``endpoint`` and ``values``. If a function + #: returns ``None`` or raises a ``BuildError``, it is skipped. + #: Otherwise, its return value is returned by ``url_for``. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: list[ + t.Callable[[Exception, str, dict[str, t.Any]], str] + ] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: dict[str, Blueprint] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict[str, t.Any] = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class(host_matching=host_matching) + + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_first_request: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called" + " on the application. It has already handled its first" + " request, any changes will not be applied" + " consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the application are done before" + " running it." + ) + + @cached_property + def name(self) -> str: # type: ignore + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn: str | None = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + def create_jinja_environment(self) -> Environment: + raise NotImplementedError() + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def make_aborter(self) -> Aborter: + """Create the object to assign to :attr:`aborter`. That object + is called by :func:`flask.abort` to raise HTTP errors, and can + be called directly as well. + + By default, this creates an instance of :attr:`aborter_class`, + which defaults to :class:`werkzeug.exceptions.Aborter`. + + .. versionadded:: 2.2 + """ + return self.aborter_class() + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionchanged:: 2.2 + Autoescaping is now enabled by default for ``.svg`` files. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start the + development server, an interactive debugger will be shown for unhandled + exceptions, and the server will be reloaded when code changes. This maps to the + :data:`DEBUG` config key. It may not behave as expected if set late. + + **Do not enable debug mode when deploying in production.** + + Default: ``False`` + """ + return self.config["DEBUG"] # type: ignore[no-any-return] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + + if self.config["TEMPLATES_AUTO_RELOAD"] is None: + self.jinja_env.auto_reload = value + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView[Blueprint]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods = set(getattr(view_func, "required_methods", ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + if provide_automatic_options is None: + provide_automatic_options = getattr( + view_func, "provide_automatic_options", None + ) + + if provide_automatic_options is None: + if "OPTIONS" not in methods: + provide_automatic_options = True + required_methods.add("OPTIONS") + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule_obj = self.url_rule_class(rule, methods=methods, **options) + rule_obj.provide_automatic_options = provide_automatic_options # type: ignore[attr-defined] + + self.url_map.add(rule_obj) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError( + "View function mapping is overwriting an existing" + f" endpoint function: {endpoint}" + ) + self.view_functions[endpoint] = view_func + + @setupmethod + def template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def teardown_appcontext(self, f: T_teardown) -> T_teardown: + """Registers a function to be called when the application + context is popped. The application context is typically popped + after the request context for each request, at the end of CLI + commands, or after a manually pushed context ends. + + .. code-block:: python + + with app.app_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the app context is + made inactive. Since a request context typically also manages an + application context it would also be called when you pop a + request context. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def shell_context_processor( + self, f: T_shell_context_processor + ) -> T_shell_context_processor: + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + def _find_error_handler( + self, e: Exception, blueprints: list[str] + ) -> ft.ErrorHandlerCallable | None: + """Return a registered error handler for an exception in this order: + blueprint handler for a specific code, app handler for a specific code, + blueprint handler for an exception class, app handler for an exception + class, or ``None`` if a suitable handler is not found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + names = (*blueprints, None) + + for c in (code, None) if code is not None else (None,): + for name in names: + handler_map = self.error_handler_spec[name][c] + + if not handler_map: + continue + + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + + if handler is not None: + return handler + return None + + def trap_http_exception(self, e: Exception) -> bool: + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionchanged:: 1.0 + Bad request errors are not trapped by default in debug mode. + + .. versionadded:: 0.8 + """ + if self.config["TRAP_HTTP_EXCEPTIONS"]: + return True + + trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] + + # if unset, trap key errors in debug mode + if ( + trap_bad_request is None + and self.debug + and isinstance(e, BadRequestKeyError) + ): + return True + + if trap_bad_request: + return isinstance(e, BadRequest) + + return False + + def should_ignore_error(self, error: BaseException | None) -> bool: + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def redirect(self, location: str, code: int = 302) -> BaseResponse: + """Create a redirect response object. + + This is called by :func:`flask.redirect`, and can be called + directly as well. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + + .. versionadded:: 2.2 + Moved from ``flask.redirect``, which calls this method. + """ + return _wz_redirect( + location, + code=code, + Response=self.response_class, # type: ignore[arg-type] + ) + + def inject_url_defaults(self, endpoint: str, values: dict[str, t.Any]) -> None: + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + names: t.Iterable[str | None] = (None,) + + # url_for may be called outside a request context, parse the + # passed endpoint instead of using request.blueprints. + if "." in endpoint: + names = chain( + names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) + ) + + for name in names: + if name in self.url_default_functions: + for func in self.url_default_functions[name]: + func(endpoint, values) + + def handle_url_build_error( + self, error: BuildError, endpoint: str, values: dict[str, t.Any] + ) -> str: + """Called by :meth:`.url_for` if a + :exc:`~werkzeug.routing.BuildError` was raised. If this returns + a value, it will be returned by ``url_for``, otherwise the error + will be re-raised. + + Each function in :attr:`url_build_error_handlers` is called with + ``error``, ``endpoint`` and ``values``. If a function returns + ``None`` or raises a ``BuildError``, it is skipped. Otherwise, + its return value is returned by ``url_for``. + + :param error: The active ``BuildError`` being handled. + :param endpoint: The endpoint being built. + :param values: The keyword arguments passed to ``url_for``. + """ + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + except BuildError as e: + # make error available outside except block + error = e + else: + if rv is not None: + return rv + + # Re-raise if called with an active exception, otherwise raise + # the passed in exception. + if error is sys.exc_info()[1]: + raise + + raise error diff --git a/venv/lib/python3.12/site-packages/flask/sansio/blueprints.py b/venv/lib/python3.12/site-packages/flask/sansio/blueprints.py new file mode 100644 index 0000000..4f912cc --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/sansio/blueprints.py @@ -0,0 +1,632 @@ +from __future__ import annotations + +import os +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from .. import typing as ft +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from .app import App + +DeferredSetupFunction = t.Callable[["BlueprintSetupState"], None] +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) + + +class BlueprintSetupState: + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__( + self, + blueprint: Blueprint, + app: App, + options: t.Any, + first_registration: bool, + ) -> None: + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get("subdomain") + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get("url_prefix") + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + self.name = self.options.get("name", blueprint.name) + self.name_prefix = self.options.get("name_prefix", "") + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get("url_defaults", ())) + + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + **options: t.Any, + ) -> None: + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix is not None: + if rule: + rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) + else: + rule = self.url_prefix + options.setdefault("subdomain", self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + defaults = self.url_defaults + if "defaults" in options: + defaults = dict(defaults, **options.pop("defaults")) + + self.app.add_url_rule( + rule, + f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), + view_func, + defaults=defaults, + **options, + ) + + +class Blueprint(Scaffold): + """Represents a blueprint, a collection of routes and other + app-related functions that can be registered on a real application + later. + + A blueprint is an object that allows defining application functions + without requiring an application object ahead of time. It uses the + same decorators as :class:`~flask.Flask`, but defers the need for an + application by recording them for later registration. + + Decorating a function with a blueprint creates a deferred function + that is called with :class:`~flask.blueprints.BlueprintSetupState` + when the blueprint is registered on an application. + + See :doc:`/blueprints` for more information. + + :param name: The name of the blueprint. Will be prepended to each + endpoint name. + :param import_name: The name of the blueprint package, usually + ``__name__``. This helps locate the ``root_path`` for the + blueprint. + :param static_folder: A folder with static files that should be + served by the blueprint's static route. The path is relative to + the blueprint's root path. Blueprint static files are disabled + by default. + :param static_url_path: The url to serve static files from. + Defaults to ``static_folder``. If the blueprint does not have + a ``url_prefix``, the app's static route will take precedence, + and the blueprint's static files won't be accessible. + :param template_folder: A folder with templates that should be added + to the app's template search path. The path is relative to the + blueprint's root path. Blueprint templates are disabled by + default. Blueprint templates have a lower precedence than those + in the app's templates folder. + :param url_prefix: A path to prepend to all of the blueprint's URLs, + to make them distinct from the rest of the app's routes. + :param subdomain: A subdomain that blueprint routes will match on by + default. + :param url_defaults: A dict of default values that blueprint routes + will receive by default. + :param root_path: By default, the blueprint will automatically set + this based on ``import_name``. In certain situations this + automatic detection can fail, so the path can be specified + manually instead. + + .. versionchanged:: 1.1.0 + Blueprints have a ``cli`` group to register nested CLI commands. + The ``cli_group`` parameter controls the name of the group under + the ``flask`` command. + + .. versionadded:: 0.7 + """ + + _got_registered_once = False + + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict[str, t.Any] | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore[assignment] + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if not name: + raise ValueError("'name' may not be empty.") + + if "." in name: + raise ValueError("'name' may not contain a dot '.' character.") + + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.deferred_functions: list[DeferredSetupFunction] = [] + + if url_defaults is None: + url_defaults = {} + + self.url_values_defaults = url_defaults + self.cli_group = cli_group + self._blueprints: list[tuple[Blueprint, dict[str, t.Any]]] = [] + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_registered_once: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called on the blueprint" + f" '{self.name}'. It has already been registered at least once, any" + " changes will not be applied consistently.\n" + "Make sure all imports, decorators, functions, etc. needed to set up" + " the blueprint are done before registering it." + ) + + @setupmethod + def record(self, func: DeferredSetupFunction) -> None: + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + self.deferred_functions.append(func) + + @setupmethod + def record_once(self, func: DeferredSetupFunction) -> None: + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + + def wrapper(state: BlueprintSetupState) -> None: + if state.first_registration: + func(state) + + self.record(update_wrapper(wrapper, func)) + + def make_setup_state( + self, app: App, options: dict[str, t.Any], first_registration: bool = False + ) -> BlueprintSetupState: + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on this blueprint. Keyword + arguments passed to this method will override the defaults set + on the blueprint. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 2.0 + """ + if blueprint is self: + raise ValueError("Cannot register a blueprint on itself") + self._blueprints.append((blueprint, options)) + + def register(self, app: App, options: dict[str, t.Any]) -> None: + """Called by :meth:`Flask.register_blueprint` to register all + views and callbacks registered on the blueprint with the + application. Creates a :class:`.BlueprintSetupState` and calls + each :meth:`record` callback with it. + + :param app: The application this blueprint is being registered + with. + :param options: Keyword arguments forwarded from + :meth:`~Flask.register_blueprint`. + + .. versionchanged:: 2.3 + Nested blueprints now correctly apply subdomains. + + .. versionchanged:: 2.1 + Registering the same blueprint with the same name multiple + times is an error. + + .. versionchanged:: 2.0.1 + Nested blueprints are registered with their dotted name. + This allows different blueprints with the same name to be + nested at different locations. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + """ + name_prefix = options.get("name_prefix", "") + self_name = options.get("name", self.name) + name = f"{name_prefix}.{self_name}".lstrip(".") + + if name in app.blueprints: + bp_desc = "this" if app.blueprints[name] is self else "a different" + existing_at = f" '{name}'" if self_name != name else "" + + raise ValueError( + f"The name '{self_name}' is already registered for" + f" {bp_desc} blueprint{existing_at}. Use 'name=' to" + f" provide a unique name." + ) + + first_bp_registration = not any(bp is self for bp in app.blueprints.values()) + first_name_registration = name not in app.blueprints + + app.blueprints[name] = self + self._got_registered_once = True + state = self.make_setup_state(app, options, first_bp_registration) + + if self.has_static_folder: + state.add_url_rule( + f"{self.static_url_path}/", + view_func=self.send_static_file, # type: ignore[attr-defined] + endpoint="static", + ) + + # Merge blueprint data into parent. + if first_bp_registration or first_name_registration: + self._merge_blueprint_funcs(app, name) + + for deferred in self.deferred_functions: + deferred(state) + + cli_resolved_group = options.get("cli_group", self.cli_group) + + if self.cli.commands: + if cli_resolved_group is None: + app.cli.commands.update(self.cli.commands) + elif cli_resolved_group is _sentinel: + self.cli.name = name + app.cli.add_command(self.cli) + else: + self.cli.name = cli_resolved_group + app.cli.add_command(self.cli) + + for blueprint, bp_options in self._blueprints: + bp_options = bp_options.copy() + bp_url_prefix = bp_options.get("url_prefix") + bp_subdomain = bp_options.get("subdomain") + + if bp_subdomain is None: + bp_subdomain = blueprint.subdomain + + if state.subdomain is not None and bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + "." + state.subdomain + elif bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + elif state.subdomain is not None: + bp_options["subdomain"] = state.subdomain + + if bp_url_prefix is None: + bp_url_prefix = blueprint.url_prefix + + if state.url_prefix is not None and bp_url_prefix is not None: + bp_options["url_prefix"] = ( + state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") + ) + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: + bp_options["url_prefix"] = state.url_prefix + + bp_options["name_prefix"] = name + blueprint.register(app, bp_options) + + def _merge_blueprint_funcs(self, app: App, name: str) -> None: + def extend( + bp_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], + parent_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], + ) -> None: + for key, values in bp_dict.items(): + key = name if key is None else f"{name}.{key}" + parent_dict[key].extend(values) + + for key, value in self.error_handler_spec.items(): + key = name if key is None else f"{name}.{key}" + value = defaultdict( + dict, + { + code: {exc_class: func for exc_class, func in code_values.items()} + for code, code_values in value.items() + }, + ) + app.error_handler_spec[key] = value + + for endpoint, func in self.view_functions.items(): + app.view_functions[endpoint] = func + + extend(self.before_request_funcs, app.before_request_funcs) + extend(self.after_request_funcs, app.after_request_funcs) + extend( + self.teardown_request_funcs, + app.teardown_request_funcs, + ) + extend(self.url_default_functions, app.url_default_functions) + extend(self.url_value_preprocessors, app.url_value_preprocessors) + extend(self.template_context_processors, app.template_context_processors) + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for + full documentation. + + The URL rule is prefixed with the blueprint's URL prefix. The endpoint name, + used with :func:`url_for`, is prefixed with the blueprint's name. + """ + if endpoint and "." in endpoint: + raise ValueError("'endpoint' may not contain a dot '.' character.") + + if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: + raise ValueError("'view_func' name may not contain a dot '.' character.") + + self.record( + lambda s: s.add_url_rule( + rule, + endpoint, + view_func, + provide_automatic_options=provide_automatic_options, + **options, + ) + ) + + @setupmethod + def app_template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """Register a template filter, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_app_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a template filter, available in any template rendered by the + application. Works like the :meth:`app_template_filter` decorator. Equivalent to + :meth:`.Flask.add_template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.filters[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """Register a template test, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_app_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a template test, available in any template rendered by the + application. Works like the :meth:`app_template_test` decorator. Equivalent to + :meth:`.Flask.add_template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.tests[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """Register a template global, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_app_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a template global, available in any template rendered by the + application. Works like the :meth:`app_template_global` decorator. Equivalent to + :meth:`.Flask.add_template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.globals[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def before_app_request(self, f: T_before_request) -> T_before_request: + """Like :meth:`before_request`, but before every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.before_request`. + """ + self.record_once( + lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def after_app_request(self, f: T_after_request) -> T_after_request: + """Like :meth:`after_request`, but after every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.after_request`. + """ + self.record_once( + lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def teardown_app_request(self, f: T_teardown) -> T_teardown: + """Like :meth:`teardown_request`, but after every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`. + """ + self.record_once( + lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_context_processor( + self, f: T_template_context_processor + ) -> T_template_context_processor: + """Like :meth:`context_processor`, but for templates rendered by every view, not + only by the blueprint. Equivalent to :meth:`.Flask.context_processor`. + """ + self.record_once( + lambda s: s.app.template_context_processors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_errorhandler( + self, code: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Like :meth:`errorhandler`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.errorhandler`. + """ + + def decorator(f: T_error_handler) -> T_error_handler: + def from_blueprint(state: BlueprintSetupState) -> None: + state.app.errorhandler(code)(f) + + self.record_once(from_blueprint) + return f + + return decorator + + @setupmethod + def app_url_value_preprocessor( + self, f: T_url_value_preprocessor + ) -> T_url_value_preprocessor: + """Like :meth:`url_value_preprocessor`, but for every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`. + """ + self.record_once( + lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Like :meth:`url_defaults`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.url_defaults`. + """ + self.record_once( + lambda s: s.app.url_default_functions.setdefault(None, []).append(f) + ) + return f diff --git a/venv/lib/python3.12/site-packages/flask/sansio/scaffold.py b/venv/lib/python3.12/site-packages/flask/sansio/scaffold.py new file mode 100644 index 0000000..69e33a0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/sansio/scaffold.py @@ -0,0 +1,801 @@ +from __future__ import annotations + +import importlib.util +import os +import pathlib +import sys +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from jinja2 import BaseLoader +from jinja2 import FileSystemLoader +from werkzeug.exceptions import default_exceptions +from werkzeug.exceptions import HTTPException +from werkzeug.utils import cached_property + +from .. import typing as ft +from ..helpers import get_root_path +from ..templating import _default_template_ctx_processor + +if t.TYPE_CHECKING: # pragma: no cover + from click import Group + +# a singleton sentinel value for parameter defaults +_sentinel = object() + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) +T_route = t.TypeVar("T_route", bound=ft.RouteCallable) + + +def setupmethod(f: F) -> F: + f_name = f.__name__ + + def wrapper_func(self: Scaffold, *args: t.Any, **kwargs: t.Any) -> t.Any: + self._check_setup_finished(f_name) + return f(self, *args, **kwargs) + + return t.cast(F, update_wrapper(wrapper_func, f)) + + +class Scaffold: + """Common behavior shared between :class:`~flask.Flask` and + :class:`~flask.blueprints.Blueprint`. + + :param import_name: The import name of the module where this object + is defined. Usually :attr:`__name__` should be used. + :param static_folder: Path to a folder of static files to serve. + If this is set, a static route will be added. + :param static_url_path: URL prefix for the static route. + :param template_folder: Path to a folder containing template files. + for rendering. If this is set, a Jinja loader will be added. + :param root_path: The path that static, template, and resource files + are relative to. Typically not set, it is discovered based on + the ``import_name``. + + .. versionadded:: 2.0 + """ + + cli: Group + name: str + _static_folder: str | None = None + _static_url_path: str | None = None + + def __init__( + self, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + root_path: str | None = None, + ): + #: The name of the package or module that this object belongs + #: to. Do not change this once it is set by the constructor. + self.import_name = import_name + + self.static_folder = static_folder # type: ignore + self.static_url_path = static_url_path + + #: The path to the templates folder, relative to + #: :attr:`root_path`, to add to the template loader. ``None`` if + #: templates should not be added. + self.template_folder = template_folder + + if root_path is None: + root_path = get_root_path(self.import_name) + + #: Absolute path to the package on the filesystem. Used to look + #: up resources contained in the package. + self.root_path = root_path + + #: A dictionary mapping endpoint names to view functions. + #: + #: To register a view function, use the :meth:`route` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.view_functions: dict[str, ft.RouteCallable] = {} + + #: A data structure of registered error handlers, in the format + #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is + #: the name of a blueprint the handlers are active for, or + #: ``None`` for all requests. The ``code`` key is the HTTP + #: status code for ``HTTPException``, or ``None`` for + #: other exceptions. The innermost dictionary maps exception + #: classes to handler functions. + #: + #: To register an error handler, use the :meth:`errorhandler` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.error_handler_spec: dict[ + ft.AppOrBlueprintKey, + dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]], + ] = defaultdict(lambda: defaultdict(dict)) + + #: A data structure of functions to call at the beginning of + #: each request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`before_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.before_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`after_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.after_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request even if an exception is raised, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`teardown_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.teardown_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.TeardownCallable] + ] = defaultdict(list) + + #: A data structure of functions to call to pass extra context + #: values when rendering templates, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`context_processor` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.template_context_processors: dict[ + ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable] + ] = defaultdict(list, {None: [_default_template_ctx_processor]}) + + #: A data structure of functions to call to modify the keyword + #: arguments passed to the view function, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the + #: :meth:`url_value_preprocessor` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_value_preprocessors: dict[ + ft.AppOrBlueprintKey, + list[ft.URLValuePreprocessorCallable], + ] = defaultdict(list) + + #: A data structure of functions to call to modify the keyword + #: arguments when generating URLs, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`url_defaults` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_default_functions: dict[ + ft.AppOrBlueprintKey, list[ft.URLDefaultCallable] + ] = defaultdict(list) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.name!r}>" + + def _check_setup_finished(self, f_name: str) -> None: + raise NotImplementedError + + @property + def static_folder(self) -> str | None: + """The absolute path to the configured static folder. ``None`` + if no static folder is set. + """ + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + else: + return None + + @static_folder.setter + def static_folder(self, value: str | os.PathLike[str] | None) -> None: + if value is not None: + value = os.fspath(value).rstrip(r"\/") + + self._static_folder = value + + @property + def has_static_folder(self) -> bool: + """``True`` if :attr:`static_folder` is set. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @property + def static_url_path(self) -> str | None: + """The URL prefix that the static route will be accessible from. + + If it was not configured during init, it is derived from + :attr:`static_folder`. + """ + if self._static_url_path is not None: + return self._static_url_path + + if self.static_folder is not None: + basename = os.path.basename(self.static_folder) + return f"/{basename}".rstrip("/") + + return None + + @static_url_path.setter + def static_url_path(self, value: str | None) -> None: + if value is not None: + value = value.rstrip("/") + + self._static_url_path = value + + @cached_property + def jinja_loader(self) -> BaseLoader | None: + """The Jinja loader for this object's templates. By default this + is a class :class:`jinja2.loaders.FileSystemLoader` to + :attr:`template_folder` if it is set. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) + else: + return None + + def _method_route( + self, + method: str, + rule: str, + options: dict[str, t.Any], + ) -> t.Callable[[T_route], T_route]: + if "methods" in options: + raise TypeError("Use the 'route' decorator to use the 'methods' argument.") + + return self.route(rule, methods=[method], **options) + + @setupmethod + def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["GET"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("GET", rule, options) + + @setupmethod + def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["POST"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("POST", rule, options) + + @setupmethod + def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PUT"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PUT", rule, options) + + @setupmethod + def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["DELETE"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("DELETE", rule, options) + + @setupmethod + def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PATCH"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PATCH", rule, options) + + @setupmethod + def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Decorate a view function to register it with the given URL + rule and options. Calls :meth:`add_url_rule`, which has more + details about the implementation. + + .. code-block:: python + + @app.route("/") + def index(): + return "Hello, World!" + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and + ``OPTIONS`` are added automatically. + + :param rule: The URL rule string. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + + def decorator(f: T_route) -> T_route: + endpoint = options.pop("endpoint", None) + self.add_url_rule(rule, endpoint, f, **options) + return f + + return decorator + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a rule for routing incoming requests and building + URLs. The :meth:`route` decorator is a shortcut to call this + with the ``view_func`` argument. These are equivalent: + + .. code-block:: python + + @app.route("/") + def index(): + ... + + .. code-block:: python + + def index(): + ... + + app.add_url_rule("/", view_func=index) + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. An error + will be raised if a function has already been registered for the + endpoint. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is + always added automatically, and ``OPTIONS`` is added + automatically by default. + + ``view_func`` does not necessarily need to be passed, but if the + rule should participate in routing an endpoint name must be + associated with a view function at some point with the + :meth:`endpoint` decorator. + + .. code-block:: python + + app.add_url_rule("/", endpoint="index") + + @app.endpoint("index") + def index(): + ... + + If ``view_func`` has a ``required_methods`` attribute, those + methods are added to the passed and automatic methods. If it + has a ``provide_automatic_methods`` attribute, it is used as the + default if the parameter is not passed. + + :param rule: The URL rule string. + :param endpoint: The endpoint name to associate with the rule + and view function. Used when routing and building URLs. + Defaults to ``view_func.__name__``. + :param view_func: The view function to associate with the + endpoint name. + :param provide_automatic_options: Add the ``OPTIONS`` method and + respond to ``OPTIONS`` requests automatically. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + raise NotImplementedError + + @setupmethod + def endpoint(self, endpoint: str) -> t.Callable[[F], F]: + """Decorate a view function to register it for the given + endpoint. Used if a rule is added without a ``view_func`` with + :meth:`add_url_rule`. + + .. code-block:: python + + app.add_url_rule("/ex", endpoint="example") + + @app.endpoint("example") + def example(): + ... + + :param endpoint: The endpoint name to associate with the view + function. + """ + + def decorator(f: F) -> F: + self.view_functions[endpoint] = f + return f + + return decorator + + @setupmethod + def before_request(self, f: T_before_request) -> T_before_request: + """Register a function to run before each request. + + For example, this can be used to open a database connection, or + to load the logged in user from the session. + + .. code-block:: python + + @app.before_request + def load_user(): + if "user_id" in session: + g.user = db.session.get(session["user_id"]) + + The function will be called without any arguments. If it returns + a non-``None`` value, the value is handled as if it was the + return value from the view, and further request handling is + stopped. + + This is available on both app and blueprint objects. When used on an app, this + executes before every request. When used on a blueprint, this executes before + every request that the blueprint handles. To register with a blueprint and + execute before every request, use :meth:`.Blueprint.before_app_request`. + """ + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def after_request(self, f: T_after_request) -> T_after_request: + """Register a function to run after each request to this object. + + The function is called with the response object, and must return + a response object. This allows the functions to modify or + replace the response before it is sent. + + If a function raises an exception, any remaining + ``after_request`` functions will not be called. Therefore, this + should not be used for actions that must execute, such as to + close resources. Use :meth:`teardown_request` for that. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.after_app_request`. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f: T_teardown) -> T_teardown: + """Register a function to be called when the request context is + popped. Typically this happens at the end of each request, but + contexts may be pushed manually as well during testing. + + .. code-block:: python + + with app.test_request_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the request context is + made inactive. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.teardown_app_request`. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def context_processor( + self, + f: T_template_context_processor, + ) -> T_template_context_processor: + """Registers a template context processor function. These functions run before + rendering a template. The keys of the returned dict are added as variables + available in the template. + + This is available on both app and blueprint objects. When used on an app, this + is called for every rendered template. When used on a blueprint, this is called + for templates rendered from the blueprint's views. To register with a blueprint + and affect every template, use :meth:`.Blueprint.app_context_processor`. + """ + self.template_context_processors[None].append(f) + return f + + @setupmethod + def url_value_preprocessor( + self, + f: T_url_value_preprocessor, + ) -> T_url_value_preprocessor: + """Register a URL value preprocessor function for all view + functions in the application. These functions will be called before the + :meth:`before_request` functions. + + The function can modify the values captured from the matched url before + they are passed to the view. For example, this can be used to pop a + common language code value and place it in ``g`` rather than pass it to + every view. + + The function is passed the endpoint name and values dict. The return + value is ignored. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_value_preprocessor`. + """ + self.url_value_preprocessors[None].append(f) + return f + + @setupmethod + def url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_defaults`. + """ + self.url_default_functions[None].append(f) + return f + + @setupmethod + def errorhandler( + self, code_or_exception: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Register a function to handle errors by code or exception class. + + A decorator that is used to register a function given an + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + This is available on both app and blueprint objects. When used on an app, this + can handle errors from every request. When used on a blueprint, this can handle + errors from requests that the blueprint handles. To register with a blueprint + and affect every request, use :meth:`.Blueprint.app_errorhandler`. + + .. versionadded:: 0.7 + Use :meth:`register_error_handler` instead of modifying + :attr:`error_handler_spec` directly, for application wide error + handlers. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code_or_exception: the code as integer for the handler, or + an arbitrary exception + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.register_error_handler(code_or_exception, f) + return f + + return decorator + + @setupmethod + def register_error_handler( + self, + code_or_exception: type[Exception] | int, + f: ft.ErrorHandlerCallable, + ) -> None: + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + exc_class, code = self._get_exc_class_and_code(code_or_exception) + self.error_handler_spec[None][code][exc_class] = f + + @staticmethod + def _get_exc_class_and_code( + exc_class_or_code: type[Exception] | int, + ) -> tuple[type[Exception], int | None]: + """Get the exception class being handled. For HTTP status codes + or ``HTTPException`` subclasses, return both the exception and + status code. + + :param exc_class_or_code: Any exception class, or an HTTP status + code as an integer. + """ + exc_class: type[Exception] + + if isinstance(exc_class_or_code, int): + try: + exc_class = default_exceptions[exc_class_or_code] + except KeyError: + raise ValueError( + f"'{exc_class_or_code}' is not a recognized HTTP" + " error code. Use a subclass of HTTPException with" + " that code instead." + ) from None + else: + exc_class = exc_class_or_code + + if isinstance(exc_class, Exception): + raise TypeError( + f"{exc_class!r} is an instance, not a class. Handlers" + " can only be registered for Exception classes or HTTP" + " error codes." + ) + + if not issubclass(exc_class, Exception): + raise ValueError( + f"'{exc_class.__name__}' is not a subclass of Exception." + " Handlers can only be registered for Exception classes" + " or HTTP error codes." + ) + + if issubclass(exc_class, HTTPException): + return exc_class, exc_class.code + else: + return exc_class, None + + +def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str: + """Internal helper that returns the default endpoint for a given + function. This always is the function name. + """ + assert view_func is not None, "expected view func if endpoint is not provided." + return view_func.__name__ + + +def _path_is_relative_to(path: pathlib.PurePath, base: str) -> bool: + # Path.is_relative_to doesn't exist until Python 3.9 + try: + path.relative_to(base) + return True + except ValueError: + return False + + +def _find_package_path(import_name: str) -> str: + """Find the path that contains the package or module.""" + root_mod_name, _, _ = import_name.partition(".") + + try: + root_spec = importlib.util.find_spec(root_mod_name) + + if root_spec is None: + raise ValueError("not found") + except (ImportError, ValueError): + # ImportError: the machinery told us it does not exist + # ValueError: + # - the module name was invalid + # - the module name is __main__ + # - we raised `ValueError` due to `root_spec` being `None` + return os.getcwd() + + if root_spec.submodule_search_locations: + if root_spec.origin is None or root_spec.origin == "namespace": + # namespace package + package_spec = importlib.util.find_spec(import_name) + + if package_spec is not None and package_spec.submodule_search_locations: + # Pick the path in the namespace that contains the submodule. + package_path = pathlib.Path( + os.path.commonpath(package_spec.submodule_search_locations) + ) + search_location = next( + location + for location in root_spec.submodule_search_locations + if _path_is_relative_to(package_path, location) + ) + else: + # Pick the first path. + search_location = root_spec.submodule_search_locations[0] + + return os.path.dirname(search_location) + else: + # package with __init__.py + return os.path.dirname(os.path.dirname(root_spec.origin)) + else: + # module + return os.path.dirname(root_spec.origin) # type: ignore[type-var, return-value] + + +def find_package(import_name: str) -> tuple[str | None, str]: + """Find the prefix that a package is installed under, and the path + that it would be imported from. + + The prefix is the directory containing the standard directory + hierarchy (lib, bin, etc.). If the package is not installed to the + system (:attr:`sys.prefix`) or a virtualenv (``site-packages``), + ``None`` is returned. + + The path is the entry in :attr:`sys.path` that contains the package + for import. If the package is not installed, it's assumed that the + package was imported from the current working directory. + """ + package_path = _find_package_path(import_name) + py_prefix = os.path.abspath(sys.prefix) + + # installed to the system + if _path_is_relative_to(pathlib.PurePath(package_path), py_prefix): + return py_prefix, package_path + + site_parent, site_folder = os.path.split(package_path) + + # installed to a virtualenv + if site_folder.lower() == "site-packages": + parent, folder = os.path.split(site_parent) + + # Windows (prefix/lib/site-packages) + if folder.lower() == "lib": + return parent, package_path + + # Unix (prefix/lib/pythonX.Y/site-packages) + if os.path.basename(parent).lower() == "lib": + return os.path.dirname(parent), package_path + + # something else (prefix/site-packages) + return site_parent, package_path + + # not installed + return None, package_path diff --git a/venv/lib/python3.12/site-packages/flask/sessions.py b/venv/lib/python3.12/site-packages/flask/sessions.py new file mode 100644 index 0000000..ee19ad6 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/sessions.py @@ -0,0 +1,379 @@ +from __future__ import annotations + +import hashlib +import typing as t +from collections.abc import MutableMapping +from datetime import datetime +from datetime import timezone + +from itsdangerous import BadSignature +from itsdangerous import URLSafeTimedSerializer +from werkzeug.datastructures import CallbackDict + +from .json.tag import TaggedJSONSerializer + +if t.TYPE_CHECKING: # pragma: no cover + import typing_extensions as te + + from .app import Flask + from .wrappers import Request + from .wrappers import Response + + +# TODO generic when Python > 3.8 +class SessionMixin(MutableMapping): # type: ignore[type-arg] + """Expands a basic dictionary with session attributes.""" + + @property + def permanent(self) -> bool: + """This reflects the ``'_permanent'`` key in the dict.""" + return self.get("_permanent", False) + + @permanent.setter + def permanent(self, value: bool) -> None: + self["_permanent"] = bool(value) + + #: Some implementations can detect whether a session is newly + #: created, but that is not guaranteed. Use with caution. The mixin + # default is hard-coded ``False``. + new = False + + #: Some implementations can detect changes to the session and set + #: this when that happens. The mixin default is hard coded to + #: ``True``. + modified = True + + #: Some implementations can detect when session data is read or + #: written and set this when that happens. The mixin default is hard + #: coded to ``True``. + accessed = True + + +# TODO generic when Python > 3.8 +class SecureCookieSession(CallbackDict, SessionMixin): # type: ignore[type-arg] + """Base class for sessions based on signed cookies. + + This session backend will set the :attr:`modified` and + :attr:`accessed` attributes. It cannot reliably track whether a + session is new (vs. empty), so :attr:`new` remains hard coded to + ``False``. + """ + + #: When data is changed, this is set to ``True``. Only the session + #: dictionary itself is tracked; if the session contains mutable + #: data (for example a nested dict) then this must be set to + #: ``True`` manually when modifying that data. The session cookie + #: will only be written to the response if this is ``True``. + modified = False + + #: When data is read or written, this is set to ``True``. Used by + # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie`` + #: header, which allows caching proxies to cache different pages for + #: different users. + accessed = False + + def __init__(self, initial: t.Any = None) -> None: + def on_update(self: te.Self) -> None: + self.modified = True + self.accessed = True + + super().__init__(initial, on_update) + + def __getitem__(self, key: str) -> t.Any: + self.accessed = True + return super().__getitem__(key) + + def get(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().get(key, default) + + def setdefault(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().setdefault(key, default) + + +class NullSession(SecureCookieSession): + """Class used to generate nicer error messages if sessions are not + available. Will still allow read-only access to the empty session + but fail on setting. + """ + + def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + raise RuntimeError( + "The session is unavailable because no secret " + "key was set. Set the secret_key on the " + "application to something unique and secret." + ) + + __setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail # type: ignore # noqa: B950 + del _fail + + +class SessionInterface: + """The basic interface you have to implement in order to replace the + default session interface which uses werkzeug's securecookie + implementation. The only methods you have to implement are + :meth:`open_session` and :meth:`save_session`, the others have + useful defaults which you don't need to change. + + The session object returned by the :meth:`open_session` method has to + provide a dictionary like interface plus the properties and methods + from the :class:`SessionMixin`. We recommend just subclassing a dict + and adding that mixin:: + + class Session(dict, SessionMixin): + pass + + If :meth:`open_session` returns ``None`` Flask will call into + :meth:`make_null_session` to create a session that acts as replacement + if the session support cannot work because some requirement is not + fulfilled. The default :class:`NullSession` class that is created + will complain that the secret key was not set. + + To replace the session interface on an application all you have to do + is to assign :attr:`flask.Flask.session_interface`:: + + app = Flask(__name__) + app.session_interface = MySessionInterface() + + Multiple requests with the same session may be sent and handled + concurrently. When implementing a new session interface, consider + whether reads or writes to the backing store must be synchronized. + There is no guarantee on the order in which the session for each + request is opened or saved, it will occur in the order that requests + begin and end processing. + + .. versionadded:: 0.8 + """ + + #: :meth:`make_null_session` will look here for the class that should + #: be created when a null session is requested. Likewise the + #: :meth:`is_null_session` method will perform a typecheck against + #: this type. + null_session_class = NullSession + + #: A flag that indicates if the session interface is pickle based. + #: This can be used by Flask extensions to make a decision in regards + #: to how to deal with the session object. + #: + #: .. versionadded:: 0.10 + pickle_based = False + + def make_null_session(self, app: Flask) -> NullSession: + """Creates a null session which acts as a replacement object if the + real session support could not be loaded due to a configuration + error. This mainly aids the user experience because the job of the + null session is to still support lookup without complaining but + modifications are answered with a helpful error message of what + failed. + + This creates an instance of :attr:`null_session_class` by default. + """ + return self.null_session_class() + + def is_null_session(self, obj: object) -> bool: + """Checks if a given object is a null session. Null sessions are + not asked to be saved. + + This checks if the object is an instance of :attr:`null_session_class` + by default. + """ + return isinstance(obj, self.null_session_class) + + def get_cookie_name(self, app: Flask) -> str: + """The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``.""" + return app.config["SESSION_COOKIE_NAME"] # type: ignore[no-any-return] + + def get_cookie_domain(self, app: Flask) -> str | None: + """The value of the ``Domain`` parameter on the session cookie. If not set, + browsers will only send the cookie to the exact domain it was set from. + Otherwise, they will send it to any subdomain of the given value as well. + + Uses the :data:`SESSION_COOKIE_DOMAIN` config. + + .. versionchanged:: 2.3 + Not set by default, does not fall back to ``SERVER_NAME``. + """ + return app.config["SESSION_COOKIE_DOMAIN"] # type: ignore[no-any-return] + + def get_cookie_path(self, app: Flask) -> str: + """Returns the path for which the cookie should be valid. The + default implementation uses the value from the ``SESSION_COOKIE_PATH`` + config var if it's set, and falls back to ``APPLICATION_ROOT`` or + uses ``/`` if it's ``None``. + """ + return app.config["SESSION_COOKIE_PATH"] or app.config["APPLICATION_ROOT"] # type: ignore[no-any-return] + + def get_cookie_httponly(self, app: Flask) -> bool: + """Returns True if the session cookie should be httponly. This + currently just returns the value of the ``SESSION_COOKIE_HTTPONLY`` + config var. + """ + return app.config["SESSION_COOKIE_HTTPONLY"] # type: ignore[no-any-return] + + def get_cookie_secure(self, app: Flask) -> bool: + """Returns True if the cookie should be secure. This currently + just returns the value of the ``SESSION_COOKIE_SECURE`` setting. + """ + return app.config["SESSION_COOKIE_SECURE"] # type: ignore[no-any-return] + + def get_cookie_samesite(self, app: Flask) -> str | None: + """Return ``'Strict'`` or ``'Lax'`` if the cookie should use the + ``SameSite`` attribute. This currently just returns the value of + the :data:`SESSION_COOKIE_SAMESITE` setting. + """ + return app.config["SESSION_COOKIE_SAMESITE"] # type: ignore[no-any-return] + + def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None: + """A helper method that returns an expiration date for the session + or ``None`` if the session is linked to the browser session. The + default implementation returns now + the permanent session + lifetime configured on the application. + """ + if session.permanent: + return datetime.now(timezone.utc) + app.permanent_session_lifetime + return None + + def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool: + """Used by session backends to determine if a ``Set-Cookie`` header + should be set for this session cookie for this response. If the session + has been modified, the cookie is set. If the session is permanent and + the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is + always set. + + This check is usually skipped if the session was deleted. + + .. versionadded:: 0.11 + """ + + return session.modified or ( + session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"] + ) + + def open_session(self, app: Flask, request: Request) -> SessionMixin | None: + """This is called at the beginning of each request, after + pushing the request context, before matching the URL. + + This must return an object which implements a dictionary-like + interface as well as the :class:`SessionMixin` interface. + + This will return ``None`` to indicate that loading failed in + some way that is not immediately an error. The request + context will fall back to using :meth:`make_null_session` + in this case. + """ + raise NotImplementedError() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + """This is called at the end of each request, after generating + a response, before removing the request context. It is skipped + if :meth:`is_null_session` returns ``True``. + """ + raise NotImplementedError() + + +session_json_serializer = TaggedJSONSerializer() + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class SecureCookieSessionInterface(SessionInterface): + """The default session interface that stores sessions in signed cookies + through the :mod:`itsdangerous` module. + """ + + #: the salt that should be applied on top of the secret key for the + #: signing of cookie based sessions. + salt = "cookie-session" + #: the hash function to use for the signature. The default is sha1 + digest_method = staticmethod(_lazy_sha1) + #: the name of the itsdangerous supported key derivation. The default + #: is hmac. + key_derivation = "hmac" + #: A python serializer for the payload. The default is a compact + #: JSON derived serializer with support for some extra Python types + #: such as datetime objects or tuples. + serializer = session_json_serializer + session_class = SecureCookieSession + + def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None: + if not app.secret_key: + return None + signer_kwargs = dict( + key_derivation=self.key_derivation, digest_method=self.digest_method + ) + return URLSafeTimedSerializer( + app.secret_key, + salt=self.salt, + serializer=self.serializer, + signer_kwargs=signer_kwargs, + ) + + def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None: + s = self.get_signing_serializer(app) + if s is None: + return None + val = request.cookies.get(self.get_cookie_name(app)) + if not val: + return self.session_class() + max_age = int(app.permanent_session_lifetime.total_seconds()) + try: + data = s.loads(val, max_age=max_age) + return self.session_class(data) + except BadSignature: + return self.session_class() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + name = self.get_cookie_name(app) + domain = self.get_cookie_domain(app) + path = self.get_cookie_path(app) + secure = self.get_cookie_secure(app) + samesite = self.get_cookie_samesite(app) + httponly = self.get_cookie_httponly(app) + + # Add a "Vary: Cookie" header if the session was accessed at all. + if session.accessed: + response.vary.add("Cookie") + + # If the session is modified to be empty, remove the cookie. + # If the session is empty, return without setting the cookie. + if not session: + if session.modified: + response.delete_cookie( + name, + domain=domain, + path=path, + secure=secure, + samesite=samesite, + httponly=httponly, + ) + response.vary.add("Cookie") + + return + + if not self.should_set_cookie(app, session): + return + + expires = self.get_expiration_time(app, session) + val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore + response.set_cookie( + name, + val, # type: ignore + expires=expires, + httponly=httponly, + domain=domain, + path=path, + secure=secure, + samesite=samesite, + ) + response.vary.add("Cookie") diff --git a/venv/lib/python3.12/site-packages/flask/signals.py b/venv/lib/python3.12/site-packages/flask/signals.py new file mode 100644 index 0000000..444fda9 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/signals.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from blinker import Namespace + +# This namespace is only for signals provided by Flask itself. +_signals = Namespace() + +template_rendered = _signals.signal("template-rendered") +before_render_template = _signals.signal("before-render-template") +request_started = _signals.signal("request-started") +request_finished = _signals.signal("request-finished") +request_tearing_down = _signals.signal("request-tearing-down") +got_request_exception = _signals.signal("got-request-exception") +appcontext_tearing_down = _signals.signal("appcontext-tearing-down") +appcontext_pushed = _signals.signal("appcontext-pushed") +appcontext_popped = _signals.signal("appcontext-popped") +message_flashed = _signals.signal("message-flashed") diff --git a/venv/lib/python3.12/site-packages/flask/templating.py b/venv/lib/python3.12/site-packages/flask/templating.py new file mode 100644 index 0000000..618a3b3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/templating.py @@ -0,0 +1,219 @@ +from __future__ import annotations + +import typing as t + +from jinja2 import BaseLoader +from jinja2 import Environment as BaseEnvironment +from jinja2 import Template +from jinja2 import TemplateNotFound + +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .helpers import stream_with_context +from .signals import before_render_template +from .signals import template_rendered + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .sansio.app import App + from .sansio.scaffold import Scaffold + + +def _default_template_ctx_processor() -> dict[str, t.Any]: + """Default template context processor. Injects `request`, + `session` and `g`. + """ + appctx = _cv_app.get(None) + reqctx = _cv_request.get(None) + rv: dict[str, t.Any] = {} + if appctx is not None: + rv["g"] = appctx.g + if reqctx is not None: + rv["request"] = reqctx.request + rv["session"] = reqctx.session + return rv + + +class Environment(BaseEnvironment): + """Works like a regular Jinja2 environment but has some additional + knowledge of how Flask's blueprint works so that it can prepend the + name of the blueprint to referenced templates if necessary. + """ + + def __init__(self, app: App, **options: t.Any) -> None: + if "loader" not in options: + options["loader"] = app.create_global_jinja_loader() + BaseEnvironment.__init__(self, **options) + self.app = app + + +class DispatchingJinjaLoader(BaseLoader): + """A loader that looks for templates in the application and all + the blueprint folders. + """ + + def __init__(self, app: App) -> None: + self.app = app + + def get_source( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + if self.app.config["EXPLAIN_TEMPLATE_LOADING"]: + return self._get_source_explained(environment, template) + return self._get_source_fast(environment, template) + + def _get_source_explained( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + attempts = [] + rv: tuple[str, str | None, t.Callable[[], bool] | None] | None + trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None + + for srcobj, loader in self._iter_loaders(template): + try: + rv = loader.get_source(environment, template) + if trv is None: + trv = rv + except TemplateNotFound: + rv = None + attempts.append((loader, srcobj, rv)) + + from .debughelpers import explain_template_loading_attempts + + explain_template_loading_attempts(self.app, template, attempts) + + if trv is not None: + return trv + raise TemplateNotFound(template) + + def _get_source_fast( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + for _srcobj, loader in self._iter_loaders(template): + try: + return loader.get_source(environment, template) + except TemplateNotFound: + continue + raise TemplateNotFound(template) + + def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]: + loader = self.app.jinja_loader + if loader is not None: + yield self.app, loader + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + yield blueprint, loader + + def list_templates(self) -> list[str]: + result = set() + loader = self.app.jinja_loader + if loader is not None: + result.update(loader.list_templates()) + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + for template in loader.list_templates(): + result.add(template) + + return list(result) + + +def _render(app: Flask, template: Template, context: dict[str, t.Any]) -> str: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + rv = template.render(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + return rv + + +def render_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> str: + """Render a template by name with the given context. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _render(app, template, context) + + +def render_template_string(source: str, **context: t.Any) -> str: + """Render a template from the given source string with the given + context. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _render(app, template, context) + + +def _stream( + app: Flask, template: Template, context: dict[str, t.Any] +) -> t.Iterator[str]: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + def generate() -> t.Iterator[str]: + yield from template.generate(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + rv = generate() + + # If a request context is active, keep it while generating. + if request: + rv = stream_with_context(rv) + + return rv + + +def stream_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> t.Iterator[str]: + """Render a template by name with the given context as a stream. + This returns an iterator of strings, which can be used as a + streaming response from a view. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _stream(app, template, context) + + +def stream_template_string(source: str, **context: t.Any) -> t.Iterator[str]: + """Render a template from the given source string with the given + context as a stream. This returns an iterator of strings, which can + be used as a streaming response from a view. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _stream(app, template, context) diff --git a/venv/lib/python3.12/site-packages/flask/testing.py b/venv/lib/python3.12/site-packages/flask/testing.py new file mode 100644 index 0000000..a27b7c8 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/testing.py @@ -0,0 +1,298 @@ +from __future__ import annotations + +import importlib.metadata +import typing as t +from contextlib import contextmanager +from contextlib import ExitStack +from copy import copy +from types import TracebackType +from urllib.parse import urlsplit + +import werkzeug.test +from click.testing import CliRunner +from werkzeug.test import Client +from werkzeug.wrappers import Request as BaseRequest + +from .cli import ScriptInfo +from .sessions import SessionMixin + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIEnvironment + from werkzeug.test import TestResponse + + from .app import Flask + + +class EnvironBuilder(werkzeug.test.EnvironBuilder): + """An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the + application. + + :param app: The Flask application to configure the environment from. + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + + def __init__( + self, + app: Flask, + path: str = "/", + base_url: str | None = None, + subdomain: str | None = None, + url_scheme: str | None = None, + *args: t.Any, + **kwargs: t.Any, + ) -> None: + assert not (base_url or subdomain or url_scheme) or ( + base_url is not None + ) != bool( + subdomain or url_scheme + ), 'Cannot pass "subdomain" or "url_scheme" with "base_url".' + + if base_url is None: + http_host = app.config.get("SERVER_NAME") or "localhost" + app_root = app.config["APPLICATION_ROOT"] + + if subdomain: + http_host = f"{subdomain}.{http_host}" + + if url_scheme is None: + url_scheme = app.config["PREFERRED_URL_SCHEME"] + + url = urlsplit(path) + base_url = ( + f"{url.scheme or url_scheme}://{url.netloc or http_host}" + f"/{app_root.lstrip('/')}" + ) + path = url.path + + if url.query: + sep = b"?" if isinstance(url.query, bytes) else "?" + path += sep + url.query + + self.app = app + super().__init__(path, base_url, *args, **kwargs) + + def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str: # type: ignore + """Serialize ``obj`` to a JSON-formatted string. + + The serialization will be configured according to the config associated + with this EnvironBuilder's ``app``. + """ + return self.app.json.dumps(obj, **kwargs) + + +_werkzeug_version = "" + + +def _get_werkzeug_version() -> str: + global _werkzeug_version + + if not _werkzeug_version: + _werkzeug_version = importlib.metadata.version("werkzeug") + + return _werkzeug_version + + +class FlaskClient(Client): + """Works like a regular Werkzeug test client but has knowledge about + Flask's contexts to defer the cleanup of the request context until + the end of a ``with`` block. For general information about how to + use this class refer to :class:`werkzeug.test.Client`. + + .. versionchanged:: 0.12 + `app.test_client()` includes preset default environment, which can be + set after instantiation of the `app.test_client()` object in + `client.environ_base`. + + Basic usage is outlined in the :doc:`/testing` chapter. + """ + + application: Flask + + def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: + super().__init__(*args, **kwargs) + self.preserve_context = False + self._new_contexts: list[t.ContextManager[t.Any]] = [] + self._context_stack = ExitStack() + self.environ_base = { + "REMOTE_ADDR": "127.0.0.1", + "HTTP_USER_AGENT": f"Werkzeug/{_get_werkzeug_version()}", + } + + @contextmanager + def session_transaction( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Iterator[SessionMixin]: + """When used in combination with a ``with`` statement this opens a + session transaction. This can be used to modify the session that + the test client uses. Once the ``with`` block is left the session is + stored back. + + :: + + with client.session_transaction() as session: + session['value'] = 42 + + Internally this is implemented by going through a temporary test + request context and since session handling could depend on + request variables this function accepts the same arguments as + :meth:`~flask.Flask.test_request_context` which are directly + passed through. + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + app = self.application + ctx = app.test_request_context(*args, **kwargs) + self._add_cookies_to_wsgi(ctx.request.environ) + + with ctx: + sess = app.session_interface.open_session(app, ctx.request) + + if sess is None: + raise RuntimeError("Session backend did not open a session.") + + yield sess + resp = app.response_class() + + if app.session_interface.is_null_session(sess): + return + + with ctx: + app.session_interface.save_session(app, sess, resp) + + self._update_cookies_from_response( + ctx.request.host.partition(":")[0], + ctx.request.path, + resp.headers.getlist("Set-Cookie"), + ) + + def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment: + out = {**self.environ_base, **other} + + if self.preserve_context: + out["werkzeug.debug.preserve_context"] = self._new_contexts.append + + return out + + def _request_from_builder_args( + self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] + ) -> BaseRequest: + kwargs["environ_base"] = self._copy_environ(kwargs.get("environ_base", {})) + builder = EnvironBuilder(self.application, *args, **kwargs) + + try: + return builder.get_request() + finally: + builder.close() + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> TestResponse: + if args and isinstance( + args[0], (werkzeug.test.EnvironBuilder, dict, BaseRequest) + ): + if isinstance(args[0], werkzeug.test.EnvironBuilder): + builder = copy(args[0]) + builder.environ_base = self._copy_environ(builder.environ_base or {}) # type: ignore[arg-type] + request = builder.get_request() + elif isinstance(args[0], dict): + request = EnvironBuilder.from_environ( + args[0], app=self.application, environ_base=self._copy_environ({}) + ).get_request() + else: + # isinstance(args[0], BaseRequest) + request = copy(args[0]) + request.environ = self._copy_environ(request.environ) + else: + # request is None + request = self._request_from_builder_args(args, kwargs) + + # Pop any previously preserved contexts. This prevents contexts + # from being preserved across redirects or multiple requests + # within a single block. + self._context_stack.close() + + response = super().open( + request, + buffered=buffered, + follow_redirects=follow_redirects, + ) + response.json_module = self.application.json # type: ignore[assignment] + + # Re-push contexts that were preserved during the request. + while self._new_contexts: + cm = self._new_contexts.pop() + self._context_stack.enter_context(cm) + + return response + + def __enter__(self) -> FlaskClient: + if self.preserve_context: + raise RuntimeError("Cannot nest client invocations") + self.preserve_context = True + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.preserve_context = False + self._context_stack.close() + + +class FlaskCliRunner(CliRunner): + """A :class:`~click.testing.CliRunner` for testing a Flask app's + CLI commands. Typically created using + :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`. + """ + + def __init__(self, app: Flask, **kwargs: t.Any) -> None: + self.app = app + super().__init__(**kwargs) + + def invoke( # type: ignore + self, cli: t.Any = None, args: t.Any = None, **kwargs: t.Any + ) -> t.Any: + """Invokes a CLI command in an isolated environment. See + :meth:`CliRunner.invoke ` for + full method documentation. See :ref:`testing-cli` for examples. + + If the ``obj`` argument is not given, passes an instance of + :class:`~flask.cli.ScriptInfo` that knows how to load the Flask + app being tested. + + :param cli: Command object to invoke. Default is the app's + :attr:`~flask.app.Flask.cli` group. + :param args: List of strings to invoke the command with. + + :return: a :class:`~click.testing.Result` object. + """ + if cli is None: + cli = self.app.cli + + if "obj" not in kwargs: + kwargs["obj"] = ScriptInfo(create_app=lambda: self.app) + + return super().invoke(cli, args, **kwargs) diff --git a/venv/lib/python3.12/site-packages/flask/typing.py b/venv/lib/python3.12/site-packages/flask/typing.py new file mode 100644 index 0000000..cf6d4ae --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/typing.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +import typing as t + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIApplication # noqa: F401 + from werkzeug.datastructures import Headers # noqa: F401 + from werkzeug.sansio.response import Response # noqa: F401 + +# The possible types that are directly convertible or are a Response object. +ResponseValue = t.Union[ + "Response", + str, + bytes, + t.List[t.Any], + # Only dict is actually accepted, but Mapping allows for TypedDict. + t.Mapping[str, t.Any], + t.Iterator[str], + t.Iterator[bytes], +] + +# the possible types for an individual HTTP header +# This should be a Union, but mypy doesn't pass unless it's a TypeVar. +HeaderValue = t.Union[str, t.List[str], t.Tuple[str, ...]] + +# the possible types for HTTP headers +HeadersValue = t.Union[ + "Headers", + t.Mapping[str, HeaderValue], + t.Sequence[t.Tuple[str, HeaderValue]], +] + +# The possible types returned by a route function. +ResponseReturnValue = t.Union[ + ResponseValue, + t.Tuple[ResponseValue, HeadersValue], + t.Tuple[ResponseValue, int], + t.Tuple[ResponseValue, int, HeadersValue], + "WSGIApplication", +] + +# Allow any subclass of werkzeug.Response, such as the one from Flask, +# as a callback argument. Using werkzeug.Response directly makes a +# callback annotated with flask.Response fail type checking. +ResponseClass = t.TypeVar("ResponseClass", bound="Response") + +AppOrBlueprintKey = t.Optional[str] # The App key is None, whereas blueprints are named +AfterRequestCallable = t.Union[ + t.Callable[[ResponseClass], ResponseClass], + t.Callable[[ResponseClass], t.Awaitable[ResponseClass]], +] +BeforeFirstRequestCallable = t.Union[ + t.Callable[[], None], t.Callable[[], t.Awaitable[None]] +] +BeforeRequestCallable = t.Union[ + t.Callable[[], t.Optional[ResponseReturnValue]], + t.Callable[[], t.Awaitable[t.Optional[ResponseReturnValue]]], +] +ShellContextProcessorCallable = t.Callable[[], t.Dict[str, t.Any]] +TeardownCallable = t.Union[ + t.Callable[[t.Optional[BaseException]], None], + t.Callable[[t.Optional[BaseException]], t.Awaitable[None]], +] +TemplateContextProcessorCallable = t.Union[ + t.Callable[[], t.Dict[str, t.Any]], + t.Callable[[], t.Awaitable[t.Dict[str, t.Any]]], +] +TemplateFilterCallable = t.Callable[..., t.Any] +TemplateGlobalCallable = t.Callable[..., t.Any] +TemplateTestCallable = t.Callable[..., bool] +URLDefaultCallable = t.Callable[[str, t.Dict[str, t.Any]], None] +URLValuePreprocessorCallable = t.Callable[ + [t.Optional[str], t.Optional[t.Dict[str, t.Any]]], None +] + +# This should take Exception, but that either breaks typing the argument +# with a specific exception, or decorating multiple times with different +# exceptions (and using a union type on the argument). +# https://github.com/pallets/flask/issues/4095 +# https://github.com/pallets/flask/issues/4295 +# https://github.com/pallets/flask/issues/4297 +ErrorHandlerCallable = t.Union[ + t.Callable[[t.Any], ResponseReturnValue], + t.Callable[[t.Any], t.Awaitable[ResponseReturnValue]], +] + +RouteCallable = t.Union[ + t.Callable[..., ResponseReturnValue], + t.Callable[..., t.Awaitable[ResponseReturnValue]], +] diff --git a/venv/lib/python3.12/site-packages/flask/views.py b/venv/lib/python3.12/site-packages/flask/views.py new file mode 100644 index 0000000..794fdc0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/views.py @@ -0,0 +1,191 @@ +from __future__ import annotations + +import typing as t + +from . import typing as ft +from .globals import current_app +from .globals import request + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +http_method_funcs = frozenset( + ["get", "post", "head", "options", "delete", "put", "trace", "patch"] +) + + +class View: + """Subclass this class and override :meth:`dispatch_request` to + create a generic class-based view. Call :meth:`as_view` to create a + view function that creates an instance of the class with the given + arguments and calls its ``dispatch_request`` method with any URL + variables. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class Hello(View): + init_every_request = False + + def dispatch_request(self, name): + return f"Hello, {name}!" + + app.add_url_rule( + "/hello/", view_func=Hello.as_view("hello") + ) + + Set :attr:`methods` on the class to change what methods the view + accepts. + + Set :attr:`decorators` on the class to apply a list of decorators to + the generated view function. Decorators applied to the class itself + will not be applied to the generated view function! + + Set :attr:`init_every_request` to ``False`` for efficiency, unless + you need to store request-global data on ``self``. + """ + + #: The methods this view is registered for. Uses the same default + #: (``["GET", "HEAD", "OPTIONS"]``) as ``route`` and + #: ``add_url_rule`` by default. + methods: t.ClassVar[t.Collection[str] | None] = None + + #: Control whether the ``OPTIONS`` method is handled automatically. + #: Uses the same default (``True``) as ``route`` and + #: ``add_url_rule`` by default. + provide_automatic_options: t.ClassVar[bool | None] = None + + #: A list of decorators to apply, in order, to the generated view + #: function. Remember that ``@decorator`` syntax is applied bottom + #: to top, so the first decorator in the list would be the bottom + #: decorator. + #: + #: .. versionadded:: 0.8 + decorators: t.ClassVar[list[t.Callable[[F], F]]] = [] + + #: Create a new instance of this view class for every request by + #: default. If a view subclass sets this to ``False``, the same + #: instance is used for every request. + #: + #: A single instance is more efficient, especially if complex setup + #: is done during init. However, storing data on ``self`` is no + #: longer safe across requests, and :data:`~flask.g` should be used + #: instead. + #: + #: .. versionadded:: 2.2 + init_every_request: t.ClassVar[bool] = True + + def dispatch_request(self) -> ft.ResponseReturnValue: + """The actual view function behavior. Subclasses must override + this and return a valid response. Any variables from the URL + rule are passed as keyword arguments. + """ + raise NotImplementedError() + + @classmethod + def as_view( + cls, name: str, *class_args: t.Any, **class_kwargs: t.Any + ) -> ft.RouteCallable: + """Convert the class into a view function that can be registered + for a route. + + By default, the generated view will create a new instance of the + view class for every request and call its + :meth:`dispatch_request` method. If the view class sets + :attr:`init_every_request` to ``False``, the same instance will + be used for every request. + + Except for ``name``, all other arguments passed to this method + are forwarded to the view class ``__init__`` method. + + .. versionchanged:: 2.2 + Added the ``init_every_request`` class attribute. + """ + if cls.init_every_request: + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + self = view.view_class( # type: ignore[attr-defined] + *class_args, **class_kwargs + ) + return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] + + else: + self = cls(*class_args, **class_kwargs) + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] + + if cls.decorators: + view.__name__ = name + view.__module__ = cls.__module__ + for decorator in cls.decorators: + view = decorator(view) + + # We attach the view class to the view function for two reasons: + # first of all it allows us to easily figure out what class-based + # view this thing came from, secondly it's also used for instantiating + # the view class so you can actually replace it with something else + # for testing purposes and debugging. + view.view_class = cls # type: ignore + view.__name__ = name + view.__doc__ = cls.__doc__ + view.__module__ = cls.__module__ + view.methods = cls.methods # type: ignore + view.provide_automatic_options = cls.provide_automatic_options # type: ignore + return view + + +class MethodView(View): + """Dispatches request methods to the corresponding instance methods. + For example, if you implement a ``get`` method, it will be used to + handle ``GET`` requests. + + This can be useful for defining a REST API. + + :attr:`methods` is automatically set based on the methods defined on + the class. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class CounterAPI(MethodView): + def get(self): + return str(session.get("counter", 0)) + + def post(self): + session["counter"] = session.get("counter", 0) + 1 + return redirect(url_for("counter")) + + app.add_url_rule( + "/counter", view_func=CounterAPI.as_view("counter") + ) + """ + + def __init_subclass__(cls, **kwargs: t.Any) -> None: + super().__init_subclass__(**kwargs) + + if "methods" not in cls.__dict__: + methods = set() + + for base in cls.__bases__: + if getattr(base, "methods", None): + methods.update(base.methods) # type: ignore[attr-defined] + + for key in http_method_funcs: + if hasattr(cls, key): + methods.add(key.upper()) + + if methods: + cls.methods = methods + + def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue: + meth = getattr(self, request.method.lower(), None) + + # If the request method is HEAD and we don't have a handler for it + # retry with GET. + if meth is None and request.method == "HEAD": + meth = getattr(self, "get", None) + + assert meth is not None, f"Unimplemented method {request.method!r}" + return current_app.ensure_sync(meth)(**kwargs) # type: ignore[no-any-return] diff --git a/venv/lib/python3.12/site-packages/flask/wrappers.py b/venv/lib/python3.12/site-packages/flask/wrappers.py new file mode 100644 index 0000000..c1eca80 --- /dev/null +++ b/venv/lib/python3.12/site-packages/flask/wrappers.py @@ -0,0 +1,174 @@ +from __future__ import annotations + +import typing as t + +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import HTTPException +from werkzeug.wrappers import Request as RequestBase +from werkzeug.wrappers import Response as ResponseBase + +from . import json +from .globals import current_app +from .helpers import _split_blueprint_path + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.routing import Rule + + +class Request(RequestBase): + """The request object used by default in Flask. Remembers the + matched endpoint and view arguments. + + It is what ends up as :class:`~flask.request`. If you want to replace + the request object used you can subclass this and set + :attr:`~flask.Flask.request_class` to your subclass. + + The request object is a :class:`~werkzeug.wrappers.Request` subclass and + provides all of the attributes Werkzeug defines plus a few Flask + specific ones. + """ + + json_module: t.Any = json + + #: The internal URL rule that matched the request. This can be + #: useful to inspect which methods are allowed for the URL from + #: a before/after handler (``request.url_rule.methods``) etc. + #: Though if the request's method was invalid for the URL rule, + #: the valid list is available in ``routing_exception.valid_methods`` + #: instead (an attribute of the Werkzeug exception + #: :exc:`~werkzeug.exceptions.MethodNotAllowed`) + #: because the request was never internally bound. + #: + #: .. versionadded:: 0.6 + url_rule: Rule | None = None + + #: A dict of view arguments that matched the request. If an exception + #: happened when matching, this will be ``None``. + view_args: dict[str, t.Any] | None = None + + #: If matching the URL failed, this is the exception that will be + #: raised / was raised as part of the request handling. This is + #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or + #: something similar. + routing_exception: HTTPException | None = None + + @property + def max_content_length(self) -> int | None: # type: ignore[override] + """Read-only view of the ``MAX_CONTENT_LENGTH`` config key.""" + if current_app: + return current_app.config["MAX_CONTENT_LENGTH"] # type: ignore[no-any-return] + else: + return None + + @property + def endpoint(self) -> str | None: + """The endpoint that matched the request URL. + + This will be ``None`` if matching failed or has not been + performed yet. + + This in combination with :attr:`view_args` can be used to + reconstruct the same URL or a modified URL. + """ + if self.url_rule is not None: + return self.url_rule.endpoint + + return None + + @property + def blueprint(self) -> str | None: + """The registered name of the current blueprint. + + This will be ``None`` if the endpoint is not part of a + blueprint, or if URL matching failed or has not been performed + yet. + + This does not necessarily match the name the blueprint was + created with. It may have been nested, or registered with a + different name. + """ + endpoint = self.endpoint + + if endpoint is not None and "." in endpoint: + return endpoint.rpartition(".")[0] + + return None + + @property + def blueprints(self) -> list[str]: + """The registered names of the current blueprint upwards through + parent blueprints. + + This will be an empty list if there is no current blueprint, or + if URL matching failed. + + .. versionadded:: 2.0.1 + """ + name = self.blueprint + + if name is None: + return [] + + return _split_blueprint_path(name) + + def _load_form_data(self) -> None: + super()._load_form_data() + + # In debug mode we're replacing the files multidict with an ad-hoc + # subclass that raises a different error for key errors. + if ( + current_app + and current_app.debug + and self.mimetype != "multipart/form-data" + and not self.files + ): + from .debughelpers import attach_enctype_error_multidict + + attach_enctype_error_multidict(self) + + def on_json_loading_failed(self, e: ValueError | None) -> t.Any: + try: + return super().on_json_loading_failed(e) + except BadRequest as e: + if current_app and current_app.debug: + raise + + raise BadRequest() from e + + +class Response(ResponseBase): + """The response object that is used by default in Flask. Works like the + response object from Werkzeug but is set to have an HTML mimetype by + default. Quite often you don't have to create this object yourself because + :meth:`~flask.Flask.make_response` will take care of that for you. + + If you want to replace the response object used you can subclass this and + set :attr:`~flask.Flask.response_class` to your subclass. + + .. versionchanged:: 1.0 + JSON support is added to the response, like the request. This is useful + when testing to get the test client response data as JSON. + + .. versionchanged:: 1.0 + + Added :attr:`max_cookie_size`. + """ + + default_mimetype: str | None = "text/html" + + json_module = json + + autocorrect_location_header = False + + @property + def max_cookie_size(self) -> int: # type: ignore + """Read-only view of the :data:`MAX_COOKIE_SIZE` config key. + + See :attr:`~werkzeug.wrappers.Response.max_cookie_size` in + Werkzeug's docs. + """ + if current_app: + return current_app.config["MAX_COOKIE_SIZE"] # type: ignore[no-any-return] + + # return Werkzeug's default when not in an app context + return super().max_cookie_size diff --git a/venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md new file mode 100644 index 0000000..19b6b45 --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md @@ -0,0 +1,31 @@ +BSD 3-Clause License + +Copyright (c) 2013-2024, Kim Davies and contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA new file mode 100644 index 0000000..c42623e --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA @@ -0,0 +1,250 @@ +Metadata-Version: 2.1 +Name: idna +Version: 3.10 +Summary: Internationalized Domain Names in Applications (IDNA) +Author-email: Kim Davies +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.6 +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 +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Utilities +Requires-Dist: ruff >= 0.6.2 ; extra == "all" +Requires-Dist: mypy >= 1.11.2 ; extra == "all" +Requires-Dist: pytest >= 8.3.2 ; extra == "all" +Requires-Dist: flake8 >= 7.1.1 ; extra == "all" +Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst +Project-URL: Issue tracker, https://github.com/kjd/idna/issues +Project-URL: Source, https://github.com/kjd/idna +Provides-Extra: all + +Internationalized Domain Names in Applications (IDNA) +===================================================== + +Support for the Internationalized Domain Names in +Applications (IDNA) protocol as specified in `RFC 5891 +`_. This is the latest version of +the protocol and is sometimes referred to as “IDNA 2008”. + +This library also provides support for Unicode Technical +Standard 46, `Unicode IDNA Compatibility Processing +`_. + +This acts as a suitable replacement for the “encodings.idna” +module that comes with the Python standard library, but which +only supports the older superseded IDNA specification (`RFC 3490 +`_). + +Basic functions are simply executed: + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + + +Installation +------------ + +This package is available for installation from PyPI: + +.. code-block:: bash + + $ python3 -m pip install idna + + +Usage +----- + +For typical usage, the ``encode`` and ``decode`` functions will take a +domain name argument and perform a conversion to A-labels or U-labels +respectively. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + +You may use the codec encoding and decoding methods using the +``idna.codec`` module: + +.. code-block:: pycon + + >>> import idna.codec + >>> print('домен.испытание'.encode('idna2008')) + b'xn--d1acufc.xn--80akhbyknj4f' + >>> print(b'xn--d1acufc.xn--80akhbyknj4f'.decode('idna2008')) + домен.испытание + +Conversions can be applied at a per-label basis using the ``ulabel`` or +``alabel`` functions if necessary: + +.. code-block:: pycon + + >>> idna.alabel('测试') + b'xn--0zwm56d' + +Compatibility Mapping (UTS #46) ++++++++++++++++++++++++++++++++ + +As described in `RFC 5895 `_, the +IDNA specification does not normalize input from different potential +ways a user may input a domain name. This functionality, known as +a “mapping”, is considered by the specification to be a local +user-interface issue distinct from IDNA conversion functionality. + +This library provides one such mapping that was developed by the +Unicode Consortium. Known as `Unicode IDNA Compatibility Processing +`_, it provides for both a regular +mapping for typical applications, as well as a transitional mapping to +help migrate from older IDNA 2003 applications. Strings are +preprocessed according to Section 4.4 “Preprocessing for IDNA2008” +prior to the IDNA operations. + +For example, “Königsgäßchen” is not a permissible label as *LATIN +CAPITAL LETTER K* is not allowed (nor are capital letters in general). +UTS 46 will convert this into lower case prior to applying the IDNA +conversion. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('Königsgäßchen') + ... + idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed + >>> idna.encode('Königsgäßchen', uts46=True) + b'xn--knigsgchen-b4a3dun' + >>> print(idna.decode('xn--knigsgchen-b4a3dun')) + königsgäßchen + +Transitional processing provides conversions to help transition from +the older 2003 standard to the current standard. For example, in the +original IDNA specification, the *LATIN SMALL LETTER SHARP S* (ß) was +converted into two *LATIN SMALL LETTER S* (ss), whereas in the current +IDNA specification this conversion is not performed. + +.. code-block:: pycon + + >>> idna.encode('Königsgäßchen', uts46=True, transitional=True) + 'xn--knigsgsschen-lcb0w' + +Implementers should use transitional processing with caution, only in +rare cases where conversion from legacy labels to current labels must be +performed (i.e. IDNA implementations that pre-date 2008). For typical +applications that just need to convert labels, transitional processing +is unlikely to be beneficial and could produce unexpected incompatible +results. + +``encodings.idna`` Compatibility +++++++++++++++++++++++++++++++++ + +Function calls from the Python built-in ``encodings.idna`` module are +mapped to their IDNA 2008 equivalents using the ``idna.compat`` module. +Simply substitute the ``import`` clause in your code to refer to the new +module name. + +Exceptions +---------- + +All errors raised during the conversion following the specification +should raise an exception derived from the ``idna.IDNAError`` base +class. + +More specific exceptions that may be generated as ``idna.IDNABidiError`` +when the error reflects an illegal combination of left-to-right and +right-to-left characters in a label; ``idna.InvalidCodepoint`` when +a specific codepoint is an illegal character in an IDN label (i.e. +INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is +illegal based on its positional context (i.e. it is CONTEXTO or CONTEXTJ +but the contextual requirements are not satisfied.) + +Building and Diagnostics +------------------------ + +The IDNA and UTS 46 functionality relies upon pre-calculated lookup +tables for performance. These tables are derived from computing against +eligibility criteria in the respective standards. These tables are +computed using the command-line script ``tools/idna-data``. + +This tool will fetch relevant codepoint data from the Unicode repository +and perform the required calculations to identify eligibility. There are +three main modes: + +* ``idna-data make-libdata``. Generates ``idnadata.py`` and + ``uts46data.py``, the pre-calculated lookup tables used for IDNA and + UTS 46 conversions. Implementers who wish to track this library against + a different Unicode version may use this tool to manually generate a + different version of the ``idnadata.py`` and ``uts46data.py`` files. + +* ``idna-data make-table``. Generate a table of the IDNA disposition + (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix + B.1 of RFC 5892 and the pre-computed tables published by `IANA + `_. + +* ``idna-data U+0061``. Prints debugging output on the various + properties associated with an individual Unicode codepoint (in this + case, U+0061), that are used to assess the IDNA and UTS 46 status of a + codepoint. This is helpful in debugging or analysis. + +The tool accepts a number of arguments, described using ``idna-data +-h``. Most notably, the ``--version`` argument allows the specification +of the version of Unicode to be used in computing the table data. For +example, ``idna-data --version 9.0.0 make-libdata`` will generate +library data against Unicode 9.0.0. + + +Additional Notes +---------------- + +* **Packages**. The latest tagged release version is published in the + `Python Package Index `_. + +* **Version support**. This library supports Python 3.6 and higher. + As this library serves as a low-level toolkit for a variety of + applications, many of which strive for broad compatibility with older + Python versions, there is no rush to remove older interpreter support. + Removing support for older versions should be well justified in that the + maintenance burden has become too high. + +* **Python 2**. Python 2 is supported by version 2.x of this library. + Use "idna<3" in your requirements file if you need this library for + a Python 2 application. Be advised that these versions are no longer + actively developed. + +* **Testing**. The library has a test suite based on each rule of the + IDNA specification, as well as tests that are provided as part of the + Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing + `_. + +* **Emoji**. It is an occasional request to support emoji domains in + this library. Encoding of symbols like emoji is expressly prohibited by + the technical standard IDNA 2008 and emoji domains are broadly phased + out across the domain industry due to associated security risks. For + now, applications that need to support these non-compliant labels + may wish to consider trying the encode/decode operation in this library + first, and then falling back to using `encodings.idna`. See `the Github + project `_ for more discussion. + diff --git a/venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD new file mode 100644 index 0000000..9cfce7f --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD @@ -0,0 +1,22 @@ +idna-3.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +idna-3.10.dist-info/LICENSE.md,sha256=pZ8LDvNjWHQQmkRhykT_enDVBpboFHZ7-vch1Mmw2w8,1541 +idna-3.10.dist-info/METADATA,sha256=URR5ZyDfQ1PCEGhkYoojqfi2Ra0tau2--lhwG4XSfjI,10158 +idna-3.10.dist-info/RECORD,, +idna-3.10.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868 +idna/__pycache__/__init__.cpython-312.pyc,, +idna/__pycache__/codec.cpython-312.pyc,, +idna/__pycache__/compat.cpython-312.pyc,, +idna/__pycache__/core.cpython-312.pyc,, +idna/__pycache__/idnadata.cpython-312.pyc,, +idna/__pycache__/intranges.cpython-312.pyc,, +idna/__pycache__/package_data.cpython-312.pyc,, +idna/__pycache__/uts46data.cpython-312.pyc,, +idna/codec.py,sha256=PEew3ItwzjW4hymbasnty2N2OXvNcgHB-JjrBuxHPYY,3422 +idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 +idna/core.py,sha256=YJYyAMnwiQEPjVC4-Fqu_p4CJ6yKKuDGmppBNQNQpFs,13239 +idna/idnadata.py,sha256=W30GcIGvtOWYwAjZj4ZjuouUutC6ffgNuyjJy7fZ-lo,78306 +idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 +idna/package_data.py,sha256=q59S3OXsc5VI8j6vSD0sGBMyk6zZ4vWFREE88yCJYKs,21 +idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +idna/uts46data.py,sha256=rt90K9J40gUSwppDPCrhjgi5AA6pWM65dEGRSf6rIhM,239289 diff --git a/venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/idna/__init__.py b/venv/lib/python3.12/site-packages/idna/__init__.py new file mode 100644 index 0000000..cfdc030 --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/__init__.py @@ -0,0 +1,45 @@ +from .core import ( + IDNABidiError, + IDNAError, + InvalidCodepoint, + InvalidCodepointContext, + alabel, + check_bidi, + check_hyphen_ok, + check_initial_combiner, + check_label, + check_nfc, + decode, + encode, + ulabel, + uts46_remap, + valid_contextj, + valid_contexto, + valid_label_length, + valid_string_length, +) +from .intranges import intranges_contain +from .package_data import __version__ + +__all__ = [ + "__version__", + "IDNABidiError", + "IDNAError", + "InvalidCodepoint", + "InvalidCodepointContext", + "alabel", + "check_bidi", + "check_hyphen_ok", + "check_initial_combiner", + "check_label", + "check_nfc", + "decode", + "encode", + "intranges_contain", + "ulabel", + "uts46_remap", + "valid_contextj", + "valid_contexto", + "valid_label_length", + "valid_string_length", +] diff --git a/venv/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da5a576e83e59dfe599c9ff4ca9a94f712325143 GIT binary patch literal 892 zcmbu7yN(kv6o&0dGRb6ezbyr#Ln6iQh>NHY66_+eO*$GkmNVl`yzyn^aRMoM3VJ%8 zgn~D)L`6k`gjk`Kw!)rSC>DtZ7vG%okNuzH%cpL)4cwT0{C1Yr0QlmQ-y^sVE{qG_ zfed7j0|5~f0SZJ7)kGcDMFTZNh(ggsP0>Ov5ur%5QCq|)79G?PUDOpl)DwNw7Xvg9 zLo^g4G=knQ;A1gClQORHshFV|1S^o$-$Qh;Z_LB5(3PH#Z1?nJ@$5Ov*bA+dwvkV( zaBwPjgtP2eWi(ez8hdb4IabopH^zp9lO^T0ovvxR!Aoan`&GQ&=W8ml+SpkoFv$!f z9H&YwnWWmrm0meSRU*$)8)h_hrEN%M_1#ue;;ktjJ;s^}lG|R{qBAQSIlqxBJF5Pd zD>0{XW!83FX@${DuCB#7v_rQ=P2`Fer5$0?i801Istcwh#`B4uxkJtU*Q4h#_2_#HJcb@4kFm$ZVKKjD>#5T8zv}$6gpK}ewQR_Ca*}Sy zisFnIQf|^VF(#a2`~h6Jroa_RUKQ>j5<|~PkrTssa-!0$pwbk{f|}P#Zwma<`2J^r^n%D*E?X96Efj fK?pB{F$^xj-}reC!1-rz_eXsi2XCADwp;NFqIvYj literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc b/venv/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..327cb3383043ae41619526f469840888b89d2bb7 GIT binary patch literal 4982 zcmd6qO>7&-6@X{S-R1H}A}Q*}qGVf=9mzy0(Xr~pkewh-=q5H~wTNTKWs$HncWIL* zm+b5^230C>0|AwhAg0>@B9I(hAO{-`ie3t&Knu918t6rg5{Ooy4g#tFZ~uzF)kVlx_|QmVy-MRm(o$GT+r##>BkV{!!%mJ^h{7eeHJrC{ zS-1iIF@?J<Y`ekM&20BgB zH`^!!jWOa#o(uRMpvhdoYFH1ec|-bfR!?NqXvz>?&t+4}102tQVAzj_<_;gBG(!zB znu?xLQidoiv5c%3qN194j_GqQc;jbNUtN6nn?HZ>&0l`^W(*r>BzwJ3orS_ObP*>% zY>{m;r&whR{H^eDf+EH(>|;ckUlhVNRxdQ`t!?!J)Ju6WAQ{5T(4CmU%TYZFy~56F zhDa4XN7Yz;wpsH6NPMnR)`@~e=FUGy2=(jr)k9!CCfna&uMtwPG{&xxzsnUkjmukg z^vP0zYt-qs&APbd1PSnShN$T@5z`;;JgI8AY&Ju6MIK>Y9yu3P+-`<7rKs1f2CpfpIPFGLHwXyIr4?1zf^&*~Aw$n=kyoR!^HKd=Mh(8LsBZ^Ti8H}$9-pVDp4k`F61p;( zMU%6N7EH)$G>8)(o66={ALdB%|R#1Ve z1D>i=Alk^##s!&?L9x}@AjtxN4)?yz=sBv!sDjHnnmWRGL|ePT5aJ0y8uftZSRK2p zT|AZ;2!76vrSAm3uFb{PL_6>fThj6_OsAbr*&$TuY#T~#_!h?T9sv>x&809EV zN9`?#P*3Jg(4)3BCEz z&FgP!qsdP2qLo2BDHpw?Yu<^ncj6kq>YZE?D+B%|*KMa4kXai0%}izIuA-~b>o4uQ za_n}W{~nf#$8P%uE4wC&v-i9{c*E^k;_vhgEgh-2dM+Qobo}G-t9>6$e&O148_4VF zEpb=uMZV(leE4!n`0cT>YsaO~x}Ee7uXmGe!^`8%Sa$Q|t^F&noxC+uK60vtdealW{~f5p zL$o0PRYZt6{u@<7EZS+K3R_iMFs1bUF{LfI&~baPbOU1oNSdoX(2)6teu2|*W3ZHL zGNGY?V5S+U0E>hsi^MvMY>Y)>8;hXKSOhhUMN$Wgnj~qpp*QKV1&i!W7I_vB=TRBD@_KLR5<-5_CJ1X#m7SuAN7YHXb<=T0+(Is2Wq)8mCX= zI~a~rT(%U)+6)EoD0?)GXb_DsJg0ziLieGV24Ohr?17_tYx01u)d-q*me^D>JvFdwjDRh4mj|MmLXzX!38vmbpY*;s`Rp(e%nsPTV^1SBP=o*`yJ^zJW$~%3-SF9jO)Lz%|TbxK8L)iKgG65N*@B z>()-1cJ%K>@IX<>@UP;xERqT@nGK`zdfeV`^7nc#?5e-C1r6yVCwE?Hcjw60mnI>W%EnF^$JnYvNeCY#i2nmx*@$-6eI zMqEjB9CVg+yeF9@3<+8K)N-R9ufYY)I%i0D&)K(k?}31g9svt>(_vAv(UWM!n&$CO zH|We=M-3NjVVKbiY(^VTpn+kAcwJ<7D9y05%hOR6E_DddRy*u4WJ{3EGaG*h_pvh? z4)ll_iMTZ-N@M3D@thjNt2>>8x)d7WOv0A8IhW=?w+&X@zPnEEnscb^9IAAA@49>6 zyKwoPOYgJ_Lz8#m*Eb5knp<*->qHVnHqn7WIt$JW3&dWcp3g$?MA>fQL2F(p_*jN2 zCL~!n#_mHn_6&!HEtW}V6Dh@HC4Q*ke~Cp~-%5mHs(shT}|3N0oWa4Xb@Jn*=o^N|`-}20r znUx(gtGBlYjA8~*gIRF3v literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc b/venv/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ad8e4385f4005c556f1d7b1dda8e2f1cff8110a GIT binary patch literal 896 zcmb7Cy=xRf6rb6z`%3%@h6IUhW3iZIV?w|p3c&~-m<37FTw&Pkyo+mgcb1vC$clxC zolUx=v<)`?7Zx@rc8g$PAt{7|vr6TgO)gmKz`XZ<^P73^&2Q%O_;{1xnEdpsyFv;1 zp}}Za=fUtP28VqHmxjM7}qiqhW7VxFB~Lwd2I$Q7?r|Nk0Jff{Q)5{V0s~LiLPi{yt>;eiHBad7<&r{GCN##tP-QFywYj2MDuaKk$LL7GH`FtNm$U7)VAWk*Sh(vl4${rIa(k#* zEWypf6mkK%n+vXZ#1oH}69HH4G*3Y53GAT|Twu!+*u>x6)<Br;kksSS$Moax_u z{I$8>x7MrHy|L0!MIL9nLO;3C-?g+NF5pZD{lKLul_>3JQFB>`zg$RpEjjGD= znHH5?r}dSTvt9!C#SA9UKSMr2GcYNo-^t8R;tm{2rw^6}1l`f{P`g20FKrzyzxVn# bZhyHxTah0pF35l$n0hUsN7nDkS9kaWn?A~# literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc b/venv/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ccccfd2539231150acda1cafbd7caffdb4f2ad3 GIT binary patch literal 16127 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 Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + return encode(data), len(data) + + def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return "", 0 + + return decode(data), len(data) + + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + labels = _unicode_dots_re.split(data) + trailing_dot = b"" + if labels: + if not labels[-1]: + trailing_dot = b"." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = b"." + + result = [] + size = 0 + for label in labels: + result.append(alabel(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result_bytes = b".".join(result) + trailing_dot + size += len(trailing_dot) + return result_bytes, size + + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return ("", 0) + + if not isinstance(data, str): + data = str(data, "ascii") + + labels = _unicode_dots_re.split(data) + trailing_dot = "" + if labels: + if not labels[-1]: + trailing_dot = "." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = "." + + result = [] + size = 0 + for label in labels: + result.append(ulabel(label)) + if size: + size += 1 + size += len(label) + + result_str = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result_str, size) + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + + +class StreamReader(Codec, codecs.StreamReader): + pass + + +def search_function(name: str) -> Optional[codecs.CodecInfo]: + if name != "idna2008": + return None + return codecs.CodecInfo( + name=name, + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) + + +codecs.register(search_function) diff --git a/venv/lib/python3.12/site-packages/idna/compat.py b/venv/lib/python3.12/site-packages/idna/compat.py new file mode 100644 index 0000000..1df9f2a --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/compat.py @@ -0,0 +1,15 @@ +from typing import Any, Union + +from .core import decode, encode + + +def ToASCII(label: str) -> bytes: + return encode(label) + + +def ToUnicode(label: Union[bytes, bytearray]) -> str: + return decode(label) + + +def nameprep(s: Any) -> None: + raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") diff --git a/venv/lib/python3.12/site-packages/idna/core.py b/venv/lib/python3.12/site-packages/idna/core.py new file mode 100644 index 0000000..9115f12 --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/core.py @@ -0,0 +1,437 @@ +import bisect +import re +import unicodedata +from typing import Optional, Union + +from . import idnadata +from .intranges import intranges_contain + +_virama_combining_class = 9 +_alabel_prefix = b"xn--" +_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") + + +class IDNAError(UnicodeError): + """Base exception for all IDNA-encoding related problems""" + + pass + + +class IDNABidiError(IDNAError): + """Exception when bidirectional requirements are not satisfied""" + + pass + + +class InvalidCodepoint(IDNAError): + """Exception when a disallowed or unallocated codepoint is used""" + + pass + + +class InvalidCodepointContext(IDNAError): + """Exception when the codepoint is not valid in the context it is used""" + + pass + + +def _combining_class(cp: int) -> int: + v = unicodedata.combining(chr(cp)) + if v == 0: + if not unicodedata.name(chr(cp)): + raise ValueError("Unknown character in unicodedata") + return v + + +def _is_script(cp: str, script: str) -> bool: + return intranges_contain(ord(cp), idnadata.scripts[script]) + + +def _punycode(s: str) -> bytes: + return s.encode("punycode") + + +def _unot(s: int) -> str: + return "U+{:04X}".format(s) + + +def valid_label_length(label: Union[bytes, str]) -> bool: + if len(label) > 63: + return False + return True + + +def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool: + if len(label) > (254 if trailing_dot else 253): + return False + return True + + +def check_bidi(label: str, check_ltr: bool = False) -> bool: + # Bidi rules should only be applied if string contains RTL characters + bidi_label = False + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + if direction == "": + # String likely comes from a newer version of Unicode + raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx)) + if direction in ["R", "AL", "AN"]: + bidi_label = True + if not bidi_label and not check_ltr: + return True + + # Bidi rule 1 + direction = unicodedata.bidirectional(label[0]) + if direction in ["R", "AL"]: + rtl = True + elif direction == "L": + rtl = False + else: + raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label))) + + valid_ending = False + number_type: Optional[str] = None + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if direction not in [ + "R", + "AL", + "AN", + "EN", + "ES", + "CS", + "ET", + "ON", + "BN", + "NSM", + ]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx)) + # Bidi rule 3 + if direction in ["R", "AL", "EN", "AN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + # Bidi rule 4 + if direction in ["AN", "EN"]: + if not number_type: + number_type = direction + else: + if number_type != direction: + raise IDNABidiError("Can not mix numeral types in a right-to-left label") + else: + # Bidi rule 5 + if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx)) + # Bidi rule 6 + if direction in ["L", "EN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + + if not valid_ending: + raise IDNABidiError("Label ends with illegal codepoint directionality") + + return True + + +def check_initial_combiner(label: str) -> bool: + if unicodedata.category(label[0])[0] == "M": + raise IDNAError("Label begins with an illegal combining character") + return True + + +def check_hyphen_ok(label: str) -> bool: + if label[2:4] == "--": + raise IDNAError("Label has disallowed hyphens in 3rd and 4th position") + if label[0] == "-" or label[-1] == "-": + raise IDNAError("Label must not start or end with a hyphen") + return True + + +def check_nfc(label: str) -> None: + if unicodedata.normalize("NFC", label) != label: + raise IDNAError("Label must be in Normalization Form C") + + +def valid_contextj(label: str, pos: int) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x200C: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + + ok = False + for i in range(pos - 1, -1, -1): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("L"), ord("D")]: + ok = True + break + else: + break + + if not ok: + return False + + ok = False + for i in range(pos + 1, len(label)): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("R"), ord("D")]: + ok = True + break + else: + break + return ok + + if cp_value == 0x200D: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + return False + + else: + return False + + +def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x00B7: + if 0 < pos < len(label) - 1: + if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C: + return True + return False + + elif cp_value == 0x0375: + if pos < len(label) - 1 and len(label) > 1: + return _is_script(label[pos + 1], "Greek") + return False + + elif cp_value == 0x05F3 or cp_value == 0x05F4: + if pos > 0: + return _is_script(label[pos - 1], "Hebrew") + return False + + elif cp_value == 0x30FB: + for cp in label: + if cp == "\u30fb": + continue + if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"): + return True + return False + + elif 0x660 <= cp_value <= 0x669: + for cp in label: + if 0x6F0 <= ord(cp) <= 0x06F9: + return False + return True + + elif 0x6F0 <= cp_value <= 0x6F9: + for cp in label: + if 0x660 <= ord(cp) <= 0x0669: + return False + return True + + return False + + +def check_label(label: Union[str, bytes, bytearray]) -> None: + if isinstance(label, (bytes, bytearray)): + label = label.decode("utf-8") + if len(label) == 0: + raise IDNAError("Empty Label") + + check_nfc(label) + check_hyphen_ok(label) + check_initial_combiner(label) + + for pos, cp in enumerate(label): + cp_value = ord(cp) + if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]): + continue + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]): + try: + if not valid_contextj(label, pos): + raise InvalidCodepointContext( + "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + except ValueError: + raise IDNAError( + "Unknown codepoint adjacent to joiner {} at position {} in {}".format( + _unot(cp_value), pos + 1, repr(label) + ) + ) + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]): + if not valid_contexto(label, pos): + raise InvalidCodepointContext( + "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + else: + raise InvalidCodepoint( + "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label)) + ) + + check_bidi(label) + + +def alabel(label: str) -> bytes: + try: + label_bytes = label.encode("ascii") + ulabel(label_bytes) + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + return label_bytes + except UnicodeEncodeError: + pass + + check_label(label) + label_bytes = _alabel_prefix + _punycode(label) + + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + + return label_bytes + + +def ulabel(label: Union[str, bytes, bytearray]) -> str: + if not isinstance(label, (bytes, bytearray)): + try: + label_bytes = label.encode("ascii") + except UnicodeEncodeError: + check_label(label) + return label + else: + label_bytes = label + + label_bytes = label_bytes.lower() + if label_bytes.startswith(_alabel_prefix): + label_bytes = label_bytes[len(_alabel_prefix) :] + if not label_bytes: + raise IDNAError("Malformed A-label, no Punycode eligible content found") + if label_bytes.decode("ascii")[-1] == "-": + raise IDNAError("A-label must not end with a hyphen") + else: + check_label(label_bytes) + return label_bytes.decode("ascii") + + try: + label = label_bytes.decode("punycode") + except UnicodeError: + raise IDNAError("Invalid A-label") + check_label(label) + return label + + +def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str: + """Re-map the characters in the string according to UTS46 processing.""" + from .uts46data import uts46data + + output = "" + + for pos, char in enumerate(domain): + code_point = ord(char) + try: + uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + status = uts46row[1] + replacement: Optional[str] = None + if len(uts46row) == 3: + replacement = uts46row[2] + if ( + status == "V" + or (status == "D" and not transitional) + or (status == "3" and not std3_rules and replacement is None) + ): + output += char + elif replacement is not None and ( + status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional) + ): + output += replacement + elif status != "I": + raise IndexError() + except IndexError: + raise InvalidCodepoint( + "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain)) + ) + + return unicodedata.normalize("NFC", output) + + +def encode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, + transitional: bool = False, +) -> bytes: + if not isinstance(s, str): + try: + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("should pass a unicode string to the function rather than a byte string.") + if uts46: + s = uts46_remap(s, std3_rules, transitional) + trailing_dot = False + result = [] + if strict: + labels = s.split(".") + else: + labels = _unicode_dots_re.split(s) + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if labels[-1] == "": + del labels[-1] + trailing_dot = True + for label in labels: + s = alabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append(b"") + s = b".".join(result) + if not valid_string_length(s, trailing_dot): + raise IDNAError("Domain too long") + return s + + +def decode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, +) -> str: + try: + if not isinstance(s, str): + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("Invalid ASCII in A-label") + if uts46: + s = uts46_remap(s, std3_rules, False) + trailing_dot = False + result = [] + if not strict: + labels = _unicode_dots_re.split(s) + else: + labels = s.split(".") + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if not labels[-1]: + del labels[-1] + trailing_dot = True + for label in labels: + s = ulabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append("") + return ".".join(result) diff --git a/venv/lib/python3.12/site-packages/idna/idnadata.py b/venv/lib/python3.12/site-packages/idna/idnadata.py new file mode 100644 index 0000000..4be6004 --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/idnadata.py @@ -0,0 +1,4243 @@ +# This file is automatically generated by tools/idna-data + +__version__ = "15.1.0" +scripts = { + "Greek": ( + 0x37000000374, + 0x37500000378, + 0x37A0000037E, + 0x37F00000380, + 0x38400000385, + 0x38600000387, + 0x3880000038B, + 0x38C0000038D, + 0x38E000003A2, + 0x3A3000003E2, + 0x3F000000400, + 0x1D2600001D2B, + 0x1D5D00001D62, + 0x1D6600001D6B, + 0x1DBF00001DC0, + 0x1F0000001F16, + 0x1F1800001F1E, + 0x1F2000001F46, + 0x1F4800001F4E, + 0x1F5000001F58, + 0x1F5900001F5A, + 0x1F5B00001F5C, + 0x1F5D00001F5E, + 0x1F5F00001F7E, + 0x1F8000001FB5, + 0x1FB600001FC5, + 0x1FC600001FD4, + 0x1FD600001FDC, + 0x1FDD00001FF0, + 0x1FF200001FF5, + 0x1FF600001FFF, + 0x212600002127, + 0xAB650000AB66, + 0x101400001018F, + 0x101A0000101A1, + 0x1D2000001D246, + ), + "Han": ( + 0x2E8000002E9A, + 0x2E9B00002EF4, + 0x2F0000002FD6, + 0x300500003006, + 0x300700003008, + 0x30210000302A, + 0x30380000303C, + 0x340000004DC0, + 0x4E000000A000, + 0xF9000000FA6E, + 0xFA700000FADA, + 0x16FE200016FE4, + 0x16FF000016FF2, + 0x200000002A6E0, + 0x2A7000002B73A, + 0x2B7400002B81E, + 0x2B8200002CEA2, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x2F8000002FA1E, + 0x300000003134B, + 0x31350000323B0, + ), + "Hebrew": ( + 0x591000005C8, + 0x5D0000005EB, + 0x5EF000005F5, + 0xFB1D0000FB37, + 0xFB380000FB3D, + 0xFB3E0000FB3F, + 0xFB400000FB42, + 0xFB430000FB45, + 0xFB460000FB50, + ), + "Hiragana": ( + 0x304100003097, + 0x309D000030A0, + 0x1B0010001B120, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1F2000001F201, + ), + "Katakana": ( + 0x30A1000030FB, + 0x30FD00003100, + 0x31F000003200, + 0x32D0000032FF, + 0x330000003358, + 0xFF660000FF70, + 0xFF710000FF9E, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B001, + 0x1B1200001B123, + 0x1B1550001B156, + 0x1B1640001B168, + ), +} +joining_types = { + 0xAD: 84, + 0x300: 84, + 0x301: 84, + 0x302: 84, + 0x303: 84, + 0x304: 84, + 0x305: 84, + 0x306: 84, + 0x307: 84, + 0x308: 84, + 0x309: 84, + 0x30A: 84, + 0x30B: 84, + 0x30C: 84, + 0x30D: 84, + 0x30E: 84, + 0x30F: 84, + 0x310: 84, + 0x311: 84, + 0x312: 84, + 0x313: 84, + 0x314: 84, + 0x315: 84, + 0x316: 84, + 0x317: 84, + 0x318: 84, + 0x319: 84, + 0x31A: 84, + 0x31B: 84, + 0x31C: 84, + 0x31D: 84, + 0x31E: 84, + 0x31F: 84, + 0x320: 84, + 0x321: 84, + 0x322: 84, + 0x323: 84, + 0x324: 84, + 0x325: 84, + 0x326: 84, + 0x327: 84, + 0x328: 84, + 0x329: 84, + 0x32A: 84, + 0x32B: 84, + 0x32C: 84, + 0x32D: 84, + 0x32E: 84, + 0x32F: 84, + 0x330: 84, + 0x331: 84, + 0x332: 84, + 0x333: 84, + 0x334: 84, + 0x335: 84, + 0x336: 84, + 0x337: 84, + 0x338: 84, + 0x339: 84, + 0x33A: 84, + 0x33B: 84, + 0x33C: 84, + 0x33D: 84, + 0x33E: 84, + 0x33F: 84, + 0x340: 84, + 0x341: 84, + 0x342: 84, + 0x343: 84, + 0x344: 84, + 0x345: 84, + 0x346: 84, + 0x347: 84, + 0x348: 84, + 0x349: 84, + 0x34A: 84, + 0x34B: 84, + 0x34C: 84, + 0x34D: 84, + 0x34E: 84, + 0x34F: 84, + 0x350: 84, + 0x351: 84, + 0x352: 84, + 0x353: 84, + 0x354: 84, + 0x355: 84, + 0x356: 84, + 0x357: 84, + 0x358: 84, + 0x359: 84, + 0x35A: 84, + 0x35B: 84, + 0x35C: 84, + 0x35D: 84, + 0x35E: 84, + 0x35F: 84, + 0x360: 84, + 0x361: 84, + 0x362: 84, + 0x363: 84, + 0x364: 84, + 0x365: 84, + 0x366: 84, + 0x367: 84, + 0x368: 84, + 0x369: 84, + 0x36A: 84, + 0x36B: 84, + 0x36C: 84, + 0x36D: 84, + 0x36E: 84, + 0x36F: 84, + 0x483: 84, + 0x484: 84, + 0x485: 84, + 0x486: 84, + 0x487: 84, + 0x488: 84, + 0x489: 84, + 0x591: 84, + 0x592: 84, + 0x593: 84, + 0x594: 84, + 0x595: 84, + 0x596: 84, + 0x597: 84, + 0x598: 84, + 0x599: 84, + 0x59A: 84, + 0x59B: 84, + 0x59C: 84, + 0x59D: 84, + 0x59E: 84, + 0x59F: 84, + 0x5A0: 84, + 0x5A1: 84, + 0x5A2: 84, + 0x5A3: 84, + 0x5A4: 84, + 0x5A5: 84, + 0x5A6: 84, + 0x5A7: 84, + 0x5A8: 84, + 0x5A9: 84, + 0x5AA: 84, + 0x5AB: 84, + 0x5AC: 84, + 0x5AD: 84, + 0x5AE: 84, + 0x5AF: 84, + 0x5B0: 84, + 0x5B1: 84, + 0x5B2: 84, + 0x5B3: 84, + 0x5B4: 84, + 0x5B5: 84, + 0x5B6: 84, + 0x5B7: 84, + 0x5B8: 84, + 0x5B9: 84, + 0x5BA: 84, + 0x5BB: 84, + 0x5BC: 84, + 0x5BD: 84, + 0x5BF: 84, + 0x5C1: 84, + 0x5C2: 84, + 0x5C4: 84, + 0x5C5: 84, + 0x5C7: 84, + 0x610: 84, + 0x611: 84, + 0x612: 84, + 0x613: 84, + 0x614: 84, + 0x615: 84, + 0x616: 84, + 0x617: 84, + 0x618: 84, + 0x619: 84, + 0x61A: 84, + 0x61C: 84, + 0x620: 68, + 0x622: 82, + 0x623: 82, + 0x624: 82, + 0x625: 82, + 0x626: 68, + 0x627: 82, + 0x628: 68, + 0x629: 82, + 0x62A: 68, + 0x62B: 68, + 0x62C: 68, + 0x62D: 68, + 0x62E: 68, + 0x62F: 82, + 0x630: 82, + 0x631: 82, + 0x632: 82, + 0x633: 68, + 0x634: 68, + 0x635: 68, + 0x636: 68, + 0x637: 68, + 0x638: 68, + 0x639: 68, + 0x63A: 68, + 0x63B: 68, + 0x63C: 68, + 0x63D: 68, + 0x63E: 68, + 0x63F: 68, + 0x640: 67, + 0x641: 68, + 0x642: 68, + 0x643: 68, + 0x644: 68, + 0x645: 68, + 0x646: 68, + 0x647: 68, + 0x648: 82, + 0x649: 68, + 0x64A: 68, + 0x64B: 84, + 0x64C: 84, + 0x64D: 84, + 0x64E: 84, + 0x64F: 84, + 0x650: 84, + 0x651: 84, + 0x652: 84, + 0x653: 84, + 0x654: 84, + 0x655: 84, + 0x656: 84, + 0x657: 84, + 0x658: 84, + 0x659: 84, + 0x65A: 84, + 0x65B: 84, + 0x65C: 84, + 0x65D: 84, + 0x65E: 84, + 0x65F: 84, + 0x66E: 68, + 0x66F: 68, + 0x670: 84, + 0x671: 82, + 0x672: 82, + 0x673: 82, + 0x675: 82, + 0x676: 82, + 0x677: 82, + 0x678: 68, + 0x679: 68, + 0x67A: 68, + 0x67B: 68, + 0x67C: 68, + 0x67D: 68, + 0x67E: 68, + 0x67F: 68, + 0x680: 68, + 0x681: 68, + 0x682: 68, + 0x683: 68, + 0x684: 68, + 0x685: 68, + 0x686: 68, + 0x687: 68, + 0x688: 82, + 0x689: 82, + 0x68A: 82, + 0x68B: 82, + 0x68C: 82, + 0x68D: 82, + 0x68E: 82, + 0x68F: 82, + 0x690: 82, + 0x691: 82, + 0x692: 82, + 0x693: 82, + 0x694: 82, + 0x695: 82, + 0x696: 82, + 0x697: 82, + 0x698: 82, + 0x699: 82, + 0x69A: 68, + 0x69B: 68, + 0x69C: 68, + 0x69D: 68, + 0x69E: 68, + 0x69F: 68, + 0x6A0: 68, + 0x6A1: 68, + 0x6A2: 68, + 0x6A3: 68, + 0x6A4: 68, + 0x6A5: 68, + 0x6A6: 68, + 0x6A7: 68, + 0x6A8: 68, + 0x6A9: 68, + 0x6AA: 68, + 0x6AB: 68, + 0x6AC: 68, + 0x6AD: 68, + 0x6AE: 68, + 0x6AF: 68, + 0x6B0: 68, + 0x6B1: 68, + 0x6B2: 68, + 0x6B3: 68, + 0x6B4: 68, + 0x6B5: 68, + 0x6B6: 68, + 0x6B7: 68, + 0x6B8: 68, + 0x6B9: 68, + 0x6BA: 68, + 0x6BB: 68, + 0x6BC: 68, + 0x6BD: 68, + 0x6BE: 68, + 0x6BF: 68, + 0x6C0: 82, + 0x6C1: 68, + 0x6C2: 68, + 0x6C3: 82, + 0x6C4: 82, + 0x6C5: 82, + 0x6C6: 82, + 0x6C7: 82, + 0x6C8: 82, + 0x6C9: 82, + 0x6CA: 82, + 0x6CB: 82, + 0x6CC: 68, + 0x6CD: 82, + 0x6CE: 68, + 0x6CF: 82, + 0x6D0: 68, + 0x6D1: 68, + 0x6D2: 82, + 0x6D3: 82, + 0x6D5: 82, + 0x6D6: 84, + 0x6D7: 84, + 0x6D8: 84, + 0x6D9: 84, + 0x6DA: 84, + 0x6DB: 84, + 0x6DC: 84, + 0x6DF: 84, + 0x6E0: 84, + 0x6E1: 84, + 0x6E2: 84, + 0x6E3: 84, + 0x6E4: 84, + 0x6E7: 84, + 0x6E8: 84, + 0x6EA: 84, + 0x6EB: 84, + 0x6EC: 84, + 0x6ED: 84, + 0x6EE: 82, + 0x6EF: 82, + 0x6FA: 68, + 0x6FB: 68, + 0x6FC: 68, + 0x6FF: 68, + 0x70F: 84, + 0x710: 82, + 0x711: 84, + 0x712: 68, + 0x713: 68, + 0x714: 68, + 0x715: 82, + 0x716: 82, + 0x717: 82, + 0x718: 82, + 0x719: 82, + 0x71A: 68, + 0x71B: 68, + 0x71C: 68, + 0x71D: 68, + 0x71E: 82, + 0x71F: 68, + 0x720: 68, + 0x721: 68, + 0x722: 68, + 0x723: 68, + 0x724: 68, + 0x725: 68, + 0x726: 68, + 0x727: 68, + 0x728: 82, + 0x729: 68, + 0x72A: 82, + 0x72B: 68, + 0x72C: 82, + 0x72D: 68, + 0x72E: 68, + 0x72F: 82, + 0x730: 84, + 0x731: 84, + 0x732: 84, + 0x733: 84, + 0x734: 84, + 0x735: 84, + 0x736: 84, + 0x737: 84, + 0x738: 84, + 0x739: 84, + 0x73A: 84, + 0x73B: 84, + 0x73C: 84, + 0x73D: 84, + 0x73E: 84, + 0x73F: 84, + 0x740: 84, + 0x741: 84, + 0x742: 84, + 0x743: 84, + 0x744: 84, + 0x745: 84, + 0x746: 84, + 0x747: 84, + 0x748: 84, + 0x749: 84, + 0x74A: 84, + 0x74D: 82, + 0x74E: 68, + 0x74F: 68, + 0x750: 68, + 0x751: 68, + 0x752: 68, + 0x753: 68, + 0x754: 68, + 0x755: 68, + 0x756: 68, + 0x757: 68, + 0x758: 68, + 0x759: 82, + 0x75A: 82, + 0x75B: 82, + 0x75C: 68, + 0x75D: 68, + 0x75E: 68, + 0x75F: 68, + 0x760: 68, + 0x761: 68, + 0x762: 68, + 0x763: 68, + 0x764: 68, + 0x765: 68, + 0x766: 68, + 0x767: 68, + 0x768: 68, + 0x769: 68, + 0x76A: 68, + 0x76B: 82, + 0x76C: 82, + 0x76D: 68, + 0x76E: 68, + 0x76F: 68, + 0x770: 68, + 0x771: 82, + 0x772: 68, + 0x773: 82, + 0x774: 82, + 0x775: 68, + 0x776: 68, + 0x777: 68, + 0x778: 82, + 0x779: 82, + 0x77A: 68, + 0x77B: 68, + 0x77C: 68, + 0x77D: 68, + 0x77E: 68, + 0x77F: 68, + 0x7A6: 84, + 0x7A7: 84, + 0x7A8: 84, + 0x7A9: 84, + 0x7AA: 84, + 0x7AB: 84, + 0x7AC: 84, + 0x7AD: 84, + 0x7AE: 84, + 0x7AF: 84, + 0x7B0: 84, + 0x7CA: 68, + 0x7CB: 68, + 0x7CC: 68, + 0x7CD: 68, + 0x7CE: 68, + 0x7CF: 68, + 0x7D0: 68, + 0x7D1: 68, + 0x7D2: 68, + 0x7D3: 68, + 0x7D4: 68, + 0x7D5: 68, + 0x7D6: 68, + 0x7D7: 68, + 0x7D8: 68, + 0x7D9: 68, + 0x7DA: 68, + 0x7DB: 68, + 0x7DC: 68, + 0x7DD: 68, + 0x7DE: 68, + 0x7DF: 68, + 0x7E0: 68, + 0x7E1: 68, + 0x7E2: 68, + 0x7E3: 68, + 0x7E4: 68, + 0x7E5: 68, + 0x7E6: 68, + 0x7E7: 68, + 0x7E8: 68, + 0x7E9: 68, + 0x7EA: 68, + 0x7EB: 84, + 0x7EC: 84, + 0x7ED: 84, + 0x7EE: 84, + 0x7EF: 84, + 0x7F0: 84, + 0x7F1: 84, + 0x7F2: 84, + 0x7F3: 84, + 0x7FA: 67, + 0x7FD: 84, + 0x816: 84, + 0x817: 84, + 0x818: 84, + 0x819: 84, + 0x81B: 84, + 0x81C: 84, + 0x81D: 84, + 0x81E: 84, + 0x81F: 84, + 0x820: 84, + 0x821: 84, + 0x822: 84, + 0x823: 84, + 0x825: 84, + 0x826: 84, + 0x827: 84, + 0x829: 84, + 0x82A: 84, + 0x82B: 84, + 0x82C: 84, + 0x82D: 84, + 0x840: 82, + 0x841: 68, + 0x842: 68, + 0x843: 68, + 0x844: 68, + 0x845: 68, + 0x846: 82, + 0x847: 82, + 0x848: 68, + 0x849: 82, + 0x84A: 68, + 0x84B: 68, + 0x84C: 68, + 0x84D: 68, + 0x84E: 68, + 0x84F: 68, + 0x850: 68, + 0x851: 68, + 0x852: 68, + 0x853: 68, + 0x854: 82, + 0x855: 68, + 0x856: 82, + 0x857: 82, + 0x858: 82, + 0x859: 84, + 0x85A: 84, + 0x85B: 84, + 0x860: 68, + 0x862: 68, + 0x863: 68, + 0x864: 68, + 0x865: 68, + 0x867: 82, + 0x868: 68, + 0x869: 82, + 0x86A: 82, + 0x870: 82, + 0x871: 82, + 0x872: 82, + 0x873: 82, + 0x874: 82, + 0x875: 82, + 0x876: 82, + 0x877: 82, + 0x878: 82, + 0x879: 82, + 0x87A: 82, + 0x87B: 82, + 0x87C: 82, + 0x87D: 82, + 0x87E: 82, + 0x87F: 82, + 0x880: 82, + 0x881: 82, + 0x882: 82, + 0x883: 67, + 0x884: 67, + 0x885: 67, + 0x886: 68, + 0x889: 68, + 0x88A: 68, + 0x88B: 68, + 0x88C: 68, + 0x88D: 68, + 0x88E: 82, + 0x898: 84, + 0x899: 84, + 0x89A: 84, + 0x89B: 84, + 0x89C: 84, + 0x89D: 84, + 0x89E: 84, + 0x89F: 84, + 0x8A0: 68, + 0x8A1: 68, + 0x8A2: 68, + 0x8A3: 68, + 0x8A4: 68, + 0x8A5: 68, + 0x8A6: 68, + 0x8A7: 68, + 0x8A8: 68, + 0x8A9: 68, + 0x8AA: 82, + 0x8AB: 82, + 0x8AC: 82, + 0x8AE: 82, + 0x8AF: 68, + 0x8B0: 68, + 0x8B1: 82, + 0x8B2: 82, + 0x8B3: 68, + 0x8B4: 68, + 0x8B5: 68, + 0x8B6: 68, + 0x8B7: 68, + 0x8B8: 68, + 0x8B9: 82, + 0x8BA: 68, + 0x8BB: 68, + 0x8BC: 68, + 0x8BD: 68, + 0x8BE: 68, + 0x8BF: 68, + 0x8C0: 68, + 0x8C1: 68, + 0x8C2: 68, + 0x8C3: 68, + 0x8C4: 68, + 0x8C5: 68, + 0x8C6: 68, + 0x8C7: 68, + 0x8C8: 68, + 0x8CA: 84, + 0x8CB: 84, + 0x8CC: 84, + 0x8CD: 84, + 0x8CE: 84, + 0x8CF: 84, + 0x8D0: 84, + 0x8D1: 84, + 0x8D2: 84, + 0x8D3: 84, + 0x8D4: 84, + 0x8D5: 84, + 0x8D6: 84, + 0x8D7: 84, + 0x8D8: 84, + 0x8D9: 84, + 0x8DA: 84, + 0x8DB: 84, + 0x8DC: 84, + 0x8DD: 84, + 0x8DE: 84, + 0x8DF: 84, + 0x8E0: 84, + 0x8E1: 84, + 0x8E3: 84, + 0x8E4: 84, + 0x8E5: 84, + 0x8E6: 84, + 0x8E7: 84, + 0x8E8: 84, + 0x8E9: 84, + 0x8EA: 84, + 0x8EB: 84, + 0x8EC: 84, + 0x8ED: 84, + 0x8EE: 84, + 0x8EF: 84, + 0x8F0: 84, + 0x8F1: 84, + 0x8F2: 84, + 0x8F3: 84, + 0x8F4: 84, + 0x8F5: 84, + 0x8F6: 84, + 0x8F7: 84, + 0x8F8: 84, + 0x8F9: 84, + 0x8FA: 84, + 0x8FB: 84, + 0x8FC: 84, + 0x8FD: 84, + 0x8FE: 84, + 0x8FF: 84, + 0x900: 84, + 0x901: 84, + 0x902: 84, + 0x93A: 84, + 0x93C: 84, + 0x941: 84, + 0x942: 84, + 0x943: 84, + 0x944: 84, + 0x945: 84, + 0x946: 84, + 0x947: 84, + 0x948: 84, + 0x94D: 84, + 0x951: 84, + 0x952: 84, + 0x953: 84, + 0x954: 84, + 0x955: 84, + 0x956: 84, + 0x957: 84, + 0x962: 84, + 0x963: 84, + 0x981: 84, + 0x9BC: 84, + 0x9C1: 84, + 0x9C2: 84, + 0x9C3: 84, + 0x9C4: 84, + 0x9CD: 84, + 0x9E2: 84, + 0x9E3: 84, + 0x9FE: 84, + 0xA01: 84, + 0xA02: 84, + 0xA3C: 84, + 0xA41: 84, + 0xA42: 84, + 0xA47: 84, + 0xA48: 84, + 0xA4B: 84, + 0xA4C: 84, + 0xA4D: 84, + 0xA51: 84, + 0xA70: 84, + 0xA71: 84, + 0xA75: 84, + 0xA81: 84, + 0xA82: 84, + 0xABC: 84, + 0xAC1: 84, + 0xAC2: 84, + 0xAC3: 84, + 0xAC4: 84, + 0xAC5: 84, + 0xAC7: 84, + 0xAC8: 84, + 0xACD: 84, + 0xAE2: 84, + 0xAE3: 84, + 0xAFA: 84, + 0xAFB: 84, + 0xAFC: 84, + 0xAFD: 84, + 0xAFE: 84, + 0xAFF: 84, + 0xB01: 84, + 0xB3C: 84, + 0xB3F: 84, + 0xB41: 84, + 0xB42: 84, + 0xB43: 84, + 0xB44: 84, + 0xB4D: 84, + 0xB55: 84, + 0xB56: 84, + 0xB62: 84, + 0xB63: 84, + 0xB82: 84, + 0xBC0: 84, + 0xBCD: 84, + 0xC00: 84, + 0xC04: 84, + 0xC3C: 84, + 0xC3E: 84, + 0xC3F: 84, + 0xC40: 84, + 0xC46: 84, + 0xC47: 84, + 0xC48: 84, + 0xC4A: 84, + 0xC4B: 84, + 0xC4C: 84, + 0xC4D: 84, + 0xC55: 84, + 0xC56: 84, + 0xC62: 84, + 0xC63: 84, + 0xC81: 84, + 0xCBC: 84, + 0xCBF: 84, + 0xCC6: 84, + 0xCCC: 84, + 0xCCD: 84, + 0xCE2: 84, + 0xCE3: 84, + 0xD00: 84, + 0xD01: 84, + 0xD3B: 84, + 0xD3C: 84, + 0xD41: 84, + 0xD42: 84, + 0xD43: 84, + 0xD44: 84, + 0xD4D: 84, + 0xD62: 84, + 0xD63: 84, + 0xD81: 84, + 0xDCA: 84, + 0xDD2: 84, + 0xDD3: 84, + 0xDD4: 84, + 0xDD6: 84, + 0xE31: 84, + 0xE34: 84, + 0xE35: 84, + 0xE36: 84, + 0xE37: 84, + 0xE38: 84, + 0xE39: 84, + 0xE3A: 84, + 0xE47: 84, + 0xE48: 84, + 0xE49: 84, + 0xE4A: 84, + 0xE4B: 84, + 0xE4C: 84, + 0xE4D: 84, + 0xE4E: 84, + 0xEB1: 84, + 0xEB4: 84, + 0xEB5: 84, + 0xEB6: 84, + 0xEB7: 84, + 0xEB8: 84, + 0xEB9: 84, + 0xEBA: 84, + 0xEBB: 84, + 0xEBC: 84, + 0xEC8: 84, + 0xEC9: 84, + 0xECA: 84, + 0xECB: 84, + 0xECC: 84, + 0xECD: 84, + 0xECE: 84, + 0xF18: 84, + 0xF19: 84, + 0xF35: 84, + 0xF37: 84, + 0xF39: 84, + 0xF71: 84, + 0xF72: 84, + 0xF73: 84, + 0xF74: 84, + 0xF75: 84, + 0xF76: 84, + 0xF77: 84, + 0xF78: 84, + 0xF79: 84, + 0xF7A: 84, + 0xF7B: 84, + 0xF7C: 84, + 0xF7D: 84, + 0xF7E: 84, + 0xF80: 84, + 0xF81: 84, + 0xF82: 84, + 0xF83: 84, + 0xF84: 84, + 0xF86: 84, + 0xF87: 84, + 0xF8D: 84, + 0xF8E: 84, + 0xF8F: 84, + 0xF90: 84, + 0xF91: 84, + 0xF92: 84, + 0xF93: 84, + 0xF94: 84, + 0xF95: 84, + 0xF96: 84, + 0xF97: 84, + 0xF99: 84, + 0xF9A: 84, + 0xF9B: 84, + 0xF9C: 84, + 0xF9D: 84, + 0xF9E: 84, + 0xF9F: 84, + 0xFA0: 84, + 0xFA1: 84, + 0xFA2: 84, + 0xFA3: 84, + 0xFA4: 84, + 0xFA5: 84, + 0xFA6: 84, + 0xFA7: 84, + 0xFA8: 84, + 0xFA9: 84, + 0xFAA: 84, + 0xFAB: 84, + 0xFAC: 84, + 0xFAD: 84, + 0xFAE: 84, + 0xFAF: 84, + 0xFB0: 84, + 0xFB1: 84, + 0xFB2: 84, + 0xFB3: 84, + 0xFB4: 84, + 0xFB5: 84, + 0xFB6: 84, + 0xFB7: 84, + 0xFB8: 84, + 0xFB9: 84, + 0xFBA: 84, + 0xFBB: 84, + 0xFBC: 84, + 0xFC6: 84, + 0x102D: 84, + 0x102E: 84, + 0x102F: 84, + 0x1030: 84, + 0x1032: 84, + 0x1033: 84, + 0x1034: 84, + 0x1035: 84, + 0x1036: 84, + 0x1037: 84, + 0x1039: 84, + 0x103A: 84, + 0x103D: 84, + 0x103E: 84, + 0x1058: 84, + 0x1059: 84, + 0x105E: 84, + 0x105F: 84, + 0x1060: 84, + 0x1071: 84, + 0x1072: 84, + 0x1073: 84, + 0x1074: 84, + 0x1082: 84, + 0x1085: 84, + 0x1086: 84, + 0x108D: 84, + 0x109D: 84, + 0x135D: 84, + 0x135E: 84, + 0x135F: 84, + 0x1712: 84, + 0x1713: 84, + 0x1714: 84, + 0x1732: 84, + 0x1733: 84, + 0x1752: 84, + 0x1753: 84, + 0x1772: 84, + 0x1773: 84, + 0x17B4: 84, + 0x17B5: 84, + 0x17B7: 84, + 0x17B8: 84, + 0x17B9: 84, + 0x17BA: 84, + 0x17BB: 84, + 0x17BC: 84, + 0x17BD: 84, + 0x17C6: 84, + 0x17C9: 84, + 0x17CA: 84, + 0x17CB: 84, + 0x17CC: 84, + 0x17CD: 84, + 0x17CE: 84, + 0x17CF: 84, + 0x17D0: 84, + 0x17D1: 84, + 0x17D2: 84, + 0x17D3: 84, + 0x17DD: 84, + 0x1807: 68, + 0x180A: 67, + 0x180B: 84, + 0x180C: 84, + 0x180D: 84, + 0x180F: 84, + 0x1820: 68, + 0x1821: 68, + 0x1822: 68, + 0x1823: 68, + 0x1824: 68, + 0x1825: 68, + 0x1826: 68, + 0x1827: 68, + 0x1828: 68, + 0x1829: 68, + 0x182A: 68, + 0x182B: 68, + 0x182C: 68, + 0x182D: 68, + 0x182E: 68, + 0x182F: 68, + 0x1830: 68, + 0x1831: 68, + 0x1832: 68, + 0x1833: 68, + 0x1834: 68, + 0x1835: 68, + 0x1836: 68, + 0x1837: 68, + 0x1838: 68, + 0x1839: 68, + 0x183A: 68, + 0x183B: 68, + 0x183C: 68, + 0x183D: 68, + 0x183E: 68, + 0x183F: 68, + 0x1840: 68, + 0x1841: 68, + 0x1842: 68, + 0x1843: 68, + 0x1844: 68, + 0x1845: 68, + 0x1846: 68, + 0x1847: 68, + 0x1848: 68, + 0x1849: 68, + 0x184A: 68, + 0x184B: 68, + 0x184C: 68, + 0x184D: 68, + 0x184E: 68, + 0x184F: 68, + 0x1850: 68, + 0x1851: 68, + 0x1852: 68, + 0x1853: 68, + 0x1854: 68, + 0x1855: 68, + 0x1856: 68, + 0x1857: 68, + 0x1858: 68, + 0x1859: 68, + 0x185A: 68, + 0x185B: 68, + 0x185C: 68, + 0x185D: 68, + 0x185E: 68, + 0x185F: 68, + 0x1860: 68, + 0x1861: 68, + 0x1862: 68, + 0x1863: 68, + 0x1864: 68, + 0x1865: 68, + 0x1866: 68, + 0x1867: 68, + 0x1868: 68, + 0x1869: 68, + 0x186A: 68, + 0x186B: 68, + 0x186C: 68, + 0x186D: 68, + 0x186E: 68, + 0x186F: 68, + 0x1870: 68, + 0x1871: 68, + 0x1872: 68, + 0x1873: 68, + 0x1874: 68, + 0x1875: 68, + 0x1876: 68, + 0x1877: 68, + 0x1878: 68, + 0x1885: 84, + 0x1886: 84, + 0x1887: 68, + 0x1888: 68, + 0x1889: 68, + 0x188A: 68, + 0x188B: 68, + 0x188C: 68, + 0x188D: 68, + 0x188E: 68, + 0x188F: 68, + 0x1890: 68, + 0x1891: 68, + 0x1892: 68, + 0x1893: 68, + 0x1894: 68, + 0x1895: 68, + 0x1896: 68, + 0x1897: 68, + 0x1898: 68, + 0x1899: 68, + 0x189A: 68, + 0x189B: 68, + 0x189C: 68, + 0x189D: 68, + 0x189E: 68, + 0x189F: 68, + 0x18A0: 68, + 0x18A1: 68, + 0x18A2: 68, + 0x18A3: 68, + 0x18A4: 68, + 0x18A5: 68, + 0x18A6: 68, + 0x18A7: 68, + 0x18A8: 68, + 0x18A9: 84, + 0x18AA: 68, + 0x1920: 84, + 0x1921: 84, + 0x1922: 84, + 0x1927: 84, + 0x1928: 84, + 0x1932: 84, + 0x1939: 84, + 0x193A: 84, + 0x193B: 84, + 0x1A17: 84, + 0x1A18: 84, + 0x1A1B: 84, + 0x1A56: 84, + 0x1A58: 84, + 0x1A59: 84, + 0x1A5A: 84, + 0x1A5B: 84, + 0x1A5C: 84, + 0x1A5D: 84, + 0x1A5E: 84, + 0x1A60: 84, + 0x1A62: 84, + 0x1A65: 84, + 0x1A66: 84, + 0x1A67: 84, + 0x1A68: 84, + 0x1A69: 84, + 0x1A6A: 84, + 0x1A6B: 84, + 0x1A6C: 84, + 0x1A73: 84, + 0x1A74: 84, + 0x1A75: 84, + 0x1A76: 84, + 0x1A77: 84, + 0x1A78: 84, + 0x1A79: 84, + 0x1A7A: 84, + 0x1A7B: 84, + 0x1A7C: 84, + 0x1A7F: 84, + 0x1AB0: 84, + 0x1AB1: 84, + 0x1AB2: 84, + 0x1AB3: 84, + 0x1AB4: 84, + 0x1AB5: 84, + 0x1AB6: 84, + 0x1AB7: 84, + 0x1AB8: 84, + 0x1AB9: 84, + 0x1ABA: 84, + 0x1ABB: 84, + 0x1ABC: 84, + 0x1ABD: 84, + 0x1ABE: 84, + 0x1ABF: 84, + 0x1AC0: 84, + 0x1AC1: 84, + 0x1AC2: 84, + 0x1AC3: 84, + 0x1AC4: 84, + 0x1AC5: 84, + 0x1AC6: 84, + 0x1AC7: 84, + 0x1AC8: 84, + 0x1AC9: 84, + 0x1ACA: 84, + 0x1ACB: 84, + 0x1ACC: 84, + 0x1ACD: 84, + 0x1ACE: 84, + 0x1B00: 84, + 0x1B01: 84, + 0x1B02: 84, + 0x1B03: 84, + 0x1B34: 84, + 0x1B36: 84, + 0x1B37: 84, + 0x1B38: 84, + 0x1B39: 84, + 0x1B3A: 84, + 0x1B3C: 84, + 0x1B42: 84, + 0x1B6B: 84, + 0x1B6C: 84, + 0x1B6D: 84, + 0x1B6E: 84, + 0x1B6F: 84, + 0x1B70: 84, + 0x1B71: 84, + 0x1B72: 84, + 0x1B73: 84, + 0x1B80: 84, + 0x1B81: 84, + 0x1BA2: 84, + 0x1BA3: 84, + 0x1BA4: 84, + 0x1BA5: 84, + 0x1BA8: 84, + 0x1BA9: 84, + 0x1BAB: 84, + 0x1BAC: 84, + 0x1BAD: 84, + 0x1BE6: 84, + 0x1BE8: 84, + 0x1BE9: 84, + 0x1BED: 84, + 0x1BEF: 84, + 0x1BF0: 84, + 0x1BF1: 84, + 0x1C2C: 84, + 0x1C2D: 84, + 0x1C2E: 84, + 0x1C2F: 84, + 0x1C30: 84, + 0x1C31: 84, + 0x1C32: 84, + 0x1C33: 84, + 0x1C36: 84, + 0x1C37: 84, + 0x1CD0: 84, + 0x1CD1: 84, + 0x1CD2: 84, + 0x1CD4: 84, + 0x1CD5: 84, + 0x1CD6: 84, + 0x1CD7: 84, + 0x1CD8: 84, + 0x1CD9: 84, + 0x1CDA: 84, + 0x1CDB: 84, + 0x1CDC: 84, + 0x1CDD: 84, + 0x1CDE: 84, + 0x1CDF: 84, + 0x1CE0: 84, + 0x1CE2: 84, + 0x1CE3: 84, + 0x1CE4: 84, + 0x1CE5: 84, + 0x1CE6: 84, + 0x1CE7: 84, + 0x1CE8: 84, + 0x1CED: 84, + 0x1CF4: 84, + 0x1CF8: 84, + 0x1CF9: 84, + 0x1DC0: 84, + 0x1DC1: 84, + 0x1DC2: 84, + 0x1DC3: 84, + 0x1DC4: 84, + 0x1DC5: 84, + 0x1DC6: 84, + 0x1DC7: 84, + 0x1DC8: 84, + 0x1DC9: 84, + 0x1DCA: 84, + 0x1DCB: 84, + 0x1DCC: 84, + 0x1DCD: 84, + 0x1DCE: 84, + 0x1DCF: 84, + 0x1DD0: 84, + 0x1DD1: 84, + 0x1DD2: 84, + 0x1DD3: 84, + 0x1DD4: 84, + 0x1DD5: 84, + 0x1DD6: 84, + 0x1DD7: 84, + 0x1DD8: 84, + 0x1DD9: 84, + 0x1DDA: 84, + 0x1DDB: 84, + 0x1DDC: 84, + 0x1DDD: 84, + 0x1DDE: 84, + 0x1DDF: 84, + 0x1DE0: 84, + 0x1DE1: 84, + 0x1DE2: 84, + 0x1DE3: 84, + 0x1DE4: 84, + 0x1DE5: 84, + 0x1DE6: 84, + 0x1DE7: 84, + 0x1DE8: 84, + 0x1DE9: 84, + 0x1DEA: 84, + 0x1DEB: 84, + 0x1DEC: 84, + 0x1DED: 84, + 0x1DEE: 84, + 0x1DEF: 84, + 0x1DF0: 84, + 0x1DF1: 84, + 0x1DF2: 84, + 0x1DF3: 84, + 0x1DF4: 84, + 0x1DF5: 84, + 0x1DF6: 84, + 0x1DF7: 84, + 0x1DF8: 84, + 0x1DF9: 84, + 0x1DFA: 84, + 0x1DFB: 84, + 0x1DFC: 84, + 0x1DFD: 84, + 0x1DFE: 84, + 0x1DFF: 84, + 0x200B: 84, + 0x200D: 67, + 0x200E: 84, + 0x200F: 84, + 0x202A: 84, + 0x202B: 84, + 0x202C: 84, + 0x202D: 84, + 0x202E: 84, + 0x2060: 84, + 0x2061: 84, + 0x2062: 84, + 0x2063: 84, + 0x2064: 84, + 0x206A: 84, + 0x206B: 84, + 0x206C: 84, + 0x206D: 84, + 0x206E: 84, + 0x206F: 84, + 0x20D0: 84, + 0x20D1: 84, + 0x20D2: 84, + 0x20D3: 84, + 0x20D4: 84, + 0x20D5: 84, + 0x20D6: 84, + 0x20D7: 84, + 0x20D8: 84, + 0x20D9: 84, + 0x20DA: 84, + 0x20DB: 84, + 0x20DC: 84, + 0x20DD: 84, + 0x20DE: 84, + 0x20DF: 84, + 0x20E0: 84, + 0x20E1: 84, + 0x20E2: 84, + 0x20E3: 84, + 0x20E4: 84, + 0x20E5: 84, + 0x20E6: 84, + 0x20E7: 84, + 0x20E8: 84, + 0x20E9: 84, + 0x20EA: 84, + 0x20EB: 84, + 0x20EC: 84, + 0x20ED: 84, + 0x20EE: 84, + 0x20EF: 84, + 0x20F0: 84, + 0x2CEF: 84, + 0x2CF0: 84, + 0x2CF1: 84, + 0x2D7F: 84, + 0x2DE0: 84, + 0x2DE1: 84, + 0x2DE2: 84, + 0x2DE3: 84, + 0x2DE4: 84, + 0x2DE5: 84, + 0x2DE6: 84, + 0x2DE7: 84, + 0x2DE8: 84, + 0x2DE9: 84, + 0x2DEA: 84, + 0x2DEB: 84, + 0x2DEC: 84, + 0x2DED: 84, + 0x2DEE: 84, + 0x2DEF: 84, + 0x2DF0: 84, + 0x2DF1: 84, + 0x2DF2: 84, + 0x2DF3: 84, + 0x2DF4: 84, + 0x2DF5: 84, + 0x2DF6: 84, + 0x2DF7: 84, + 0x2DF8: 84, + 0x2DF9: 84, + 0x2DFA: 84, + 0x2DFB: 84, + 0x2DFC: 84, + 0x2DFD: 84, + 0x2DFE: 84, + 0x2DFF: 84, + 0x302A: 84, + 0x302B: 84, + 0x302C: 84, + 0x302D: 84, + 0x3099: 84, + 0x309A: 84, + 0xA66F: 84, + 0xA670: 84, + 0xA671: 84, + 0xA672: 84, + 0xA674: 84, + 0xA675: 84, + 0xA676: 84, + 0xA677: 84, + 0xA678: 84, + 0xA679: 84, + 0xA67A: 84, + 0xA67B: 84, + 0xA67C: 84, + 0xA67D: 84, + 0xA69E: 84, + 0xA69F: 84, + 0xA6F0: 84, + 0xA6F1: 84, + 0xA802: 84, + 0xA806: 84, + 0xA80B: 84, + 0xA825: 84, + 0xA826: 84, + 0xA82C: 84, + 0xA840: 68, + 0xA841: 68, + 0xA842: 68, + 0xA843: 68, + 0xA844: 68, + 0xA845: 68, + 0xA846: 68, + 0xA847: 68, + 0xA848: 68, + 0xA849: 68, + 0xA84A: 68, + 0xA84B: 68, + 0xA84C: 68, + 0xA84D: 68, + 0xA84E: 68, + 0xA84F: 68, + 0xA850: 68, + 0xA851: 68, + 0xA852: 68, + 0xA853: 68, + 0xA854: 68, + 0xA855: 68, + 0xA856: 68, + 0xA857: 68, + 0xA858: 68, + 0xA859: 68, + 0xA85A: 68, + 0xA85B: 68, + 0xA85C: 68, + 0xA85D: 68, + 0xA85E: 68, + 0xA85F: 68, + 0xA860: 68, + 0xA861: 68, + 0xA862: 68, + 0xA863: 68, + 0xA864: 68, + 0xA865: 68, + 0xA866: 68, + 0xA867: 68, + 0xA868: 68, + 0xA869: 68, + 0xA86A: 68, + 0xA86B: 68, + 0xA86C: 68, + 0xA86D: 68, + 0xA86E: 68, + 0xA86F: 68, + 0xA870: 68, + 0xA871: 68, + 0xA872: 76, + 0xA8C4: 84, + 0xA8C5: 84, + 0xA8E0: 84, + 0xA8E1: 84, + 0xA8E2: 84, + 0xA8E3: 84, + 0xA8E4: 84, + 0xA8E5: 84, + 0xA8E6: 84, + 0xA8E7: 84, + 0xA8E8: 84, + 0xA8E9: 84, + 0xA8EA: 84, + 0xA8EB: 84, + 0xA8EC: 84, + 0xA8ED: 84, + 0xA8EE: 84, + 0xA8EF: 84, + 0xA8F0: 84, + 0xA8F1: 84, + 0xA8FF: 84, + 0xA926: 84, + 0xA927: 84, + 0xA928: 84, + 0xA929: 84, + 0xA92A: 84, + 0xA92B: 84, + 0xA92C: 84, + 0xA92D: 84, + 0xA947: 84, + 0xA948: 84, + 0xA949: 84, + 0xA94A: 84, + 0xA94B: 84, + 0xA94C: 84, + 0xA94D: 84, + 0xA94E: 84, + 0xA94F: 84, + 0xA950: 84, + 0xA951: 84, + 0xA980: 84, + 0xA981: 84, + 0xA982: 84, + 0xA9B3: 84, + 0xA9B6: 84, + 0xA9B7: 84, + 0xA9B8: 84, + 0xA9B9: 84, + 0xA9BC: 84, + 0xA9BD: 84, + 0xA9E5: 84, + 0xAA29: 84, + 0xAA2A: 84, + 0xAA2B: 84, + 0xAA2C: 84, + 0xAA2D: 84, + 0xAA2E: 84, + 0xAA31: 84, + 0xAA32: 84, + 0xAA35: 84, + 0xAA36: 84, + 0xAA43: 84, + 0xAA4C: 84, + 0xAA7C: 84, + 0xAAB0: 84, + 0xAAB2: 84, + 0xAAB3: 84, + 0xAAB4: 84, + 0xAAB7: 84, + 0xAAB8: 84, + 0xAABE: 84, + 0xAABF: 84, + 0xAAC1: 84, + 0xAAEC: 84, + 0xAAED: 84, + 0xAAF6: 84, + 0xABE5: 84, + 0xABE8: 84, + 0xABED: 84, + 0xFB1E: 84, + 0xFE00: 84, + 0xFE01: 84, + 0xFE02: 84, + 0xFE03: 84, + 0xFE04: 84, + 0xFE05: 84, + 0xFE06: 84, + 0xFE07: 84, + 0xFE08: 84, + 0xFE09: 84, + 0xFE0A: 84, + 0xFE0B: 84, + 0xFE0C: 84, + 0xFE0D: 84, + 0xFE0E: 84, + 0xFE0F: 84, + 0xFE20: 84, + 0xFE21: 84, + 0xFE22: 84, + 0xFE23: 84, + 0xFE24: 84, + 0xFE25: 84, + 0xFE26: 84, + 0xFE27: 84, + 0xFE28: 84, + 0xFE29: 84, + 0xFE2A: 84, + 0xFE2B: 84, + 0xFE2C: 84, + 0xFE2D: 84, + 0xFE2E: 84, + 0xFE2F: 84, + 0xFEFF: 84, + 0xFFF9: 84, + 0xFFFA: 84, + 0xFFFB: 84, + 0x101FD: 84, + 0x102E0: 84, + 0x10376: 84, + 0x10377: 84, + 0x10378: 84, + 0x10379: 84, + 0x1037A: 84, + 0x10A01: 84, + 0x10A02: 84, + 0x10A03: 84, + 0x10A05: 84, + 0x10A06: 84, + 0x10A0C: 84, + 0x10A0D: 84, + 0x10A0E: 84, + 0x10A0F: 84, + 0x10A38: 84, + 0x10A39: 84, + 0x10A3A: 84, + 0x10A3F: 84, + 0x10AC0: 68, + 0x10AC1: 68, + 0x10AC2: 68, + 0x10AC3: 68, + 0x10AC4: 68, + 0x10AC5: 82, + 0x10AC7: 82, + 0x10AC9: 82, + 0x10ACA: 82, + 0x10ACD: 76, + 0x10ACE: 82, + 0x10ACF: 82, + 0x10AD0: 82, + 0x10AD1: 82, + 0x10AD2: 82, + 0x10AD3: 68, + 0x10AD4: 68, + 0x10AD5: 68, + 0x10AD6: 68, + 0x10AD7: 76, + 0x10AD8: 68, + 0x10AD9: 68, + 0x10ADA: 68, + 0x10ADB: 68, + 0x10ADC: 68, + 0x10ADD: 82, + 0x10ADE: 68, + 0x10ADF: 68, + 0x10AE0: 68, + 0x10AE1: 82, + 0x10AE4: 82, + 0x10AE5: 84, + 0x10AE6: 84, + 0x10AEB: 68, + 0x10AEC: 68, + 0x10AED: 68, + 0x10AEE: 68, + 0x10AEF: 82, + 0x10B80: 68, + 0x10B81: 82, + 0x10B82: 68, + 0x10B83: 82, + 0x10B84: 82, + 0x10B85: 82, + 0x10B86: 68, + 0x10B87: 68, + 0x10B88: 68, + 0x10B89: 82, + 0x10B8A: 68, + 0x10B8B: 68, + 0x10B8C: 82, + 0x10B8D: 68, + 0x10B8E: 82, + 0x10B8F: 82, + 0x10B90: 68, + 0x10B91: 82, + 0x10BA9: 82, + 0x10BAA: 82, + 0x10BAB: 82, + 0x10BAC: 82, + 0x10BAD: 68, + 0x10BAE: 68, + 0x10D00: 76, + 0x10D01: 68, + 0x10D02: 68, + 0x10D03: 68, + 0x10D04: 68, + 0x10D05: 68, + 0x10D06: 68, + 0x10D07: 68, + 0x10D08: 68, + 0x10D09: 68, + 0x10D0A: 68, + 0x10D0B: 68, + 0x10D0C: 68, + 0x10D0D: 68, + 0x10D0E: 68, + 0x10D0F: 68, + 0x10D10: 68, + 0x10D11: 68, + 0x10D12: 68, + 0x10D13: 68, + 0x10D14: 68, + 0x10D15: 68, + 0x10D16: 68, + 0x10D17: 68, + 0x10D18: 68, + 0x10D19: 68, + 0x10D1A: 68, + 0x10D1B: 68, + 0x10D1C: 68, + 0x10D1D: 68, + 0x10D1E: 68, + 0x10D1F: 68, + 0x10D20: 68, + 0x10D21: 68, + 0x10D22: 82, + 0x10D23: 68, + 0x10D24: 84, + 0x10D25: 84, + 0x10D26: 84, + 0x10D27: 84, + 0x10EAB: 84, + 0x10EAC: 84, + 0x10EFD: 84, + 0x10EFE: 84, + 0x10EFF: 84, + 0x10F30: 68, + 0x10F31: 68, + 0x10F32: 68, + 0x10F33: 82, + 0x10F34: 68, + 0x10F35: 68, + 0x10F36: 68, + 0x10F37: 68, + 0x10F38: 68, + 0x10F39: 68, + 0x10F3A: 68, + 0x10F3B: 68, + 0x10F3C: 68, + 0x10F3D: 68, + 0x10F3E: 68, + 0x10F3F: 68, + 0x10F40: 68, + 0x10F41: 68, + 0x10F42: 68, + 0x10F43: 68, + 0x10F44: 68, + 0x10F46: 84, + 0x10F47: 84, + 0x10F48: 84, + 0x10F49: 84, + 0x10F4A: 84, + 0x10F4B: 84, + 0x10F4C: 84, + 0x10F4D: 84, + 0x10F4E: 84, + 0x10F4F: 84, + 0x10F50: 84, + 0x10F51: 68, + 0x10F52: 68, + 0x10F53: 68, + 0x10F54: 82, + 0x10F70: 68, + 0x10F71: 68, + 0x10F72: 68, + 0x10F73: 68, + 0x10F74: 82, + 0x10F75: 82, + 0x10F76: 68, + 0x10F77: 68, + 0x10F78: 68, + 0x10F79: 68, + 0x10F7A: 68, + 0x10F7B: 68, + 0x10F7C: 68, + 0x10F7D: 68, + 0x10F7E: 68, + 0x10F7F: 68, + 0x10F80: 68, + 0x10F81: 68, + 0x10F82: 84, + 0x10F83: 84, + 0x10F84: 84, + 0x10F85: 84, + 0x10FB0: 68, + 0x10FB2: 68, + 0x10FB3: 68, + 0x10FB4: 82, + 0x10FB5: 82, + 0x10FB6: 82, + 0x10FB8: 68, + 0x10FB9: 82, + 0x10FBA: 82, + 0x10FBB: 68, + 0x10FBC: 68, + 0x10FBD: 82, + 0x10FBE: 68, + 0x10FBF: 68, + 0x10FC1: 68, + 0x10FC2: 82, + 0x10FC3: 82, + 0x10FC4: 68, + 0x10FC9: 82, + 0x10FCA: 68, + 0x10FCB: 76, + 0x11001: 84, + 0x11038: 84, + 0x11039: 84, + 0x1103A: 84, + 0x1103B: 84, + 0x1103C: 84, + 0x1103D: 84, + 0x1103E: 84, + 0x1103F: 84, + 0x11040: 84, + 0x11041: 84, + 0x11042: 84, + 0x11043: 84, + 0x11044: 84, + 0x11045: 84, + 0x11046: 84, + 0x11070: 84, + 0x11073: 84, + 0x11074: 84, + 0x1107F: 84, + 0x11080: 84, + 0x11081: 84, + 0x110B3: 84, + 0x110B4: 84, + 0x110B5: 84, + 0x110B6: 84, + 0x110B9: 84, + 0x110BA: 84, + 0x110C2: 84, + 0x11100: 84, + 0x11101: 84, + 0x11102: 84, + 0x11127: 84, + 0x11128: 84, + 0x11129: 84, + 0x1112A: 84, + 0x1112B: 84, + 0x1112D: 84, + 0x1112E: 84, + 0x1112F: 84, + 0x11130: 84, + 0x11131: 84, + 0x11132: 84, + 0x11133: 84, + 0x11134: 84, + 0x11173: 84, + 0x11180: 84, + 0x11181: 84, + 0x111B6: 84, + 0x111B7: 84, + 0x111B8: 84, + 0x111B9: 84, + 0x111BA: 84, + 0x111BB: 84, + 0x111BC: 84, + 0x111BD: 84, + 0x111BE: 84, + 0x111C9: 84, + 0x111CA: 84, + 0x111CB: 84, + 0x111CC: 84, + 0x111CF: 84, + 0x1122F: 84, + 0x11230: 84, + 0x11231: 84, + 0x11234: 84, + 0x11236: 84, + 0x11237: 84, + 0x1123E: 84, + 0x11241: 84, + 0x112DF: 84, + 0x112E3: 84, + 0x112E4: 84, + 0x112E5: 84, + 0x112E6: 84, + 0x112E7: 84, + 0x112E8: 84, + 0x112E9: 84, + 0x112EA: 84, + 0x11300: 84, + 0x11301: 84, + 0x1133B: 84, + 0x1133C: 84, + 0x11340: 84, + 0x11366: 84, + 0x11367: 84, + 0x11368: 84, + 0x11369: 84, + 0x1136A: 84, + 0x1136B: 84, + 0x1136C: 84, + 0x11370: 84, + 0x11371: 84, + 0x11372: 84, + 0x11373: 84, + 0x11374: 84, + 0x11438: 84, + 0x11439: 84, + 0x1143A: 84, + 0x1143B: 84, + 0x1143C: 84, + 0x1143D: 84, + 0x1143E: 84, + 0x1143F: 84, + 0x11442: 84, + 0x11443: 84, + 0x11444: 84, + 0x11446: 84, + 0x1145E: 84, + 0x114B3: 84, + 0x114B4: 84, + 0x114B5: 84, + 0x114B6: 84, + 0x114B7: 84, + 0x114B8: 84, + 0x114BA: 84, + 0x114BF: 84, + 0x114C0: 84, + 0x114C2: 84, + 0x114C3: 84, + 0x115B2: 84, + 0x115B3: 84, + 0x115B4: 84, + 0x115B5: 84, + 0x115BC: 84, + 0x115BD: 84, + 0x115BF: 84, + 0x115C0: 84, + 0x115DC: 84, + 0x115DD: 84, + 0x11633: 84, + 0x11634: 84, + 0x11635: 84, + 0x11636: 84, + 0x11637: 84, + 0x11638: 84, + 0x11639: 84, + 0x1163A: 84, + 0x1163D: 84, + 0x1163F: 84, + 0x11640: 84, + 0x116AB: 84, + 0x116AD: 84, + 0x116B0: 84, + 0x116B1: 84, + 0x116B2: 84, + 0x116B3: 84, + 0x116B4: 84, + 0x116B5: 84, + 0x116B7: 84, + 0x1171D: 84, + 0x1171E: 84, + 0x1171F: 84, + 0x11722: 84, + 0x11723: 84, + 0x11724: 84, + 0x11725: 84, + 0x11727: 84, + 0x11728: 84, + 0x11729: 84, + 0x1172A: 84, + 0x1172B: 84, + 0x1182F: 84, + 0x11830: 84, + 0x11831: 84, + 0x11832: 84, + 0x11833: 84, + 0x11834: 84, + 0x11835: 84, + 0x11836: 84, + 0x11837: 84, + 0x11839: 84, + 0x1183A: 84, + 0x1193B: 84, + 0x1193C: 84, + 0x1193E: 84, + 0x11943: 84, + 0x119D4: 84, + 0x119D5: 84, + 0x119D6: 84, + 0x119D7: 84, + 0x119DA: 84, + 0x119DB: 84, + 0x119E0: 84, + 0x11A01: 84, + 0x11A02: 84, + 0x11A03: 84, + 0x11A04: 84, + 0x11A05: 84, + 0x11A06: 84, + 0x11A07: 84, + 0x11A08: 84, + 0x11A09: 84, + 0x11A0A: 84, + 0x11A33: 84, + 0x11A34: 84, + 0x11A35: 84, + 0x11A36: 84, + 0x11A37: 84, + 0x11A38: 84, + 0x11A3B: 84, + 0x11A3C: 84, + 0x11A3D: 84, + 0x11A3E: 84, + 0x11A47: 84, + 0x11A51: 84, + 0x11A52: 84, + 0x11A53: 84, + 0x11A54: 84, + 0x11A55: 84, + 0x11A56: 84, + 0x11A59: 84, + 0x11A5A: 84, + 0x11A5B: 84, + 0x11A8A: 84, + 0x11A8B: 84, + 0x11A8C: 84, + 0x11A8D: 84, + 0x11A8E: 84, + 0x11A8F: 84, + 0x11A90: 84, + 0x11A91: 84, + 0x11A92: 84, + 0x11A93: 84, + 0x11A94: 84, + 0x11A95: 84, + 0x11A96: 84, + 0x11A98: 84, + 0x11A99: 84, + 0x11C30: 84, + 0x11C31: 84, + 0x11C32: 84, + 0x11C33: 84, + 0x11C34: 84, + 0x11C35: 84, + 0x11C36: 84, + 0x11C38: 84, + 0x11C39: 84, + 0x11C3A: 84, + 0x11C3B: 84, + 0x11C3C: 84, + 0x11C3D: 84, + 0x11C3F: 84, + 0x11C92: 84, + 0x11C93: 84, + 0x11C94: 84, + 0x11C95: 84, + 0x11C96: 84, + 0x11C97: 84, + 0x11C98: 84, + 0x11C99: 84, + 0x11C9A: 84, + 0x11C9B: 84, + 0x11C9C: 84, + 0x11C9D: 84, + 0x11C9E: 84, + 0x11C9F: 84, + 0x11CA0: 84, + 0x11CA1: 84, + 0x11CA2: 84, + 0x11CA3: 84, + 0x11CA4: 84, + 0x11CA5: 84, + 0x11CA6: 84, + 0x11CA7: 84, + 0x11CAA: 84, + 0x11CAB: 84, + 0x11CAC: 84, + 0x11CAD: 84, + 0x11CAE: 84, + 0x11CAF: 84, + 0x11CB0: 84, + 0x11CB2: 84, + 0x11CB3: 84, + 0x11CB5: 84, + 0x11CB6: 84, + 0x11D31: 84, + 0x11D32: 84, + 0x11D33: 84, + 0x11D34: 84, + 0x11D35: 84, + 0x11D36: 84, + 0x11D3A: 84, + 0x11D3C: 84, + 0x11D3D: 84, + 0x11D3F: 84, + 0x11D40: 84, + 0x11D41: 84, + 0x11D42: 84, + 0x11D43: 84, + 0x11D44: 84, + 0x11D45: 84, + 0x11D47: 84, + 0x11D90: 84, + 0x11D91: 84, + 0x11D95: 84, + 0x11D97: 84, + 0x11EF3: 84, + 0x11EF4: 84, + 0x11F00: 84, + 0x11F01: 84, + 0x11F36: 84, + 0x11F37: 84, + 0x11F38: 84, + 0x11F39: 84, + 0x11F3A: 84, + 0x11F40: 84, + 0x11F42: 84, + 0x13430: 84, + 0x13431: 84, + 0x13432: 84, + 0x13433: 84, + 0x13434: 84, + 0x13435: 84, + 0x13436: 84, + 0x13437: 84, + 0x13438: 84, + 0x13439: 84, + 0x1343A: 84, + 0x1343B: 84, + 0x1343C: 84, + 0x1343D: 84, + 0x1343E: 84, + 0x1343F: 84, + 0x13440: 84, + 0x13447: 84, + 0x13448: 84, + 0x13449: 84, + 0x1344A: 84, + 0x1344B: 84, + 0x1344C: 84, + 0x1344D: 84, + 0x1344E: 84, + 0x1344F: 84, + 0x13450: 84, + 0x13451: 84, + 0x13452: 84, + 0x13453: 84, + 0x13454: 84, + 0x13455: 84, + 0x16AF0: 84, + 0x16AF1: 84, + 0x16AF2: 84, + 0x16AF3: 84, + 0x16AF4: 84, + 0x16B30: 84, + 0x16B31: 84, + 0x16B32: 84, + 0x16B33: 84, + 0x16B34: 84, + 0x16B35: 84, + 0x16B36: 84, + 0x16F4F: 84, + 0x16F8F: 84, + 0x16F90: 84, + 0x16F91: 84, + 0x16F92: 84, + 0x16FE4: 84, + 0x1BC9D: 84, + 0x1BC9E: 84, + 0x1BCA0: 84, + 0x1BCA1: 84, + 0x1BCA2: 84, + 0x1BCA3: 84, + 0x1CF00: 84, + 0x1CF01: 84, + 0x1CF02: 84, + 0x1CF03: 84, + 0x1CF04: 84, + 0x1CF05: 84, + 0x1CF06: 84, + 0x1CF07: 84, + 0x1CF08: 84, + 0x1CF09: 84, + 0x1CF0A: 84, + 0x1CF0B: 84, + 0x1CF0C: 84, + 0x1CF0D: 84, + 0x1CF0E: 84, + 0x1CF0F: 84, + 0x1CF10: 84, + 0x1CF11: 84, + 0x1CF12: 84, + 0x1CF13: 84, + 0x1CF14: 84, + 0x1CF15: 84, + 0x1CF16: 84, + 0x1CF17: 84, + 0x1CF18: 84, + 0x1CF19: 84, + 0x1CF1A: 84, + 0x1CF1B: 84, + 0x1CF1C: 84, + 0x1CF1D: 84, + 0x1CF1E: 84, + 0x1CF1F: 84, + 0x1CF20: 84, + 0x1CF21: 84, + 0x1CF22: 84, + 0x1CF23: 84, + 0x1CF24: 84, + 0x1CF25: 84, + 0x1CF26: 84, + 0x1CF27: 84, + 0x1CF28: 84, + 0x1CF29: 84, + 0x1CF2A: 84, + 0x1CF2B: 84, + 0x1CF2C: 84, + 0x1CF2D: 84, + 0x1CF30: 84, + 0x1CF31: 84, + 0x1CF32: 84, + 0x1CF33: 84, + 0x1CF34: 84, + 0x1CF35: 84, + 0x1CF36: 84, + 0x1CF37: 84, + 0x1CF38: 84, + 0x1CF39: 84, + 0x1CF3A: 84, + 0x1CF3B: 84, + 0x1CF3C: 84, + 0x1CF3D: 84, + 0x1CF3E: 84, + 0x1CF3F: 84, + 0x1CF40: 84, + 0x1CF41: 84, + 0x1CF42: 84, + 0x1CF43: 84, + 0x1CF44: 84, + 0x1CF45: 84, + 0x1CF46: 84, + 0x1D167: 84, + 0x1D168: 84, + 0x1D169: 84, + 0x1D173: 84, + 0x1D174: 84, + 0x1D175: 84, + 0x1D176: 84, + 0x1D177: 84, + 0x1D178: 84, + 0x1D179: 84, + 0x1D17A: 84, + 0x1D17B: 84, + 0x1D17C: 84, + 0x1D17D: 84, + 0x1D17E: 84, + 0x1D17F: 84, + 0x1D180: 84, + 0x1D181: 84, + 0x1D182: 84, + 0x1D185: 84, + 0x1D186: 84, + 0x1D187: 84, + 0x1D188: 84, + 0x1D189: 84, + 0x1D18A: 84, + 0x1D18B: 84, + 0x1D1AA: 84, + 0x1D1AB: 84, + 0x1D1AC: 84, + 0x1D1AD: 84, + 0x1D242: 84, + 0x1D243: 84, + 0x1D244: 84, + 0x1DA00: 84, + 0x1DA01: 84, + 0x1DA02: 84, + 0x1DA03: 84, + 0x1DA04: 84, + 0x1DA05: 84, + 0x1DA06: 84, + 0x1DA07: 84, + 0x1DA08: 84, + 0x1DA09: 84, + 0x1DA0A: 84, + 0x1DA0B: 84, + 0x1DA0C: 84, + 0x1DA0D: 84, + 0x1DA0E: 84, + 0x1DA0F: 84, + 0x1DA10: 84, + 0x1DA11: 84, + 0x1DA12: 84, + 0x1DA13: 84, + 0x1DA14: 84, + 0x1DA15: 84, + 0x1DA16: 84, + 0x1DA17: 84, + 0x1DA18: 84, + 0x1DA19: 84, + 0x1DA1A: 84, + 0x1DA1B: 84, + 0x1DA1C: 84, + 0x1DA1D: 84, + 0x1DA1E: 84, + 0x1DA1F: 84, + 0x1DA20: 84, + 0x1DA21: 84, + 0x1DA22: 84, + 0x1DA23: 84, + 0x1DA24: 84, + 0x1DA25: 84, + 0x1DA26: 84, + 0x1DA27: 84, + 0x1DA28: 84, + 0x1DA29: 84, + 0x1DA2A: 84, + 0x1DA2B: 84, + 0x1DA2C: 84, + 0x1DA2D: 84, + 0x1DA2E: 84, + 0x1DA2F: 84, + 0x1DA30: 84, + 0x1DA31: 84, + 0x1DA32: 84, + 0x1DA33: 84, + 0x1DA34: 84, + 0x1DA35: 84, + 0x1DA36: 84, + 0x1DA3B: 84, + 0x1DA3C: 84, + 0x1DA3D: 84, + 0x1DA3E: 84, + 0x1DA3F: 84, + 0x1DA40: 84, + 0x1DA41: 84, + 0x1DA42: 84, + 0x1DA43: 84, + 0x1DA44: 84, + 0x1DA45: 84, + 0x1DA46: 84, + 0x1DA47: 84, + 0x1DA48: 84, + 0x1DA49: 84, + 0x1DA4A: 84, + 0x1DA4B: 84, + 0x1DA4C: 84, + 0x1DA4D: 84, + 0x1DA4E: 84, + 0x1DA4F: 84, + 0x1DA50: 84, + 0x1DA51: 84, + 0x1DA52: 84, + 0x1DA53: 84, + 0x1DA54: 84, + 0x1DA55: 84, + 0x1DA56: 84, + 0x1DA57: 84, + 0x1DA58: 84, + 0x1DA59: 84, + 0x1DA5A: 84, + 0x1DA5B: 84, + 0x1DA5C: 84, + 0x1DA5D: 84, + 0x1DA5E: 84, + 0x1DA5F: 84, + 0x1DA60: 84, + 0x1DA61: 84, + 0x1DA62: 84, + 0x1DA63: 84, + 0x1DA64: 84, + 0x1DA65: 84, + 0x1DA66: 84, + 0x1DA67: 84, + 0x1DA68: 84, + 0x1DA69: 84, + 0x1DA6A: 84, + 0x1DA6B: 84, + 0x1DA6C: 84, + 0x1DA75: 84, + 0x1DA84: 84, + 0x1DA9B: 84, + 0x1DA9C: 84, + 0x1DA9D: 84, + 0x1DA9E: 84, + 0x1DA9F: 84, + 0x1DAA1: 84, + 0x1DAA2: 84, + 0x1DAA3: 84, + 0x1DAA4: 84, + 0x1DAA5: 84, + 0x1DAA6: 84, + 0x1DAA7: 84, + 0x1DAA8: 84, + 0x1DAA9: 84, + 0x1DAAA: 84, + 0x1DAAB: 84, + 0x1DAAC: 84, + 0x1DAAD: 84, + 0x1DAAE: 84, + 0x1DAAF: 84, + 0x1E000: 84, + 0x1E001: 84, + 0x1E002: 84, + 0x1E003: 84, + 0x1E004: 84, + 0x1E005: 84, + 0x1E006: 84, + 0x1E008: 84, + 0x1E009: 84, + 0x1E00A: 84, + 0x1E00B: 84, + 0x1E00C: 84, + 0x1E00D: 84, + 0x1E00E: 84, + 0x1E00F: 84, + 0x1E010: 84, + 0x1E011: 84, + 0x1E012: 84, + 0x1E013: 84, + 0x1E014: 84, + 0x1E015: 84, + 0x1E016: 84, + 0x1E017: 84, + 0x1E018: 84, + 0x1E01B: 84, + 0x1E01C: 84, + 0x1E01D: 84, + 0x1E01E: 84, + 0x1E01F: 84, + 0x1E020: 84, + 0x1E021: 84, + 0x1E023: 84, + 0x1E024: 84, + 0x1E026: 84, + 0x1E027: 84, + 0x1E028: 84, + 0x1E029: 84, + 0x1E02A: 84, + 0x1E08F: 84, + 0x1E130: 84, + 0x1E131: 84, + 0x1E132: 84, + 0x1E133: 84, + 0x1E134: 84, + 0x1E135: 84, + 0x1E136: 84, + 0x1E2AE: 84, + 0x1E2EC: 84, + 0x1E2ED: 84, + 0x1E2EE: 84, + 0x1E2EF: 84, + 0x1E4EC: 84, + 0x1E4ED: 84, + 0x1E4EE: 84, + 0x1E4EF: 84, + 0x1E8D0: 84, + 0x1E8D1: 84, + 0x1E8D2: 84, + 0x1E8D3: 84, + 0x1E8D4: 84, + 0x1E8D5: 84, + 0x1E8D6: 84, + 0x1E900: 68, + 0x1E901: 68, + 0x1E902: 68, + 0x1E903: 68, + 0x1E904: 68, + 0x1E905: 68, + 0x1E906: 68, + 0x1E907: 68, + 0x1E908: 68, + 0x1E909: 68, + 0x1E90A: 68, + 0x1E90B: 68, + 0x1E90C: 68, + 0x1E90D: 68, + 0x1E90E: 68, + 0x1E90F: 68, + 0x1E910: 68, + 0x1E911: 68, + 0x1E912: 68, + 0x1E913: 68, + 0x1E914: 68, + 0x1E915: 68, + 0x1E916: 68, + 0x1E917: 68, + 0x1E918: 68, + 0x1E919: 68, + 0x1E91A: 68, + 0x1E91B: 68, + 0x1E91C: 68, + 0x1E91D: 68, + 0x1E91E: 68, + 0x1E91F: 68, + 0x1E920: 68, + 0x1E921: 68, + 0x1E922: 68, + 0x1E923: 68, + 0x1E924: 68, + 0x1E925: 68, + 0x1E926: 68, + 0x1E927: 68, + 0x1E928: 68, + 0x1E929: 68, + 0x1E92A: 68, + 0x1E92B: 68, + 0x1E92C: 68, + 0x1E92D: 68, + 0x1E92E: 68, + 0x1E92F: 68, + 0x1E930: 68, + 0x1E931: 68, + 0x1E932: 68, + 0x1E933: 68, + 0x1E934: 68, + 0x1E935: 68, + 0x1E936: 68, + 0x1E937: 68, + 0x1E938: 68, + 0x1E939: 68, + 0x1E93A: 68, + 0x1E93B: 68, + 0x1E93C: 68, + 0x1E93D: 68, + 0x1E93E: 68, + 0x1E93F: 68, + 0x1E940: 68, + 0x1E941: 68, + 0x1E942: 68, + 0x1E943: 68, + 0x1E944: 84, + 0x1E945: 84, + 0x1E946: 84, + 0x1E947: 84, + 0x1E948: 84, + 0x1E949: 84, + 0x1E94A: 84, + 0x1E94B: 84, + 0xE0001: 84, + 0xE0020: 84, + 0xE0021: 84, + 0xE0022: 84, + 0xE0023: 84, + 0xE0024: 84, + 0xE0025: 84, + 0xE0026: 84, + 0xE0027: 84, + 0xE0028: 84, + 0xE0029: 84, + 0xE002A: 84, + 0xE002B: 84, + 0xE002C: 84, + 0xE002D: 84, + 0xE002E: 84, + 0xE002F: 84, + 0xE0030: 84, + 0xE0031: 84, + 0xE0032: 84, + 0xE0033: 84, + 0xE0034: 84, + 0xE0035: 84, + 0xE0036: 84, + 0xE0037: 84, + 0xE0038: 84, + 0xE0039: 84, + 0xE003A: 84, + 0xE003B: 84, + 0xE003C: 84, + 0xE003D: 84, + 0xE003E: 84, + 0xE003F: 84, + 0xE0040: 84, + 0xE0041: 84, + 0xE0042: 84, + 0xE0043: 84, + 0xE0044: 84, + 0xE0045: 84, + 0xE0046: 84, + 0xE0047: 84, + 0xE0048: 84, + 0xE0049: 84, + 0xE004A: 84, + 0xE004B: 84, + 0xE004C: 84, + 0xE004D: 84, + 0xE004E: 84, + 0xE004F: 84, + 0xE0050: 84, + 0xE0051: 84, + 0xE0052: 84, + 0xE0053: 84, + 0xE0054: 84, + 0xE0055: 84, + 0xE0056: 84, + 0xE0057: 84, + 0xE0058: 84, + 0xE0059: 84, + 0xE005A: 84, + 0xE005B: 84, + 0xE005C: 84, + 0xE005D: 84, + 0xE005E: 84, + 0xE005F: 84, + 0xE0060: 84, + 0xE0061: 84, + 0xE0062: 84, + 0xE0063: 84, + 0xE0064: 84, + 0xE0065: 84, + 0xE0066: 84, + 0xE0067: 84, + 0xE0068: 84, + 0xE0069: 84, + 0xE006A: 84, + 0xE006B: 84, + 0xE006C: 84, + 0xE006D: 84, + 0xE006E: 84, + 0xE006F: 84, + 0xE0070: 84, + 0xE0071: 84, + 0xE0072: 84, + 0xE0073: 84, + 0xE0074: 84, + 0xE0075: 84, + 0xE0076: 84, + 0xE0077: 84, + 0xE0078: 84, + 0xE0079: 84, + 0xE007A: 84, + 0xE007B: 84, + 0xE007C: 84, + 0xE007D: 84, + 0xE007E: 84, + 0xE007F: 84, + 0xE0100: 84, + 0xE0101: 84, + 0xE0102: 84, + 0xE0103: 84, + 0xE0104: 84, + 0xE0105: 84, + 0xE0106: 84, + 0xE0107: 84, + 0xE0108: 84, + 0xE0109: 84, + 0xE010A: 84, + 0xE010B: 84, + 0xE010C: 84, + 0xE010D: 84, + 0xE010E: 84, + 0xE010F: 84, + 0xE0110: 84, + 0xE0111: 84, + 0xE0112: 84, + 0xE0113: 84, + 0xE0114: 84, + 0xE0115: 84, + 0xE0116: 84, + 0xE0117: 84, + 0xE0118: 84, + 0xE0119: 84, + 0xE011A: 84, + 0xE011B: 84, + 0xE011C: 84, + 0xE011D: 84, + 0xE011E: 84, + 0xE011F: 84, + 0xE0120: 84, + 0xE0121: 84, + 0xE0122: 84, + 0xE0123: 84, + 0xE0124: 84, + 0xE0125: 84, + 0xE0126: 84, + 0xE0127: 84, + 0xE0128: 84, + 0xE0129: 84, + 0xE012A: 84, + 0xE012B: 84, + 0xE012C: 84, + 0xE012D: 84, + 0xE012E: 84, + 0xE012F: 84, + 0xE0130: 84, + 0xE0131: 84, + 0xE0132: 84, + 0xE0133: 84, + 0xE0134: 84, + 0xE0135: 84, + 0xE0136: 84, + 0xE0137: 84, + 0xE0138: 84, + 0xE0139: 84, + 0xE013A: 84, + 0xE013B: 84, + 0xE013C: 84, + 0xE013D: 84, + 0xE013E: 84, + 0xE013F: 84, + 0xE0140: 84, + 0xE0141: 84, + 0xE0142: 84, + 0xE0143: 84, + 0xE0144: 84, + 0xE0145: 84, + 0xE0146: 84, + 0xE0147: 84, + 0xE0148: 84, + 0xE0149: 84, + 0xE014A: 84, + 0xE014B: 84, + 0xE014C: 84, + 0xE014D: 84, + 0xE014E: 84, + 0xE014F: 84, + 0xE0150: 84, + 0xE0151: 84, + 0xE0152: 84, + 0xE0153: 84, + 0xE0154: 84, + 0xE0155: 84, + 0xE0156: 84, + 0xE0157: 84, + 0xE0158: 84, + 0xE0159: 84, + 0xE015A: 84, + 0xE015B: 84, + 0xE015C: 84, + 0xE015D: 84, + 0xE015E: 84, + 0xE015F: 84, + 0xE0160: 84, + 0xE0161: 84, + 0xE0162: 84, + 0xE0163: 84, + 0xE0164: 84, + 0xE0165: 84, + 0xE0166: 84, + 0xE0167: 84, + 0xE0168: 84, + 0xE0169: 84, + 0xE016A: 84, + 0xE016B: 84, + 0xE016C: 84, + 0xE016D: 84, + 0xE016E: 84, + 0xE016F: 84, + 0xE0170: 84, + 0xE0171: 84, + 0xE0172: 84, + 0xE0173: 84, + 0xE0174: 84, + 0xE0175: 84, + 0xE0176: 84, + 0xE0177: 84, + 0xE0178: 84, + 0xE0179: 84, + 0xE017A: 84, + 0xE017B: 84, + 0xE017C: 84, + 0xE017D: 84, + 0xE017E: 84, + 0xE017F: 84, + 0xE0180: 84, + 0xE0181: 84, + 0xE0182: 84, + 0xE0183: 84, + 0xE0184: 84, + 0xE0185: 84, + 0xE0186: 84, + 0xE0187: 84, + 0xE0188: 84, + 0xE0189: 84, + 0xE018A: 84, + 0xE018B: 84, + 0xE018C: 84, + 0xE018D: 84, + 0xE018E: 84, + 0xE018F: 84, + 0xE0190: 84, + 0xE0191: 84, + 0xE0192: 84, + 0xE0193: 84, + 0xE0194: 84, + 0xE0195: 84, + 0xE0196: 84, + 0xE0197: 84, + 0xE0198: 84, + 0xE0199: 84, + 0xE019A: 84, + 0xE019B: 84, + 0xE019C: 84, + 0xE019D: 84, + 0xE019E: 84, + 0xE019F: 84, + 0xE01A0: 84, + 0xE01A1: 84, + 0xE01A2: 84, + 0xE01A3: 84, + 0xE01A4: 84, + 0xE01A5: 84, + 0xE01A6: 84, + 0xE01A7: 84, + 0xE01A8: 84, + 0xE01A9: 84, + 0xE01AA: 84, + 0xE01AB: 84, + 0xE01AC: 84, + 0xE01AD: 84, + 0xE01AE: 84, + 0xE01AF: 84, + 0xE01B0: 84, + 0xE01B1: 84, + 0xE01B2: 84, + 0xE01B3: 84, + 0xE01B4: 84, + 0xE01B5: 84, + 0xE01B6: 84, + 0xE01B7: 84, + 0xE01B8: 84, + 0xE01B9: 84, + 0xE01BA: 84, + 0xE01BB: 84, + 0xE01BC: 84, + 0xE01BD: 84, + 0xE01BE: 84, + 0xE01BF: 84, + 0xE01C0: 84, + 0xE01C1: 84, + 0xE01C2: 84, + 0xE01C3: 84, + 0xE01C4: 84, + 0xE01C5: 84, + 0xE01C6: 84, + 0xE01C7: 84, + 0xE01C8: 84, + 0xE01C9: 84, + 0xE01CA: 84, + 0xE01CB: 84, + 0xE01CC: 84, + 0xE01CD: 84, + 0xE01CE: 84, + 0xE01CF: 84, + 0xE01D0: 84, + 0xE01D1: 84, + 0xE01D2: 84, + 0xE01D3: 84, + 0xE01D4: 84, + 0xE01D5: 84, + 0xE01D6: 84, + 0xE01D7: 84, + 0xE01D8: 84, + 0xE01D9: 84, + 0xE01DA: 84, + 0xE01DB: 84, + 0xE01DC: 84, + 0xE01DD: 84, + 0xE01DE: 84, + 0xE01DF: 84, + 0xE01E0: 84, + 0xE01E1: 84, + 0xE01E2: 84, + 0xE01E3: 84, + 0xE01E4: 84, + 0xE01E5: 84, + 0xE01E6: 84, + 0xE01E7: 84, + 0xE01E8: 84, + 0xE01E9: 84, + 0xE01EA: 84, + 0xE01EB: 84, + 0xE01EC: 84, + 0xE01ED: 84, + 0xE01EE: 84, + 0xE01EF: 84, +} +codepoint_classes = { + "PVALID": ( + 0x2D0000002E, + 0x300000003A, + 0x610000007B, + 0xDF000000F7, + 0xF800000100, + 0x10100000102, + 0x10300000104, + 0x10500000106, + 0x10700000108, + 0x1090000010A, + 0x10B0000010C, + 0x10D0000010E, + 0x10F00000110, + 0x11100000112, + 0x11300000114, + 0x11500000116, + 0x11700000118, + 0x1190000011A, + 0x11B0000011C, + 0x11D0000011E, + 0x11F00000120, + 0x12100000122, + 0x12300000124, + 0x12500000126, + 0x12700000128, + 0x1290000012A, + 0x12B0000012C, + 0x12D0000012E, + 0x12F00000130, + 0x13100000132, + 0x13500000136, + 0x13700000139, + 0x13A0000013B, + 0x13C0000013D, + 0x13E0000013F, + 0x14200000143, + 0x14400000145, + 0x14600000147, + 0x14800000149, + 0x14B0000014C, + 0x14D0000014E, + 0x14F00000150, + 0x15100000152, + 0x15300000154, + 0x15500000156, + 0x15700000158, + 0x1590000015A, + 0x15B0000015C, + 0x15D0000015E, + 0x15F00000160, + 0x16100000162, + 0x16300000164, + 0x16500000166, + 0x16700000168, + 0x1690000016A, + 0x16B0000016C, + 0x16D0000016E, + 0x16F00000170, + 0x17100000172, + 0x17300000174, + 0x17500000176, + 0x17700000178, + 0x17A0000017B, + 0x17C0000017D, + 0x17E0000017F, + 0x18000000181, + 0x18300000184, + 0x18500000186, + 0x18800000189, + 0x18C0000018E, + 0x19200000193, + 0x19500000196, + 0x1990000019C, + 0x19E0000019F, + 0x1A1000001A2, + 0x1A3000001A4, + 0x1A5000001A6, + 0x1A8000001A9, + 0x1AA000001AC, + 0x1AD000001AE, + 0x1B0000001B1, + 0x1B4000001B5, + 0x1B6000001B7, + 0x1B9000001BC, + 0x1BD000001C4, + 0x1CE000001CF, + 0x1D0000001D1, + 0x1D2000001D3, + 0x1D4000001D5, + 0x1D6000001D7, + 0x1D8000001D9, + 0x1DA000001DB, + 0x1DC000001DE, + 0x1DF000001E0, + 0x1E1000001E2, + 0x1E3000001E4, + 0x1E5000001E6, + 0x1E7000001E8, + 0x1E9000001EA, + 0x1EB000001EC, + 0x1ED000001EE, + 0x1EF000001F1, + 0x1F5000001F6, + 0x1F9000001FA, + 0x1FB000001FC, + 0x1FD000001FE, + 0x1FF00000200, + 0x20100000202, + 0x20300000204, + 0x20500000206, + 0x20700000208, + 0x2090000020A, + 0x20B0000020C, + 0x20D0000020E, + 0x20F00000210, + 0x21100000212, + 0x21300000214, + 0x21500000216, + 0x21700000218, + 0x2190000021A, + 0x21B0000021C, + 0x21D0000021E, + 0x21F00000220, + 0x22100000222, + 0x22300000224, + 0x22500000226, + 0x22700000228, + 0x2290000022A, + 0x22B0000022C, + 0x22D0000022E, + 0x22F00000230, + 0x23100000232, + 0x2330000023A, + 0x23C0000023D, + 0x23F00000241, + 0x24200000243, + 0x24700000248, + 0x2490000024A, + 0x24B0000024C, + 0x24D0000024E, + 0x24F000002B0, + 0x2B9000002C2, + 0x2C6000002D2, + 0x2EC000002ED, + 0x2EE000002EF, + 0x30000000340, + 0x34200000343, + 0x3460000034F, + 0x35000000370, + 0x37100000372, + 0x37300000374, + 0x37700000378, + 0x37B0000037E, + 0x39000000391, + 0x3AC000003CF, + 0x3D7000003D8, + 0x3D9000003DA, + 0x3DB000003DC, + 0x3DD000003DE, + 0x3DF000003E0, + 0x3E1000003E2, + 0x3E3000003E4, + 0x3E5000003E6, + 0x3E7000003E8, + 0x3E9000003EA, + 0x3EB000003EC, + 0x3ED000003EE, + 0x3EF000003F0, + 0x3F3000003F4, + 0x3F8000003F9, + 0x3FB000003FD, + 0x43000000460, + 0x46100000462, + 0x46300000464, + 0x46500000466, + 0x46700000468, + 0x4690000046A, + 0x46B0000046C, + 0x46D0000046E, + 0x46F00000470, + 0x47100000472, + 0x47300000474, + 0x47500000476, + 0x47700000478, + 0x4790000047A, + 0x47B0000047C, + 0x47D0000047E, + 0x47F00000480, + 0x48100000482, + 0x48300000488, + 0x48B0000048C, + 0x48D0000048E, + 0x48F00000490, + 0x49100000492, + 0x49300000494, + 0x49500000496, + 0x49700000498, + 0x4990000049A, + 0x49B0000049C, + 0x49D0000049E, + 0x49F000004A0, + 0x4A1000004A2, + 0x4A3000004A4, + 0x4A5000004A6, + 0x4A7000004A8, + 0x4A9000004AA, + 0x4AB000004AC, + 0x4AD000004AE, + 0x4AF000004B0, + 0x4B1000004B2, + 0x4B3000004B4, + 0x4B5000004B6, + 0x4B7000004B8, + 0x4B9000004BA, + 0x4BB000004BC, + 0x4BD000004BE, + 0x4BF000004C0, + 0x4C2000004C3, + 0x4C4000004C5, + 0x4C6000004C7, + 0x4C8000004C9, + 0x4CA000004CB, + 0x4CC000004CD, + 0x4CE000004D0, + 0x4D1000004D2, + 0x4D3000004D4, + 0x4D5000004D6, + 0x4D7000004D8, + 0x4D9000004DA, + 0x4DB000004DC, + 0x4DD000004DE, + 0x4DF000004E0, + 0x4E1000004E2, + 0x4E3000004E4, + 0x4E5000004E6, + 0x4E7000004E8, + 0x4E9000004EA, + 0x4EB000004EC, + 0x4ED000004EE, + 0x4EF000004F0, + 0x4F1000004F2, + 0x4F3000004F4, + 0x4F5000004F6, + 0x4F7000004F8, + 0x4F9000004FA, + 0x4FB000004FC, + 0x4FD000004FE, + 0x4FF00000500, + 0x50100000502, + 0x50300000504, + 0x50500000506, + 0x50700000508, + 0x5090000050A, + 0x50B0000050C, + 0x50D0000050E, + 0x50F00000510, + 0x51100000512, + 0x51300000514, + 0x51500000516, + 0x51700000518, + 0x5190000051A, + 0x51B0000051C, + 0x51D0000051E, + 0x51F00000520, + 0x52100000522, + 0x52300000524, + 0x52500000526, + 0x52700000528, + 0x5290000052A, + 0x52B0000052C, + 0x52D0000052E, + 0x52F00000530, + 0x5590000055A, + 0x56000000587, + 0x58800000589, + 0x591000005BE, + 0x5BF000005C0, + 0x5C1000005C3, + 0x5C4000005C6, + 0x5C7000005C8, + 0x5D0000005EB, + 0x5EF000005F3, + 0x6100000061B, + 0x62000000640, + 0x64100000660, + 0x66E00000675, + 0x679000006D4, + 0x6D5000006DD, + 0x6DF000006E9, + 0x6EA000006F0, + 0x6FA00000700, + 0x7100000074B, + 0x74D000007B2, + 0x7C0000007F6, + 0x7FD000007FE, + 0x8000000082E, + 0x8400000085C, + 0x8600000086B, + 0x87000000888, + 0x8890000088F, + 0x898000008E2, + 0x8E300000958, + 0x96000000964, + 0x96600000970, + 0x97100000984, + 0x9850000098D, + 0x98F00000991, + 0x993000009A9, + 0x9AA000009B1, + 0x9B2000009B3, + 0x9B6000009BA, + 0x9BC000009C5, + 0x9C7000009C9, + 0x9CB000009CF, + 0x9D7000009D8, + 0x9E0000009E4, + 0x9E6000009F2, + 0x9FC000009FD, + 0x9FE000009FF, + 0xA0100000A04, + 0xA0500000A0B, + 0xA0F00000A11, + 0xA1300000A29, + 0xA2A00000A31, + 0xA3200000A33, + 0xA3500000A36, + 0xA3800000A3A, + 0xA3C00000A3D, + 0xA3E00000A43, + 0xA4700000A49, + 0xA4B00000A4E, + 0xA5100000A52, + 0xA5C00000A5D, + 0xA6600000A76, + 0xA8100000A84, + 0xA8500000A8E, + 0xA8F00000A92, + 0xA9300000AA9, + 0xAAA00000AB1, + 0xAB200000AB4, + 0xAB500000ABA, + 0xABC00000AC6, + 0xAC700000ACA, + 0xACB00000ACE, + 0xAD000000AD1, + 0xAE000000AE4, + 0xAE600000AF0, + 0xAF900000B00, + 0xB0100000B04, + 0xB0500000B0D, + 0xB0F00000B11, + 0xB1300000B29, + 0xB2A00000B31, + 0xB3200000B34, + 0xB3500000B3A, + 0xB3C00000B45, + 0xB4700000B49, + 0xB4B00000B4E, + 0xB5500000B58, + 0xB5F00000B64, + 0xB6600000B70, + 0xB7100000B72, + 0xB8200000B84, + 0xB8500000B8B, + 0xB8E00000B91, + 0xB9200000B96, + 0xB9900000B9B, + 0xB9C00000B9D, + 0xB9E00000BA0, + 0xBA300000BA5, + 0xBA800000BAB, + 0xBAE00000BBA, + 0xBBE00000BC3, + 0xBC600000BC9, + 0xBCA00000BCE, + 0xBD000000BD1, + 0xBD700000BD8, + 0xBE600000BF0, + 0xC0000000C0D, + 0xC0E00000C11, + 0xC1200000C29, + 0xC2A00000C3A, + 0xC3C00000C45, + 0xC4600000C49, + 0xC4A00000C4E, + 0xC5500000C57, + 0xC5800000C5B, + 0xC5D00000C5E, + 0xC6000000C64, + 0xC6600000C70, + 0xC8000000C84, + 0xC8500000C8D, + 0xC8E00000C91, + 0xC9200000CA9, + 0xCAA00000CB4, + 0xCB500000CBA, + 0xCBC00000CC5, + 0xCC600000CC9, + 0xCCA00000CCE, + 0xCD500000CD7, + 0xCDD00000CDF, + 0xCE000000CE4, + 0xCE600000CF0, + 0xCF100000CF4, + 0xD0000000D0D, + 0xD0E00000D11, + 0xD1200000D45, + 0xD4600000D49, + 0xD4A00000D4F, + 0xD5400000D58, + 0xD5F00000D64, + 0xD6600000D70, + 0xD7A00000D80, + 0xD8100000D84, + 0xD8500000D97, + 0xD9A00000DB2, + 0xDB300000DBC, + 0xDBD00000DBE, + 0xDC000000DC7, + 0xDCA00000DCB, + 0xDCF00000DD5, + 0xDD600000DD7, + 0xDD800000DE0, + 0xDE600000DF0, + 0xDF200000DF4, + 0xE0100000E33, + 0xE3400000E3B, + 0xE4000000E4F, + 0xE5000000E5A, + 0xE8100000E83, + 0xE8400000E85, + 0xE8600000E8B, + 0xE8C00000EA4, + 0xEA500000EA6, + 0xEA700000EB3, + 0xEB400000EBE, + 0xEC000000EC5, + 0xEC600000EC7, + 0xEC800000ECF, + 0xED000000EDA, + 0xEDE00000EE0, + 0xF0000000F01, + 0xF0B00000F0C, + 0xF1800000F1A, + 0xF2000000F2A, + 0xF3500000F36, + 0xF3700000F38, + 0xF3900000F3A, + 0xF3E00000F43, + 0xF4400000F48, + 0xF4900000F4D, + 0xF4E00000F52, + 0xF5300000F57, + 0xF5800000F5C, + 0xF5D00000F69, + 0xF6A00000F6D, + 0xF7100000F73, + 0xF7400000F75, + 0xF7A00000F81, + 0xF8200000F85, + 0xF8600000F93, + 0xF9400000F98, + 0xF9900000F9D, + 0xF9E00000FA2, + 0xFA300000FA7, + 0xFA800000FAC, + 0xFAD00000FB9, + 0xFBA00000FBD, + 0xFC600000FC7, + 0x10000000104A, + 0x10500000109E, + 0x10D0000010FB, + 0x10FD00001100, + 0x120000001249, + 0x124A0000124E, + 0x125000001257, + 0x125800001259, + 0x125A0000125E, + 0x126000001289, + 0x128A0000128E, + 0x1290000012B1, + 0x12B2000012B6, + 0x12B8000012BF, + 0x12C0000012C1, + 0x12C2000012C6, + 0x12C8000012D7, + 0x12D800001311, + 0x131200001316, + 0x13180000135B, + 0x135D00001360, + 0x138000001390, + 0x13A0000013F6, + 0x14010000166D, + 0x166F00001680, + 0x16810000169B, + 0x16A0000016EB, + 0x16F1000016F9, + 0x170000001716, + 0x171F00001735, + 0x174000001754, + 0x17600000176D, + 0x176E00001771, + 0x177200001774, + 0x1780000017B4, + 0x17B6000017D4, + 0x17D7000017D8, + 0x17DC000017DE, + 0x17E0000017EA, + 0x18100000181A, + 0x182000001879, + 0x1880000018AB, + 0x18B0000018F6, + 0x19000000191F, + 0x19200000192C, + 0x19300000193C, + 0x19460000196E, + 0x197000001975, + 0x1980000019AC, + 0x19B0000019CA, + 0x19D0000019DA, + 0x1A0000001A1C, + 0x1A2000001A5F, + 0x1A6000001A7D, + 0x1A7F00001A8A, + 0x1A9000001A9A, + 0x1AA700001AA8, + 0x1AB000001ABE, + 0x1ABF00001ACF, + 0x1B0000001B4D, + 0x1B5000001B5A, + 0x1B6B00001B74, + 0x1B8000001BF4, + 0x1C0000001C38, + 0x1C4000001C4A, + 0x1C4D00001C7E, + 0x1CD000001CD3, + 0x1CD400001CFB, + 0x1D0000001D2C, + 0x1D2F00001D30, + 0x1D3B00001D3C, + 0x1D4E00001D4F, + 0x1D6B00001D78, + 0x1D7900001D9B, + 0x1DC000001E00, + 0x1E0100001E02, + 0x1E0300001E04, + 0x1E0500001E06, + 0x1E0700001E08, + 0x1E0900001E0A, + 0x1E0B00001E0C, + 0x1E0D00001E0E, + 0x1E0F00001E10, + 0x1E1100001E12, + 0x1E1300001E14, + 0x1E1500001E16, + 0x1E1700001E18, + 0x1E1900001E1A, + 0x1E1B00001E1C, + 0x1E1D00001E1E, + 0x1E1F00001E20, + 0x1E2100001E22, + 0x1E2300001E24, + 0x1E2500001E26, + 0x1E2700001E28, + 0x1E2900001E2A, + 0x1E2B00001E2C, + 0x1E2D00001E2E, + 0x1E2F00001E30, + 0x1E3100001E32, + 0x1E3300001E34, + 0x1E3500001E36, + 0x1E3700001E38, + 0x1E3900001E3A, + 0x1E3B00001E3C, + 0x1E3D00001E3E, + 0x1E3F00001E40, + 0x1E4100001E42, + 0x1E4300001E44, + 0x1E4500001E46, + 0x1E4700001E48, + 0x1E4900001E4A, + 0x1E4B00001E4C, + 0x1E4D00001E4E, + 0x1E4F00001E50, + 0x1E5100001E52, + 0x1E5300001E54, + 0x1E5500001E56, + 0x1E5700001E58, + 0x1E5900001E5A, + 0x1E5B00001E5C, + 0x1E5D00001E5E, + 0x1E5F00001E60, + 0x1E6100001E62, + 0x1E6300001E64, + 0x1E6500001E66, + 0x1E6700001E68, + 0x1E6900001E6A, + 0x1E6B00001E6C, + 0x1E6D00001E6E, + 0x1E6F00001E70, + 0x1E7100001E72, + 0x1E7300001E74, + 0x1E7500001E76, + 0x1E7700001E78, + 0x1E7900001E7A, + 0x1E7B00001E7C, + 0x1E7D00001E7E, + 0x1E7F00001E80, + 0x1E8100001E82, + 0x1E8300001E84, + 0x1E8500001E86, + 0x1E8700001E88, + 0x1E8900001E8A, + 0x1E8B00001E8C, + 0x1E8D00001E8E, + 0x1E8F00001E90, + 0x1E9100001E92, + 0x1E9300001E94, + 0x1E9500001E9A, + 0x1E9C00001E9E, + 0x1E9F00001EA0, + 0x1EA100001EA2, + 0x1EA300001EA4, + 0x1EA500001EA6, + 0x1EA700001EA8, + 0x1EA900001EAA, + 0x1EAB00001EAC, + 0x1EAD00001EAE, + 0x1EAF00001EB0, + 0x1EB100001EB2, + 0x1EB300001EB4, + 0x1EB500001EB6, + 0x1EB700001EB8, + 0x1EB900001EBA, + 0x1EBB00001EBC, + 0x1EBD00001EBE, + 0x1EBF00001EC0, + 0x1EC100001EC2, + 0x1EC300001EC4, + 0x1EC500001EC6, + 0x1EC700001EC8, + 0x1EC900001ECA, + 0x1ECB00001ECC, + 0x1ECD00001ECE, + 0x1ECF00001ED0, + 0x1ED100001ED2, + 0x1ED300001ED4, + 0x1ED500001ED6, + 0x1ED700001ED8, + 0x1ED900001EDA, + 0x1EDB00001EDC, + 0x1EDD00001EDE, + 0x1EDF00001EE0, + 0x1EE100001EE2, + 0x1EE300001EE4, + 0x1EE500001EE6, + 0x1EE700001EE8, + 0x1EE900001EEA, + 0x1EEB00001EEC, + 0x1EED00001EEE, + 0x1EEF00001EF0, + 0x1EF100001EF2, + 0x1EF300001EF4, + 0x1EF500001EF6, + 0x1EF700001EF8, + 0x1EF900001EFA, + 0x1EFB00001EFC, + 0x1EFD00001EFE, + 0x1EFF00001F08, + 0x1F1000001F16, + 0x1F2000001F28, + 0x1F3000001F38, + 0x1F4000001F46, + 0x1F5000001F58, + 0x1F6000001F68, + 0x1F7000001F71, + 0x1F7200001F73, + 0x1F7400001F75, + 0x1F7600001F77, + 0x1F7800001F79, + 0x1F7A00001F7B, + 0x1F7C00001F7D, + 0x1FB000001FB2, + 0x1FB600001FB7, + 0x1FC600001FC7, + 0x1FD000001FD3, + 0x1FD600001FD8, + 0x1FE000001FE3, + 0x1FE400001FE8, + 0x1FF600001FF7, + 0x214E0000214F, + 0x218400002185, + 0x2C3000002C60, + 0x2C6100002C62, + 0x2C6500002C67, + 0x2C6800002C69, + 0x2C6A00002C6B, + 0x2C6C00002C6D, + 0x2C7100002C72, + 0x2C7300002C75, + 0x2C7600002C7C, + 0x2C8100002C82, + 0x2C8300002C84, + 0x2C8500002C86, + 0x2C8700002C88, + 0x2C8900002C8A, + 0x2C8B00002C8C, + 0x2C8D00002C8E, + 0x2C8F00002C90, + 0x2C9100002C92, + 0x2C9300002C94, + 0x2C9500002C96, + 0x2C9700002C98, + 0x2C9900002C9A, + 0x2C9B00002C9C, + 0x2C9D00002C9E, + 0x2C9F00002CA0, + 0x2CA100002CA2, + 0x2CA300002CA4, + 0x2CA500002CA6, + 0x2CA700002CA8, + 0x2CA900002CAA, + 0x2CAB00002CAC, + 0x2CAD00002CAE, + 0x2CAF00002CB0, + 0x2CB100002CB2, + 0x2CB300002CB4, + 0x2CB500002CB6, + 0x2CB700002CB8, + 0x2CB900002CBA, + 0x2CBB00002CBC, + 0x2CBD00002CBE, + 0x2CBF00002CC0, + 0x2CC100002CC2, + 0x2CC300002CC4, + 0x2CC500002CC6, + 0x2CC700002CC8, + 0x2CC900002CCA, + 0x2CCB00002CCC, + 0x2CCD00002CCE, + 0x2CCF00002CD0, + 0x2CD100002CD2, + 0x2CD300002CD4, + 0x2CD500002CD6, + 0x2CD700002CD8, + 0x2CD900002CDA, + 0x2CDB00002CDC, + 0x2CDD00002CDE, + 0x2CDF00002CE0, + 0x2CE100002CE2, + 0x2CE300002CE5, + 0x2CEC00002CED, + 0x2CEE00002CF2, + 0x2CF300002CF4, + 0x2D0000002D26, + 0x2D2700002D28, + 0x2D2D00002D2E, + 0x2D3000002D68, + 0x2D7F00002D97, + 0x2DA000002DA7, + 0x2DA800002DAF, + 0x2DB000002DB7, + 0x2DB800002DBF, + 0x2DC000002DC7, + 0x2DC800002DCF, + 0x2DD000002DD7, + 0x2DD800002DDF, + 0x2DE000002E00, + 0x2E2F00002E30, + 0x300500003008, + 0x302A0000302E, + 0x303C0000303D, + 0x304100003097, + 0x30990000309B, + 0x309D0000309F, + 0x30A1000030FB, + 0x30FC000030FF, + 0x310500003130, + 0x31A0000031C0, + 0x31F000003200, + 0x340000004DC0, + 0x4E000000A48D, + 0xA4D00000A4FE, + 0xA5000000A60D, + 0xA6100000A62C, + 0xA6410000A642, + 0xA6430000A644, + 0xA6450000A646, + 0xA6470000A648, + 0xA6490000A64A, + 0xA64B0000A64C, + 0xA64D0000A64E, + 0xA64F0000A650, + 0xA6510000A652, + 0xA6530000A654, + 0xA6550000A656, + 0xA6570000A658, + 0xA6590000A65A, + 0xA65B0000A65C, + 0xA65D0000A65E, + 0xA65F0000A660, + 0xA6610000A662, + 0xA6630000A664, + 0xA6650000A666, + 0xA6670000A668, + 0xA6690000A66A, + 0xA66B0000A66C, + 0xA66D0000A670, + 0xA6740000A67E, + 0xA67F0000A680, + 0xA6810000A682, + 0xA6830000A684, + 0xA6850000A686, + 0xA6870000A688, + 0xA6890000A68A, + 0xA68B0000A68C, + 0xA68D0000A68E, + 0xA68F0000A690, + 0xA6910000A692, + 0xA6930000A694, + 0xA6950000A696, + 0xA6970000A698, + 0xA6990000A69A, + 0xA69B0000A69C, + 0xA69E0000A6E6, + 0xA6F00000A6F2, + 0xA7170000A720, + 0xA7230000A724, + 0xA7250000A726, + 0xA7270000A728, + 0xA7290000A72A, + 0xA72B0000A72C, + 0xA72D0000A72E, + 0xA72F0000A732, + 0xA7330000A734, + 0xA7350000A736, + 0xA7370000A738, + 0xA7390000A73A, + 0xA73B0000A73C, + 0xA73D0000A73E, + 0xA73F0000A740, + 0xA7410000A742, + 0xA7430000A744, + 0xA7450000A746, + 0xA7470000A748, + 0xA7490000A74A, + 0xA74B0000A74C, + 0xA74D0000A74E, + 0xA74F0000A750, + 0xA7510000A752, + 0xA7530000A754, + 0xA7550000A756, + 0xA7570000A758, + 0xA7590000A75A, + 0xA75B0000A75C, + 0xA75D0000A75E, + 0xA75F0000A760, + 0xA7610000A762, + 0xA7630000A764, + 0xA7650000A766, + 0xA7670000A768, + 0xA7690000A76A, + 0xA76B0000A76C, + 0xA76D0000A76E, + 0xA76F0000A770, + 0xA7710000A779, + 0xA77A0000A77B, + 0xA77C0000A77D, + 0xA77F0000A780, + 0xA7810000A782, + 0xA7830000A784, + 0xA7850000A786, + 0xA7870000A789, + 0xA78C0000A78D, + 0xA78E0000A790, + 0xA7910000A792, + 0xA7930000A796, + 0xA7970000A798, + 0xA7990000A79A, + 0xA79B0000A79C, + 0xA79D0000A79E, + 0xA79F0000A7A0, + 0xA7A10000A7A2, + 0xA7A30000A7A4, + 0xA7A50000A7A6, + 0xA7A70000A7A8, + 0xA7A90000A7AA, + 0xA7AF0000A7B0, + 0xA7B50000A7B6, + 0xA7B70000A7B8, + 0xA7B90000A7BA, + 0xA7BB0000A7BC, + 0xA7BD0000A7BE, + 0xA7BF0000A7C0, + 0xA7C10000A7C2, + 0xA7C30000A7C4, + 0xA7C80000A7C9, + 0xA7CA0000A7CB, + 0xA7D10000A7D2, + 0xA7D30000A7D4, + 0xA7D50000A7D6, + 0xA7D70000A7D8, + 0xA7D90000A7DA, + 0xA7F60000A7F8, + 0xA7FA0000A828, + 0xA82C0000A82D, + 0xA8400000A874, + 0xA8800000A8C6, + 0xA8D00000A8DA, + 0xA8E00000A8F8, + 0xA8FB0000A8FC, + 0xA8FD0000A92E, + 0xA9300000A954, + 0xA9800000A9C1, + 0xA9CF0000A9DA, + 0xA9E00000A9FF, + 0xAA000000AA37, + 0xAA400000AA4E, + 0xAA500000AA5A, + 0xAA600000AA77, + 0xAA7A0000AAC3, + 0xAADB0000AADE, + 0xAAE00000AAF0, + 0xAAF20000AAF7, + 0xAB010000AB07, + 0xAB090000AB0F, + 0xAB110000AB17, + 0xAB200000AB27, + 0xAB280000AB2F, + 0xAB300000AB5B, + 0xAB600000AB69, + 0xABC00000ABEB, + 0xABEC0000ABEE, + 0xABF00000ABFA, + 0xAC000000D7A4, + 0xFA0E0000FA10, + 0xFA110000FA12, + 0xFA130000FA15, + 0xFA1F0000FA20, + 0xFA210000FA22, + 0xFA230000FA25, + 0xFA270000FA2A, + 0xFB1E0000FB1F, + 0xFE200000FE30, + 0xFE730000FE74, + 0x100000001000C, + 0x1000D00010027, + 0x100280001003B, + 0x1003C0001003E, + 0x1003F0001004E, + 0x100500001005E, + 0x10080000100FB, + 0x101FD000101FE, + 0x102800001029D, + 0x102A0000102D1, + 0x102E0000102E1, + 0x1030000010320, + 0x1032D00010341, + 0x103420001034A, + 0x103500001037B, + 0x103800001039E, + 0x103A0000103C4, + 0x103C8000103D0, + 0x104280001049E, + 0x104A0000104AA, + 0x104D8000104FC, + 0x1050000010528, + 0x1053000010564, + 0x10597000105A2, + 0x105A3000105B2, + 0x105B3000105BA, + 0x105BB000105BD, + 0x1060000010737, + 0x1074000010756, + 0x1076000010768, + 0x1078000010781, + 0x1080000010806, + 0x1080800010809, + 0x1080A00010836, + 0x1083700010839, + 0x1083C0001083D, + 0x1083F00010856, + 0x1086000010877, + 0x108800001089F, + 0x108E0000108F3, + 0x108F4000108F6, + 0x1090000010916, + 0x109200001093A, + 0x10980000109B8, + 0x109BE000109C0, + 0x10A0000010A04, + 0x10A0500010A07, + 0x10A0C00010A14, + 0x10A1500010A18, + 0x10A1900010A36, + 0x10A3800010A3B, + 0x10A3F00010A40, + 0x10A6000010A7D, + 0x10A8000010A9D, + 0x10AC000010AC8, + 0x10AC900010AE7, + 0x10B0000010B36, + 0x10B4000010B56, + 0x10B6000010B73, + 0x10B8000010B92, + 0x10C0000010C49, + 0x10CC000010CF3, + 0x10D0000010D28, + 0x10D3000010D3A, + 0x10E8000010EAA, + 0x10EAB00010EAD, + 0x10EB000010EB2, + 0x10EFD00010F1D, + 0x10F2700010F28, + 0x10F3000010F51, + 0x10F7000010F86, + 0x10FB000010FC5, + 0x10FE000010FF7, + 0x1100000011047, + 0x1106600011076, + 0x1107F000110BB, + 0x110C2000110C3, + 0x110D0000110E9, + 0x110F0000110FA, + 0x1110000011135, + 0x1113600011140, + 0x1114400011148, + 0x1115000011174, + 0x1117600011177, + 0x11180000111C5, + 0x111C9000111CD, + 0x111CE000111DB, + 0x111DC000111DD, + 0x1120000011212, + 0x1121300011238, + 0x1123E00011242, + 0x1128000011287, + 0x1128800011289, + 0x1128A0001128E, + 0x1128F0001129E, + 0x1129F000112A9, + 0x112B0000112EB, + 0x112F0000112FA, + 0x1130000011304, + 0x113050001130D, + 0x1130F00011311, + 0x1131300011329, + 0x1132A00011331, + 0x1133200011334, + 0x113350001133A, + 0x1133B00011345, + 0x1134700011349, + 0x1134B0001134E, + 0x1135000011351, + 0x1135700011358, + 0x1135D00011364, + 0x113660001136D, + 0x1137000011375, + 0x114000001144B, + 0x114500001145A, + 0x1145E00011462, + 0x11480000114C6, + 0x114C7000114C8, + 0x114D0000114DA, + 0x11580000115B6, + 0x115B8000115C1, + 0x115D8000115DE, + 0x1160000011641, + 0x1164400011645, + 0x116500001165A, + 0x11680000116B9, + 0x116C0000116CA, + 0x117000001171B, + 0x1171D0001172C, + 0x117300001173A, + 0x1174000011747, + 0x118000001183B, + 0x118C0000118EA, + 0x118FF00011907, + 0x119090001190A, + 0x1190C00011914, + 0x1191500011917, + 0x1191800011936, + 0x1193700011939, + 0x1193B00011944, + 0x119500001195A, + 0x119A0000119A8, + 0x119AA000119D8, + 0x119DA000119E2, + 0x119E3000119E5, + 0x11A0000011A3F, + 0x11A4700011A48, + 0x11A5000011A9A, + 0x11A9D00011A9E, + 0x11AB000011AF9, + 0x11C0000011C09, + 0x11C0A00011C37, + 0x11C3800011C41, + 0x11C5000011C5A, + 0x11C7200011C90, + 0x11C9200011CA8, + 0x11CA900011CB7, + 0x11D0000011D07, + 0x11D0800011D0A, + 0x11D0B00011D37, + 0x11D3A00011D3B, + 0x11D3C00011D3E, + 0x11D3F00011D48, + 0x11D5000011D5A, + 0x11D6000011D66, + 0x11D6700011D69, + 0x11D6A00011D8F, + 0x11D9000011D92, + 0x11D9300011D99, + 0x11DA000011DAA, + 0x11EE000011EF7, + 0x11F0000011F11, + 0x11F1200011F3B, + 0x11F3E00011F43, + 0x11F5000011F5A, + 0x11FB000011FB1, + 0x120000001239A, + 0x1248000012544, + 0x12F9000012FF1, + 0x1300000013430, + 0x1344000013456, + 0x1440000014647, + 0x1680000016A39, + 0x16A4000016A5F, + 0x16A6000016A6A, + 0x16A7000016ABF, + 0x16AC000016ACA, + 0x16AD000016AEE, + 0x16AF000016AF5, + 0x16B0000016B37, + 0x16B4000016B44, + 0x16B5000016B5A, + 0x16B6300016B78, + 0x16B7D00016B90, + 0x16E6000016E80, + 0x16F0000016F4B, + 0x16F4F00016F88, + 0x16F8F00016FA0, + 0x16FE000016FE2, + 0x16FE300016FE5, + 0x16FF000016FF2, + 0x17000000187F8, + 0x1880000018CD6, + 0x18D0000018D09, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B123, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1B1550001B156, + 0x1B1640001B168, + 0x1B1700001B2FC, + 0x1BC000001BC6B, + 0x1BC700001BC7D, + 0x1BC800001BC89, + 0x1BC900001BC9A, + 0x1BC9D0001BC9F, + 0x1CF000001CF2E, + 0x1CF300001CF47, + 0x1DA000001DA37, + 0x1DA3B0001DA6D, + 0x1DA750001DA76, + 0x1DA840001DA85, + 0x1DA9B0001DAA0, + 0x1DAA10001DAB0, + 0x1DF000001DF1F, + 0x1DF250001DF2B, + 0x1E0000001E007, + 0x1E0080001E019, + 0x1E01B0001E022, + 0x1E0230001E025, + 0x1E0260001E02B, + 0x1E08F0001E090, + 0x1E1000001E12D, + 0x1E1300001E13E, + 0x1E1400001E14A, + 0x1E14E0001E14F, + 0x1E2900001E2AF, + 0x1E2C00001E2FA, + 0x1E4D00001E4FA, + 0x1E7E00001E7E7, + 0x1E7E80001E7EC, + 0x1E7ED0001E7EF, + 0x1E7F00001E7FF, + 0x1E8000001E8C5, + 0x1E8D00001E8D7, + 0x1E9220001E94C, + 0x1E9500001E95A, + 0x200000002A6E0, + 0x2A7000002B73A, + 0x2B7400002B81E, + 0x2B8200002CEA2, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x300000003134B, + 0x31350000323B0, + ), + "CONTEXTJ": (0x200C0000200E,), + "CONTEXTO": ( + 0xB7000000B8, + 0x37500000376, + 0x5F3000005F5, + 0x6600000066A, + 0x6F0000006FA, + 0x30FB000030FC, + ), +} diff --git a/venv/lib/python3.12/site-packages/idna/intranges.py b/venv/lib/python3.12/site-packages/idna/intranges.py new file mode 100644 index 0000000..7bfaa8d --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/intranges.py @@ -0,0 +1,57 @@ +""" +Given a list of integers, made up of (hopefully) a small number of long runs +of consecutive integers, compute a representation of the form +((start1, end1), (start2, end2) ...). Then answer the question "was x present +in the original list?" in time O(log(# runs)). +""" + +import bisect +from typing import List, Tuple + + +def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: + """Represent a list of integers as a sequence of ranges: + ((start_0, end_0), (start_1, end_1), ...), such that the original + integers are exactly those x such that start_i <= x < end_i for some i. + + Ranges are encoded as single integers (start << 32 | end), not as tuples. + """ + + sorted_list = sorted(list_) + ranges = [] + last_write = -1 + for i in range(len(sorted_list)): + if i + 1 < len(sorted_list): + if sorted_list[i] == sorted_list[i + 1] - 1: + continue + current_range = sorted_list[last_write + 1 : i + 1] + ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) + last_write = i + + return tuple(ranges) + + +def _encode_range(start: int, end: int) -> int: + return (start << 32) | end + + +def _decode_range(r: int) -> Tuple[int, int]: + return (r >> 32), (r & ((1 << 32) - 1)) + + +def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: + """Determine if `int_` falls into one of the ranges in `ranges`.""" + tuple_ = _encode_range(int_, 0) + pos = bisect.bisect_left(ranges, tuple_) + # we could be immediately ahead of a tuple (start, end) + # with start < int_ <= end + if pos > 0: + left, right = _decode_range(ranges[pos - 1]) + if left <= int_ < right: + return True + # or we could be immediately behind a tuple (int_, end) + if pos < len(ranges): + left, _ = _decode_range(ranges[pos]) + if left == int_: + return True + return False diff --git a/venv/lib/python3.12/site-packages/idna/package_data.py b/venv/lib/python3.12/site-packages/idna/package_data.py new file mode 100644 index 0000000..514ff7e --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/package_data.py @@ -0,0 +1 @@ +__version__ = "3.10" diff --git a/venv/lib/python3.12/site-packages/idna/py.typed b/venv/lib/python3.12/site-packages/idna/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/idna/uts46data.py b/venv/lib/python3.12/site-packages/idna/uts46data.py new file mode 100644 index 0000000..eb89432 --- /dev/null +++ b/venv/lib/python3.12/site-packages/idna/uts46data.py @@ -0,0 +1,8681 @@ +# This file is automatically generated by tools/idna-data +# vim: set fileencoding=utf-8 : + +from typing import List, Tuple, Union + +"""IDNA Mapping Table from UTS46.""" + + +__version__ = "15.1.0" + + +def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x0, "3"), + (0x1, "3"), + (0x2, "3"), + (0x3, "3"), + (0x4, "3"), + (0x5, "3"), + (0x6, "3"), + (0x7, "3"), + (0x8, "3"), + (0x9, "3"), + (0xA, "3"), + (0xB, "3"), + (0xC, "3"), + (0xD, "3"), + (0xE, "3"), + (0xF, "3"), + (0x10, "3"), + (0x11, "3"), + (0x12, "3"), + (0x13, "3"), + (0x14, "3"), + (0x15, "3"), + (0x16, "3"), + (0x17, "3"), + (0x18, "3"), + (0x19, "3"), + (0x1A, "3"), + (0x1B, "3"), + (0x1C, "3"), + (0x1D, "3"), + (0x1E, "3"), + (0x1F, "3"), + (0x20, "3"), + (0x21, "3"), + (0x22, "3"), + (0x23, "3"), + (0x24, "3"), + (0x25, "3"), + (0x26, "3"), + (0x27, "3"), + (0x28, "3"), + (0x29, "3"), + (0x2A, "3"), + (0x2B, "3"), + (0x2C, "3"), + (0x2D, "V"), + (0x2E, "V"), + (0x2F, "3"), + (0x30, "V"), + (0x31, "V"), + (0x32, "V"), + (0x33, "V"), + (0x34, "V"), + (0x35, "V"), + (0x36, "V"), + (0x37, "V"), + (0x38, "V"), + (0x39, "V"), + (0x3A, "3"), + (0x3B, "3"), + (0x3C, "3"), + (0x3D, "3"), + (0x3E, "3"), + (0x3F, "3"), + (0x40, "3"), + (0x41, "M", "a"), + (0x42, "M", "b"), + (0x43, "M", "c"), + (0x44, "M", "d"), + (0x45, "M", "e"), + (0x46, "M", "f"), + (0x47, "M", "g"), + (0x48, "M", "h"), + (0x49, "M", "i"), + (0x4A, "M", "j"), + (0x4B, "M", "k"), + (0x4C, "M", "l"), + (0x4D, "M", "m"), + (0x4E, "M", "n"), + (0x4F, "M", "o"), + (0x50, "M", "p"), + (0x51, "M", "q"), + (0x52, "M", "r"), + (0x53, "M", "s"), + (0x54, "M", "t"), + (0x55, "M", "u"), + (0x56, "M", "v"), + (0x57, "M", "w"), + (0x58, "M", "x"), + (0x59, "M", "y"), + (0x5A, "M", "z"), + (0x5B, "3"), + (0x5C, "3"), + (0x5D, "3"), + (0x5E, "3"), + (0x5F, "3"), + (0x60, "3"), + (0x61, "V"), + (0x62, "V"), + (0x63, "V"), + ] + + +def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x64, "V"), + (0x65, "V"), + (0x66, "V"), + (0x67, "V"), + (0x68, "V"), + (0x69, "V"), + (0x6A, "V"), + (0x6B, "V"), + (0x6C, "V"), + (0x6D, "V"), + (0x6E, "V"), + (0x6F, "V"), + (0x70, "V"), + (0x71, "V"), + (0x72, "V"), + (0x73, "V"), + (0x74, "V"), + (0x75, "V"), + (0x76, "V"), + (0x77, "V"), + (0x78, "V"), + (0x79, "V"), + (0x7A, "V"), + (0x7B, "3"), + (0x7C, "3"), + (0x7D, "3"), + (0x7E, "3"), + (0x7F, "3"), + (0x80, "X"), + (0x81, "X"), + (0x82, "X"), + (0x83, "X"), + (0x84, "X"), + (0x85, "X"), + (0x86, "X"), + (0x87, "X"), + (0x88, "X"), + (0x89, "X"), + (0x8A, "X"), + (0x8B, "X"), + (0x8C, "X"), + (0x8D, "X"), + (0x8E, "X"), + (0x8F, "X"), + (0x90, "X"), + (0x91, "X"), + (0x92, "X"), + (0x93, "X"), + (0x94, "X"), + (0x95, "X"), + (0x96, "X"), + (0x97, "X"), + (0x98, "X"), + (0x99, "X"), + (0x9A, "X"), + (0x9B, "X"), + (0x9C, "X"), + (0x9D, "X"), + (0x9E, "X"), + (0x9F, "X"), + (0xA0, "3", " "), + (0xA1, "V"), + (0xA2, "V"), + (0xA3, "V"), + (0xA4, "V"), + (0xA5, "V"), + (0xA6, "V"), + (0xA7, "V"), + (0xA8, "3", " ̈"), + (0xA9, "V"), + (0xAA, "M", "a"), + (0xAB, "V"), + (0xAC, "V"), + (0xAD, "I"), + (0xAE, "V"), + (0xAF, "3", " ̄"), + (0xB0, "V"), + (0xB1, "V"), + (0xB2, "M", "2"), + (0xB3, "M", "3"), + (0xB4, "3", " ́"), + (0xB5, "M", "μ"), + (0xB6, "V"), + (0xB7, "V"), + (0xB8, "3", " ̧"), + (0xB9, "M", "1"), + (0xBA, "M", "o"), + (0xBB, "V"), + (0xBC, "M", "1⁄4"), + (0xBD, "M", "1⁄2"), + (0xBE, "M", "3⁄4"), + (0xBF, "V"), + (0xC0, "M", "à"), + (0xC1, "M", "á"), + (0xC2, "M", "â"), + (0xC3, "M", "ã"), + (0xC4, "M", "ä"), + (0xC5, "M", "å"), + (0xC6, "M", "æ"), + (0xC7, "M", "ç"), + ] + + +def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xC8, "M", "è"), + (0xC9, "M", "é"), + (0xCA, "M", "ê"), + (0xCB, "M", "ë"), + (0xCC, "M", "ì"), + (0xCD, "M", "í"), + (0xCE, "M", "î"), + (0xCF, "M", "ï"), + (0xD0, "M", "ð"), + (0xD1, "M", "ñ"), + (0xD2, "M", "ò"), + (0xD3, "M", "ó"), + (0xD4, "M", "ô"), + (0xD5, "M", "õ"), + (0xD6, "M", "ö"), + (0xD7, "V"), + (0xD8, "M", "ø"), + (0xD9, "M", "ù"), + (0xDA, "M", "ú"), + (0xDB, "M", "û"), + (0xDC, "M", "ü"), + (0xDD, "M", "ý"), + (0xDE, "M", "þ"), + (0xDF, "D", "ss"), + (0xE0, "V"), + (0xE1, "V"), + (0xE2, "V"), + (0xE3, "V"), + (0xE4, "V"), + (0xE5, "V"), + (0xE6, "V"), + (0xE7, "V"), + (0xE8, "V"), + (0xE9, "V"), + (0xEA, "V"), + (0xEB, "V"), + (0xEC, "V"), + (0xED, "V"), + (0xEE, "V"), + (0xEF, "V"), + (0xF0, "V"), + (0xF1, "V"), + (0xF2, "V"), + (0xF3, "V"), + (0xF4, "V"), + (0xF5, "V"), + (0xF6, "V"), + (0xF7, "V"), + (0xF8, "V"), + (0xF9, "V"), + (0xFA, "V"), + (0xFB, "V"), + (0xFC, "V"), + (0xFD, "V"), + (0xFE, "V"), + (0xFF, "V"), + (0x100, "M", "ā"), + (0x101, "V"), + (0x102, "M", "ă"), + (0x103, "V"), + (0x104, "M", "ą"), + (0x105, "V"), + (0x106, "M", "ć"), + (0x107, "V"), + (0x108, "M", "ĉ"), + (0x109, "V"), + (0x10A, "M", "ċ"), + (0x10B, "V"), + (0x10C, "M", "č"), + (0x10D, "V"), + (0x10E, "M", "ď"), + (0x10F, "V"), + (0x110, "M", "đ"), + (0x111, "V"), + (0x112, "M", "ē"), + (0x113, "V"), + (0x114, "M", "ĕ"), + (0x115, "V"), + (0x116, "M", "ė"), + (0x117, "V"), + (0x118, "M", "ę"), + (0x119, "V"), + (0x11A, "M", "ě"), + (0x11B, "V"), + (0x11C, "M", "ĝ"), + (0x11D, "V"), + (0x11E, "M", "ğ"), + (0x11F, "V"), + (0x120, "M", "ġ"), + (0x121, "V"), + (0x122, "M", "ģ"), + (0x123, "V"), + (0x124, "M", "ĥ"), + (0x125, "V"), + (0x126, "M", "ħ"), + (0x127, "V"), + (0x128, "M", "ĩ"), + (0x129, "V"), + (0x12A, "M", "ī"), + (0x12B, "V"), + ] + + +def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x12C, "M", "ĭ"), + (0x12D, "V"), + (0x12E, "M", "į"), + (0x12F, "V"), + (0x130, "M", "i̇"), + (0x131, "V"), + (0x132, "M", "ij"), + (0x134, "M", "ĵ"), + (0x135, "V"), + (0x136, "M", "ķ"), + (0x137, "V"), + (0x139, "M", "ĺ"), + (0x13A, "V"), + (0x13B, "M", "ļ"), + (0x13C, "V"), + (0x13D, "M", "ľ"), + (0x13E, "V"), + (0x13F, "M", "l·"), + (0x141, "M", "ł"), + (0x142, "V"), + (0x143, "M", "ń"), + (0x144, "V"), + (0x145, "M", "ņ"), + (0x146, "V"), + (0x147, "M", "ň"), + (0x148, "V"), + (0x149, "M", "ʼn"), + (0x14A, "M", "ŋ"), + (0x14B, "V"), + (0x14C, "M", "ō"), + (0x14D, "V"), + (0x14E, "M", "ŏ"), + (0x14F, "V"), + (0x150, "M", "ő"), + (0x151, "V"), + (0x152, "M", "œ"), + (0x153, "V"), + (0x154, "M", "ŕ"), + (0x155, "V"), + (0x156, "M", "ŗ"), + (0x157, "V"), + (0x158, "M", "ř"), + (0x159, "V"), + (0x15A, "M", "ś"), + (0x15B, "V"), + (0x15C, "M", "ŝ"), + (0x15D, "V"), + (0x15E, "M", "ş"), + (0x15F, "V"), + (0x160, "M", "š"), + (0x161, "V"), + (0x162, "M", "ţ"), + (0x163, "V"), + (0x164, "M", "ť"), + (0x165, "V"), + (0x166, "M", "ŧ"), + (0x167, "V"), + (0x168, "M", "ũ"), + (0x169, "V"), + (0x16A, "M", "ū"), + (0x16B, "V"), + (0x16C, "M", "ŭ"), + (0x16D, "V"), + (0x16E, "M", "ů"), + (0x16F, "V"), + (0x170, "M", "ű"), + (0x171, "V"), + (0x172, "M", "ų"), + (0x173, "V"), + (0x174, "M", "ŵ"), + (0x175, "V"), + (0x176, "M", "ŷ"), + (0x177, "V"), + (0x178, "M", "ÿ"), + (0x179, "M", "ź"), + (0x17A, "V"), + (0x17B, "M", "ż"), + (0x17C, "V"), + (0x17D, "M", "ž"), + (0x17E, "V"), + (0x17F, "M", "s"), + (0x180, "V"), + (0x181, "M", "ɓ"), + (0x182, "M", "ƃ"), + (0x183, "V"), + (0x184, "M", "ƅ"), + (0x185, "V"), + (0x186, "M", "ɔ"), + (0x187, "M", "ƈ"), + (0x188, "V"), + (0x189, "M", "ɖ"), + (0x18A, "M", "ɗ"), + (0x18B, "M", "ƌ"), + (0x18C, "V"), + (0x18E, "M", "ǝ"), + (0x18F, "M", "ə"), + (0x190, "M", "ɛ"), + (0x191, "M", "ƒ"), + (0x192, "V"), + (0x193, "M", "ɠ"), + ] + + +def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x194, "M", "ɣ"), + (0x195, "V"), + (0x196, "M", "ɩ"), + (0x197, "M", "ɨ"), + (0x198, "M", "ƙ"), + (0x199, "V"), + (0x19C, "M", "ɯ"), + (0x19D, "M", "ɲ"), + (0x19E, "V"), + (0x19F, "M", "ɵ"), + (0x1A0, "M", "ơ"), + (0x1A1, "V"), + (0x1A2, "M", "ƣ"), + (0x1A3, "V"), + (0x1A4, "M", "ƥ"), + (0x1A5, "V"), + (0x1A6, "M", "ʀ"), + (0x1A7, "M", "ƨ"), + (0x1A8, "V"), + (0x1A9, "M", "ʃ"), + (0x1AA, "V"), + (0x1AC, "M", "ƭ"), + (0x1AD, "V"), + (0x1AE, "M", "ʈ"), + (0x1AF, "M", "ư"), + (0x1B0, "V"), + (0x1B1, "M", "ʊ"), + (0x1B2, "M", "ʋ"), + (0x1B3, "M", "ƴ"), + (0x1B4, "V"), + (0x1B5, "M", "ƶ"), + (0x1B6, "V"), + (0x1B7, "M", "ʒ"), + (0x1B8, "M", "ƹ"), + (0x1B9, "V"), + (0x1BC, "M", "ƽ"), + (0x1BD, "V"), + (0x1C4, "M", "dž"), + (0x1C7, "M", "lj"), + (0x1CA, "M", "nj"), + (0x1CD, "M", "ǎ"), + (0x1CE, "V"), + (0x1CF, "M", "ǐ"), + (0x1D0, "V"), + (0x1D1, "M", "ǒ"), + (0x1D2, "V"), + (0x1D3, "M", "ǔ"), + (0x1D4, "V"), + (0x1D5, "M", "ǖ"), + (0x1D6, "V"), + (0x1D7, "M", "ǘ"), + (0x1D8, "V"), + (0x1D9, "M", "ǚ"), + (0x1DA, "V"), + (0x1DB, "M", "ǜ"), + (0x1DC, "V"), + (0x1DE, "M", "ǟ"), + (0x1DF, "V"), + (0x1E0, "M", "ǡ"), + (0x1E1, "V"), + (0x1E2, "M", "ǣ"), + (0x1E3, "V"), + (0x1E4, "M", "ǥ"), + (0x1E5, "V"), + (0x1E6, "M", "ǧ"), + (0x1E7, "V"), + (0x1E8, "M", "ǩ"), + (0x1E9, "V"), + (0x1EA, "M", "ǫ"), + (0x1EB, "V"), + (0x1EC, "M", "ǭ"), + (0x1ED, "V"), + (0x1EE, "M", "ǯ"), + (0x1EF, "V"), + (0x1F1, "M", "dz"), + (0x1F4, "M", "ǵ"), + (0x1F5, "V"), + (0x1F6, "M", "ƕ"), + (0x1F7, "M", "ƿ"), + (0x1F8, "M", "ǹ"), + (0x1F9, "V"), + (0x1FA, "M", "ǻ"), + (0x1FB, "V"), + (0x1FC, "M", "ǽ"), + (0x1FD, "V"), + (0x1FE, "M", "ǿ"), + (0x1FF, "V"), + (0x200, "M", "ȁ"), + (0x201, "V"), + (0x202, "M", "ȃ"), + (0x203, "V"), + (0x204, "M", "ȅ"), + (0x205, "V"), + (0x206, "M", "ȇ"), + (0x207, "V"), + (0x208, "M", "ȉ"), + (0x209, "V"), + (0x20A, "M", "ȋ"), + (0x20B, "V"), + (0x20C, "M", "ȍ"), + ] + + +def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x20D, "V"), + (0x20E, "M", "ȏ"), + (0x20F, "V"), + (0x210, "M", "ȑ"), + (0x211, "V"), + (0x212, "M", "ȓ"), + (0x213, "V"), + (0x214, "M", "ȕ"), + (0x215, "V"), + (0x216, "M", "ȗ"), + (0x217, "V"), + (0x218, "M", "ș"), + (0x219, "V"), + (0x21A, "M", "ț"), + (0x21B, "V"), + (0x21C, "M", "ȝ"), + (0x21D, "V"), + (0x21E, "M", "ȟ"), + (0x21F, "V"), + (0x220, "M", "ƞ"), + (0x221, "V"), + (0x222, "M", "ȣ"), + (0x223, "V"), + (0x224, "M", "ȥ"), + (0x225, "V"), + (0x226, "M", "ȧ"), + (0x227, "V"), + (0x228, "M", "ȩ"), + (0x229, "V"), + (0x22A, "M", "ȫ"), + (0x22B, "V"), + (0x22C, "M", "ȭ"), + (0x22D, "V"), + (0x22E, "M", "ȯ"), + (0x22F, "V"), + (0x230, "M", "ȱ"), + (0x231, "V"), + (0x232, "M", "ȳ"), + (0x233, "V"), + (0x23A, "M", "ⱥ"), + (0x23B, "M", "ȼ"), + (0x23C, "V"), + (0x23D, "M", "ƚ"), + (0x23E, "M", "ⱦ"), + (0x23F, "V"), + (0x241, "M", "ɂ"), + (0x242, "V"), + (0x243, "M", "ƀ"), + (0x244, "M", "ʉ"), + (0x245, "M", "ʌ"), + (0x246, "M", "ɇ"), + (0x247, "V"), + (0x248, "M", "ɉ"), + (0x249, "V"), + (0x24A, "M", "ɋ"), + (0x24B, "V"), + (0x24C, "M", "ɍ"), + (0x24D, "V"), + (0x24E, "M", "ɏ"), + (0x24F, "V"), + (0x2B0, "M", "h"), + (0x2B1, "M", "ɦ"), + (0x2B2, "M", "j"), + (0x2B3, "M", "r"), + (0x2B4, "M", "ɹ"), + (0x2B5, "M", "ɻ"), + (0x2B6, "M", "ʁ"), + (0x2B7, "M", "w"), + (0x2B8, "M", "y"), + (0x2B9, "V"), + (0x2D8, "3", " ̆"), + (0x2D9, "3", " ̇"), + (0x2DA, "3", " ̊"), + (0x2DB, "3", " ̨"), + (0x2DC, "3", " ̃"), + (0x2DD, "3", " ̋"), + (0x2DE, "V"), + (0x2E0, "M", "ɣ"), + (0x2E1, "M", "l"), + (0x2E2, "M", "s"), + (0x2E3, "M", "x"), + (0x2E4, "M", "ʕ"), + (0x2E5, "V"), + (0x340, "M", "̀"), + (0x341, "M", "́"), + (0x342, "V"), + (0x343, "M", "̓"), + (0x344, "M", "̈́"), + (0x345, "M", "ι"), + (0x346, "V"), + (0x34F, "I"), + (0x350, "V"), + (0x370, "M", "ͱ"), + (0x371, "V"), + (0x372, "M", "ͳ"), + (0x373, "V"), + (0x374, "M", "ʹ"), + (0x375, "V"), + (0x376, "M", "ͷ"), + (0x377, "V"), + ] + + +def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x378, "X"), + (0x37A, "3", " ι"), + (0x37B, "V"), + (0x37E, "3", ";"), + (0x37F, "M", "ϳ"), + (0x380, "X"), + (0x384, "3", " ́"), + (0x385, "3", " ̈́"), + (0x386, "M", "ά"), + (0x387, "M", "·"), + (0x388, "M", "έ"), + (0x389, "M", "ή"), + (0x38A, "M", "ί"), + (0x38B, "X"), + (0x38C, "M", "ό"), + (0x38D, "X"), + (0x38E, "M", "ύ"), + (0x38F, "M", "ώ"), + (0x390, "V"), + (0x391, "M", "α"), + (0x392, "M", "β"), + (0x393, "M", "γ"), + (0x394, "M", "δ"), + (0x395, "M", "ε"), + (0x396, "M", "ζ"), + (0x397, "M", "η"), + (0x398, "M", "θ"), + (0x399, "M", "ι"), + (0x39A, "M", "κ"), + (0x39B, "M", "λ"), + (0x39C, "M", "μ"), + (0x39D, "M", "ν"), + (0x39E, "M", "ξ"), + (0x39F, "M", "ο"), + (0x3A0, "M", "π"), + (0x3A1, "M", "ρ"), + (0x3A2, "X"), + (0x3A3, "M", "σ"), + (0x3A4, "M", "τ"), + (0x3A5, "M", "υ"), + (0x3A6, "M", "φ"), + (0x3A7, "M", "χ"), + (0x3A8, "M", "ψ"), + (0x3A9, "M", "ω"), + (0x3AA, "M", "ϊ"), + (0x3AB, "M", "ϋ"), + (0x3AC, "V"), + (0x3C2, "D", "σ"), + (0x3C3, "V"), + (0x3CF, "M", "ϗ"), + (0x3D0, "M", "β"), + (0x3D1, "M", "θ"), + (0x3D2, "M", "υ"), + (0x3D3, "M", "ύ"), + (0x3D4, "M", "ϋ"), + (0x3D5, "M", "φ"), + (0x3D6, "M", "π"), + (0x3D7, "V"), + (0x3D8, "M", "ϙ"), + (0x3D9, "V"), + (0x3DA, "M", "ϛ"), + (0x3DB, "V"), + (0x3DC, "M", "ϝ"), + (0x3DD, "V"), + (0x3DE, "M", "ϟ"), + (0x3DF, "V"), + (0x3E0, "M", "ϡ"), + (0x3E1, "V"), + (0x3E2, "M", "ϣ"), + (0x3E3, "V"), + (0x3E4, "M", "ϥ"), + (0x3E5, "V"), + (0x3E6, "M", "ϧ"), + (0x3E7, "V"), + (0x3E8, "M", "ϩ"), + (0x3E9, "V"), + (0x3EA, "M", "ϫ"), + (0x3EB, "V"), + (0x3EC, "M", "ϭ"), + (0x3ED, "V"), + (0x3EE, "M", "ϯ"), + (0x3EF, "V"), + (0x3F0, "M", "κ"), + (0x3F1, "M", "ρ"), + (0x3F2, "M", "σ"), + (0x3F3, "V"), + (0x3F4, "M", "θ"), + (0x3F5, "M", "ε"), + (0x3F6, "V"), + (0x3F7, "M", "ϸ"), + (0x3F8, "V"), + (0x3F9, "M", "σ"), + (0x3FA, "M", "ϻ"), + (0x3FB, "V"), + (0x3FD, "M", "ͻ"), + (0x3FE, "M", "ͼ"), + (0x3FF, "M", "ͽ"), + (0x400, "M", "ѐ"), + (0x401, "M", "ё"), + (0x402, "M", "ђ"), + ] + + +def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x403, "M", "ѓ"), + (0x404, "M", "є"), + (0x405, "M", "ѕ"), + (0x406, "M", "і"), + (0x407, "M", "ї"), + (0x408, "M", "ј"), + (0x409, "M", "љ"), + (0x40A, "M", "њ"), + (0x40B, "M", "ћ"), + (0x40C, "M", "ќ"), + (0x40D, "M", "ѝ"), + (0x40E, "M", "ў"), + (0x40F, "M", "џ"), + (0x410, "M", "а"), + (0x411, "M", "б"), + (0x412, "M", "в"), + (0x413, "M", "г"), + (0x414, "M", "д"), + (0x415, "M", "е"), + (0x416, "M", "ж"), + (0x417, "M", "з"), + (0x418, "M", "и"), + (0x419, "M", "й"), + (0x41A, "M", "к"), + (0x41B, "M", "л"), + (0x41C, "M", "м"), + (0x41D, "M", "н"), + (0x41E, "M", "о"), + (0x41F, "M", "п"), + (0x420, "M", "р"), + (0x421, "M", "с"), + (0x422, "M", "т"), + (0x423, "M", "у"), + (0x424, "M", "ф"), + (0x425, "M", "х"), + (0x426, "M", "ц"), + (0x427, "M", "ч"), + (0x428, "M", "ш"), + (0x429, "M", "щ"), + (0x42A, "M", "ъ"), + (0x42B, "M", "ы"), + (0x42C, "M", "ь"), + (0x42D, "M", "э"), + (0x42E, "M", "ю"), + (0x42F, "M", "я"), + (0x430, "V"), + (0x460, "M", "ѡ"), + (0x461, "V"), + (0x462, "M", "ѣ"), + (0x463, "V"), + (0x464, "M", "ѥ"), + (0x465, "V"), + (0x466, "M", "ѧ"), + (0x467, "V"), + (0x468, "M", "ѩ"), + (0x469, "V"), + (0x46A, "M", "ѫ"), + (0x46B, "V"), + (0x46C, "M", "ѭ"), + (0x46D, "V"), + (0x46E, "M", "ѯ"), + (0x46F, "V"), + (0x470, "M", "ѱ"), + (0x471, "V"), + (0x472, "M", "ѳ"), + (0x473, "V"), + (0x474, "M", "ѵ"), + (0x475, "V"), + (0x476, "M", "ѷ"), + (0x477, "V"), + (0x478, "M", "ѹ"), + (0x479, "V"), + (0x47A, "M", "ѻ"), + (0x47B, "V"), + (0x47C, "M", "ѽ"), + (0x47D, "V"), + (0x47E, "M", "ѿ"), + (0x47F, "V"), + (0x480, "M", "ҁ"), + (0x481, "V"), + (0x48A, "M", "ҋ"), + (0x48B, "V"), + (0x48C, "M", "ҍ"), + (0x48D, "V"), + (0x48E, "M", "ҏ"), + (0x48F, "V"), + (0x490, "M", "ґ"), + (0x491, "V"), + (0x492, "M", "ғ"), + (0x493, "V"), + (0x494, "M", "ҕ"), + (0x495, "V"), + (0x496, "M", "җ"), + (0x497, "V"), + (0x498, "M", "ҙ"), + (0x499, "V"), + (0x49A, "M", "қ"), + (0x49B, "V"), + (0x49C, "M", "ҝ"), + (0x49D, "V"), + ] + + +def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x49E, "M", "ҟ"), + (0x49F, "V"), + (0x4A0, "M", "ҡ"), + (0x4A1, "V"), + (0x4A2, "M", "ң"), + (0x4A3, "V"), + (0x4A4, "M", "ҥ"), + (0x4A5, "V"), + (0x4A6, "M", "ҧ"), + (0x4A7, "V"), + (0x4A8, "M", "ҩ"), + (0x4A9, "V"), + (0x4AA, "M", "ҫ"), + (0x4AB, "V"), + (0x4AC, "M", "ҭ"), + (0x4AD, "V"), + (0x4AE, "M", "ү"), + (0x4AF, "V"), + (0x4B0, "M", "ұ"), + (0x4B1, "V"), + (0x4B2, "M", "ҳ"), + (0x4B3, "V"), + (0x4B4, "M", "ҵ"), + (0x4B5, "V"), + (0x4B6, "M", "ҷ"), + (0x4B7, "V"), + (0x4B8, "M", "ҹ"), + (0x4B9, "V"), + (0x4BA, "M", "һ"), + (0x4BB, "V"), + (0x4BC, "M", "ҽ"), + (0x4BD, "V"), + (0x4BE, "M", "ҿ"), + (0x4BF, "V"), + (0x4C0, "X"), + (0x4C1, "M", "ӂ"), + (0x4C2, "V"), + (0x4C3, "M", "ӄ"), + (0x4C4, "V"), + (0x4C5, "M", "ӆ"), + (0x4C6, "V"), + (0x4C7, "M", "ӈ"), + (0x4C8, "V"), + (0x4C9, "M", "ӊ"), + (0x4CA, "V"), + (0x4CB, "M", "ӌ"), + (0x4CC, "V"), + (0x4CD, "M", "ӎ"), + (0x4CE, "V"), + (0x4D0, "M", "ӑ"), + (0x4D1, "V"), + (0x4D2, "M", "ӓ"), + (0x4D3, "V"), + (0x4D4, "M", "ӕ"), + (0x4D5, "V"), + (0x4D6, "M", "ӗ"), + (0x4D7, "V"), + (0x4D8, "M", "ә"), + (0x4D9, "V"), + (0x4DA, "M", "ӛ"), + (0x4DB, "V"), + (0x4DC, "M", "ӝ"), + (0x4DD, "V"), + (0x4DE, "M", "ӟ"), + (0x4DF, "V"), + (0x4E0, "M", "ӡ"), + (0x4E1, "V"), + (0x4E2, "M", "ӣ"), + (0x4E3, "V"), + (0x4E4, "M", "ӥ"), + (0x4E5, "V"), + (0x4E6, "M", "ӧ"), + (0x4E7, "V"), + (0x4E8, "M", "ө"), + (0x4E9, "V"), + (0x4EA, "M", "ӫ"), + (0x4EB, "V"), + (0x4EC, "M", "ӭ"), + (0x4ED, "V"), + (0x4EE, "M", "ӯ"), + (0x4EF, "V"), + (0x4F0, "M", "ӱ"), + (0x4F1, "V"), + (0x4F2, "M", "ӳ"), + (0x4F3, "V"), + (0x4F4, "M", "ӵ"), + (0x4F5, "V"), + (0x4F6, "M", "ӷ"), + (0x4F7, "V"), + (0x4F8, "M", "ӹ"), + (0x4F9, "V"), + (0x4FA, "M", "ӻ"), + (0x4FB, "V"), + (0x4FC, "M", "ӽ"), + (0x4FD, "V"), + (0x4FE, "M", "ӿ"), + (0x4FF, "V"), + (0x500, "M", "ԁ"), + (0x501, "V"), + (0x502, "M", "ԃ"), + ] + + +def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x503, "V"), + (0x504, "M", "ԅ"), + (0x505, "V"), + (0x506, "M", "ԇ"), + (0x507, "V"), + (0x508, "M", "ԉ"), + (0x509, "V"), + (0x50A, "M", "ԋ"), + (0x50B, "V"), + (0x50C, "M", "ԍ"), + (0x50D, "V"), + (0x50E, "M", "ԏ"), + (0x50F, "V"), + (0x510, "M", "ԑ"), + (0x511, "V"), + (0x512, "M", "ԓ"), + (0x513, "V"), + (0x514, "M", "ԕ"), + (0x515, "V"), + (0x516, "M", "ԗ"), + (0x517, "V"), + (0x518, "M", "ԙ"), + (0x519, "V"), + (0x51A, "M", "ԛ"), + (0x51B, "V"), + (0x51C, "M", "ԝ"), + (0x51D, "V"), + (0x51E, "M", "ԟ"), + (0x51F, "V"), + (0x520, "M", "ԡ"), + (0x521, "V"), + (0x522, "M", "ԣ"), + (0x523, "V"), + (0x524, "M", "ԥ"), + (0x525, "V"), + (0x526, "M", "ԧ"), + (0x527, "V"), + (0x528, "M", "ԩ"), + (0x529, "V"), + (0x52A, "M", "ԫ"), + (0x52B, "V"), + (0x52C, "M", "ԭ"), + (0x52D, "V"), + (0x52E, "M", "ԯ"), + (0x52F, "V"), + (0x530, "X"), + (0x531, "M", "ա"), + (0x532, "M", "բ"), + (0x533, "M", "գ"), + (0x534, "M", "դ"), + (0x535, "M", "ե"), + (0x536, "M", "զ"), + (0x537, "M", "է"), + (0x538, "M", "ը"), + (0x539, "M", "թ"), + (0x53A, "M", "ժ"), + (0x53B, "M", "ի"), + (0x53C, "M", "լ"), + (0x53D, "M", "խ"), + (0x53E, "M", "ծ"), + (0x53F, "M", "կ"), + (0x540, "M", "հ"), + (0x541, "M", "ձ"), + (0x542, "M", "ղ"), + (0x543, "M", "ճ"), + (0x544, "M", "մ"), + (0x545, "M", "յ"), + (0x546, "M", "ն"), + (0x547, "M", "շ"), + (0x548, "M", "ո"), + (0x549, "M", "չ"), + (0x54A, "M", "պ"), + (0x54B, "M", "ջ"), + (0x54C, "M", "ռ"), + (0x54D, "M", "ս"), + (0x54E, "M", "վ"), + (0x54F, "M", "տ"), + (0x550, "M", "ր"), + (0x551, "M", "ց"), + (0x552, "M", "ւ"), + (0x553, "M", "փ"), + (0x554, "M", "ք"), + (0x555, "M", "օ"), + (0x556, "M", "ֆ"), + (0x557, "X"), + (0x559, "V"), + (0x587, "M", "եւ"), + (0x588, "V"), + (0x58B, "X"), + (0x58D, "V"), + (0x590, "X"), + (0x591, "V"), + (0x5C8, "X"), + (0x5D0, "V"), + (0x5EB, "X"), + (0x5EF, "V"), + (0x5F5, "X"), + (0x606, "V"), + (0x61C, "X"), + (0x61D, "V"), + ] + + +def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x675, "M", "اٴ"), + (0x676, "M", "وٴ"), + (0x677, "M", "ۇٴ"), + (0x678, "M", "يٴ"), + (0x679, "V"), + (0x6DD, "X"), + (0x6DE, "V"), + (0x70E, "X"), + (0x710, "V"), + (0x74B, "X"), + (0x74D, "V"), + (0x7B2, "X"), + (0x7C0, "V"), + (0x7FB, "X"), + (0x7FD, "V"), + (0x82E, "X"), + (0x830, "V"), + (0x83F, "X"), + (0x840, "V"), + (0x85C, "X"), + (0x85E, "V"), + (0x85F, "X"), + (0x860, "V"), + (0x86B, "X"), + (0x870, "V"), + (0x88F, "X"), + (0x898, "V"), + (0x8E2, "X"), + (0x8E3, "V"), + (0x958, "M", "क़"), + (0x959, "M", "ख़"), + (0x95A, "M", "ग़"), + (0x95B, "M", "ज़"), + (0x95C, "M", "ड़"), + (0x95D, "M", "ढ़"), + (0x95E, "M", "फ़"), + (0x95F, "M", "य़"), + (0x960, "V"), + (0x984, "X"), + (0x985, "V"), + (0x98D, "X"), + (0x98F, "V"), + (0x991, "X"), + (0x993, "V"), + (0x9A9, "X"), + (0x9AA, "V"), + (0x9B1, "X"), + (0x9B2, "V"), + (0x9B3, "X"), + (0x9B6, "V"), + (0x9BA, "X"), + (0x9BC, "V"), + (0x9C5, "X"), + (0x9C7, "V"), + (0x9C9, "X"), + (0x9CB, "V"), + (0x9CF, "X"), + (0x9D7, "V"), + (0x9D8, "X"), + (0x9DC, "M", "ড়"), + (0x9DD, "M", "ঢ়"), + (0x9DE, "X"), + (0x9DF, "M", "য়"), + (0x9E0, "V"), + (0x9E4, "X"), + (0x9E6, "V"), + (0x9FF, "X"), + (0xA01, "V"), + (0xA04, "X"), + (0xA05, "V"), + (0xA0B, "X"), + (0xA0F, "V"), + (0xA11, "X"), + (0xA13, "V"), + (0xA29, "X"), + (0xA2A, "V"), + (0xA31, "X"), + (0xA32, "V"), + (0xA33, "M", "ਲ਼"), + (0xA34, "X"), + (0xA35, "V"), + (0xA36, "M", "ਸ਼"), + (0xA37, "X"), + (0xA38, "V"), + (0xA3A, "X"), + (0xA3C, "V"), + (0xA3D, "X"), + (0xA3E, "V"), + (0xA43, "X"), + (0xA47, "V"), + (0xA49, "X"), + (0xA4B, "V"), + (0xA4E, "X"), + (0xA51, "V"), + (0xA52, "X"), + (0xA59, "M", "ਖ਼"), + (0xA5A, "M", "ਗ਼"), + (0xA5B, "M", "ਜ਼"), + (0xA5C, "V"), + (0xA5D, "X"), + ] + + +def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA5E, "M", "ਫ਼"), + (0xA5F, "X"), + (0xA66, "V"), + (0xA77, "X"), + (0xA81, "V"), + (0xA84, "X"), + (0xA85, "V"), + (0xA8E, "X"), + (0xA8F, "V"), + (0xA92, "X"), + (0xA93, "V"), + (0xAA9, "X"), + (0xAAA, "V"), + (0xAB1, "X"), + (0xAB2, "V"), + (0xAB4, "X"), + (0xAB5, "V"), + (0xABA, "X"), + (0xABC, "V"), + (0xAC6, "X"), + (0xAC7, "V"), + (0xACA, "X"), + (0xACB, "V"), + (0xACE, "X"), + (0xAD0, "V"), + (0xAD1, "X"), + (0xAE0, "V"), + (0xAE4, "X"), + (0xAE6, "V"), + (0xAF2, "X"), + (0xAF9, "V"), + (0xB00, "X"), + (0xB01, "V"), + (0xB04, "X"), + (0xB05, "V"), + (0xB0D, "X"), + (0xB0F, "V"), + (0xB11, "X"), + (0xB13, "V"), + (0xB29, "X"), + (0xB2A, "V"), + (0xB31, "X"), + (0xB32, "V"), + (0xB34, "X"), + (0xB35, "V"), + (0xB3A, "X"), + (0xB3C, "V"), + (0xB45, "X"), + (0xB47, "V"), + (0xB49, "X"), + (0xB4B, "V"), + (0xB4E, "X"), + (0xB55, "V"), + (0xB58, "X"), + (0xB5C, "M", "ଡ଼"), + (0xB5D, "M", "ଢ଼"), + (0xB5E, "X"), + (0xB5F, "V"), + (0xB64, "X"), + (0xB66, "V"), + (0xB78, "X"), + (0xB82, "V"), + (0xB84, "X"), + (0xB85, "V"), + (0xB8B, "X"), + (0xB8E, "V"), + (0xB91, "X"), + (0xB92, "V"), + (0xB96, "X"), + (0xB99, "V"), + (0xB9B, "X"), + (0xB9C, "V"), + (0xB9D, "X"), + (0xB9E, "V"), + (0xBA0, "X"), + (0xBA3, "V"), + (0xBA5, "X"), + (0xBA8, "V"), + (0xBAB, "X"), + (0xBAE, "V"), + (0xBBA, "X"), + (0xBBE, "V"), + (0xBC3, "X"), + (0xBC6, "V"), + (0xBC9, "X"), + (0xBCA, "V"), + (0xBCE, "X"), + (0xBD0, "V"), + (0xBD1, "X"), + (0xBD7, "V"), + (0xBD8, "X"), + (0xBE6, "V"), + (0xBFB, "X"), + (0xC00, "V"), + (0xC0D, "X"), + (0xC0E, "V"), + (0xC11, "X"), + (0xC12, "V"), + (0xC29, "X"), + (0xC2A, "V"), + ] + + +def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xC3A, "X"), + (0xC3C, "V"), + (0xC45, "X"), + (0xC46, "V"), + (0xC49, "X"), + (0xC4A, "V"), + (0xC4E, "X"), + (0xC55, "V"), + (0xC57, "X"), + (0xC58, "V"), + (0xC5B, "X"), + (0xC5D, "V"), + (0xC5E, "X"), + (0xC60, "V"), + (0xC64, "X"), + (0xC66, "V"), + (0xC70, "X"), + (0xC77, "V"), + (0xC8D, "X"), + (0xC8E, "V"), + (0xC91, "X"), + (0xC92, "V"), + (0xCA9, "X"), + (0xCAA, "V"), + (0xCB4, "X"), + (0xCB5, "V"), + (0xCBA, "X"), + (0xCBC, "V"), + (0xCC5, "X"), + (0xCC6, "V"), + (0xCC9, "X"), + (0xCCA, "V"), + (0xCCE, "X"), + (0xCD5, "V"), + (0xCD7, "X"), + (0xCDD, "V"), + (0xCDF, "X"), + (0xCE0, "V"), + (0xCE4, "X"), + (0xCE6, "V"), + (0xCF0, "X"), + (0xCF1, "V"), + (0xCF4, "X"), + (0xD00, "V"), + (0xD0D, "X"), + (0xD0E, "V"), + (0xD11, "X"), + (0xD12, "V"), + (0xD45, "X"), + (0xD46, "V"), + (0xD49, "X"), + (0xD4A, "V"), + (0xD50, "X"), + (0xD54, "V"), + (0xD64, "X"), + (0xD66, "V"), + (0xD80, "X"), + (0xD81, "V"), + (0xD84, "X"), + (0xD85, "V"), + (0xD97, "X"), + (0xD9A, "V"), + (0xDB2, "X"), + (0xDB3, "V"), + (0xDBC, "X"), + (0xDBD, "V"), + (0xDBE, "X"), + (0xDC0, "V"), + (0xDC7, "X"), + (0xDCA, "V"), + (0xDCB, "X"), + (0xDCF, "V"), + (0xDD5, "X"), + (0xDD6, "V"), + (0xDD7, "X"), + (0xDD8, "V"), + (0xDE0, "X"), + (0xDE6, "V"), + (0xDF0, "X"), + (0xDF2, "V"), + (0xDF5, "X"), + (0xE01, "V"), + (0xE33, "M", "ํา"), + (0xE34, "V"), + (0xE3B, "X"), + (0xE3F, "V"), + (0xE5C, "X"), + (0xE81, "V"), + (0xE83, "X"), + (0xE84, "V"), + (0xE85, "X"), + (0xE86, "V"), + (0xE8B, "X"), + (0xE8C, "V"), + (0xEA4, "X"), + (0xEA5, "V"), + (0xEA6, "X"), + (0xEA7, "V"), + (0xEB3, "M", "ໍາ"), + (0xEB4, "V"), + ] + + +def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xEBE, "X"), + (0xEC0, "V"), + (0xEC5, "X"), + (0xEC6, "V"), + (0xEC7, "X"), + (0xEC8, "V"), + (0xECF, "X"), + (0xED0, "V"), + (0xEDA, "X"), + (0xEDC, "M", "ຫນ"), + (0xEDD, "M", "ຫມ"), + (0xEDE, "V"), + (0xEE0, "X"), + (0xF00, "V"), + (0xF0C, "M", "་"), + (0xF0D, "V"), + (0xF43, "M", "གྷ"), + (0xF44, "V"), + (0xF48, "X"), + (0xF49, "V"), + (0xF4D, "M", "ཌྷ"), + (0xF4E, "V"), + (0xF52, "M", "དྷ"), + (0xF53, "V"), + (0xF57, "M", "བྷ"), + (0xF58, "V"), + (0xF5C, "M", "ཛྷ"), + (0xF5D, "V"), + (0xF69, "M", "ཀྵ"), + (0xF6A, "V"), + (0xF6D, "X"), + (0xF71, "V"), + (0xF73, "M", "ཱི"), + (0xF74, "V"), + (0xF75, "M", "ཱུ"), + (0xF76, "M", "ྲྀ"), + (0xF77, "M", "ྲཱྀ"), + (0xF78, "M", "ླྀ"), + (0xF79, "M", "ླཱྀ"), + (0xF7A, "V"), + (0xF81, "M", "ཱྀ"), + (0xF82, "V"), + (0xF93, "M", "ྒྷ"), + (0xF94, "V"), + (0xF98, "X"), + (0xF99, "V"), + (0xF9D, "M", "ྜྷ"), + (0xF9E, "V"), + (0xFA2, "M", "ྡྷ"), + (0xFA3, "V"), + (0xFA7, "M", "ྦྷ"), + (0xFA8, "V"), + (0xFAC, "M", "ྫྷ"), + (0xFAD, "V"), + (0xFB9, "M", "ྐྵ"), + (0xFBA, "V"), + (0xFBD, "X"), + (0xFBE, "V"), + (0xFCD, "X"), + (0xFCE, "V"), + (0xFDB, "X"), + (0x1000, "V"), + (0x10A0, "X"), + (0x10C7, "M", "ⴧ"), + (0x10C8, "X"), + (0x10CD, "M", "ⴭ"), + (0x10CE, "X"), + (0x10D0, "V"), + (0x10FC, "M", "ნ"), + (0x10FD, "V"), + (0x115F, "X"), + (0x1161, "V"), + (0x1249, "X"), + (0x124A, "V"), + (0x124E, "X"), + (0x1250, "V"), + (0x1257, "X"), + (0x1258, "V"), + (0x1259, "X"), + (0x125A, "V"), + (0x125E, "X"), + (0x1260, "V"), + (0x1289, "X"), + (0x128A, "V"), + (0x128E, "X"), + (0x1290, "V"), + (0x12B1, "X"), + (0x12B2, "V"), + (0x12B6, "X"), + (0x12B8, "V"), + (0x12BF, "X"), + (0x12C0, "V"), + (0x12C1, "X"), + (0x12C2, "V"), + (0x12C6, "X"), + (0x12C8, "V"), + (0x12D7, "X"), + (0x12D8, "V"), + (0x1311, "X"), + (0x1312, "V"), + ] + + +def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1316, "X"), + (0x1318, "V"), + (0x135B, "X"), + (0x135D, "V"), + (0x137D, "X"), + (0x1380, "V"), + (0x139A, "X"), + (0x13A0, "V"), + (0x13F6, "X"), + (0x13F8, "M", "Ᏸ"), + (0x13F9, "M", "Ᏹ"), + (0x13FA, "M", "Ᏺ"), + (0x13FB, "M", "Ᏻ"), + (0x13FC, "M", "Ᏼ"), + (0x13FD, "M", "Ᏽ"), + (0x13FE, "X"), + (0x1400, "V"), + (0x1680, "X"), + (0x1681, "V"), + (0x169D, "X"), + (0x16A0, "V"), + (0x16F9, "X"), + (0x1700, "V"), + (0x1716, "X"), + (0x171F, "V"), + (0x1737, "X"), + (0x1740, "V"), + (0x1754, "X"), + (0x1760, "V"), + (0x176D, "X"), + (0x176E, "V"), + (0x1771, "X"), + (0x1772, "V"), + (0x1774, "X"), + (0x1780, "V"), + (0x17B4, "X"), + (0x17B6, "V"), + (0x17DE, "X"), + (0x17E0, "V"), + (0x17EA, "X"), + (0x17F0, "V"), + (0x17FA, "X"), + (0x1800, "V"), + (0x1806, "X"), + (0x1807, "V"), + (0x180B, "I"), + (0x180E, "X"), + (0x180F, "I"), + (0x1810, "V"), + (0x181A, "X"), + (0x1820, "V"), + (0x1879, "X"), + (0x1880, "V"), + (0x18AB, "X"), + (0x18B0, "V"), + (0x18F6, "X"), + (0x1900, "V"), + (0x191F, "X"), + (0x1920, "V"), + (0x192C, "X"), + (0x1930, "V"), + (0x193C, "X"), + (0x1940, "V"), + (0x1941, "X"), + (0x1944, "V"), + (0x196E, "X"), + (0x1970, "V"), + (0x1975, "X"), + (0x1980, "V"), + (0x19AC, "X"), + (0x19B0, "V"), + (0x19CA, "X"), + (0x19D0, "V"), + (0x19DB, "X"), + (0x19DE, "V"), + (0x1A1C, "X"), + (0x1A1E, "V"), + (0x1A5F, "X"), + (0x1A60, "V"), + (0x1A7D, "X"), + (0x1A7F, "V"), + (0x1A8A, "X"), + (0x1A90, "V"), + (0x1A9A, "X"), + (0x1AA0, "V"), + (0x1AAE, "X"), + (0x1AB0, "V"), + (0x1ACF, "X"), + (0x1B00, "V"), + (0x1B4D, "X"), + (0x1B50, "V"), + (0x1B7F, "X"), + (0x1B80, "V"), + (0x1BF4, "X"), + (0x1BFC, "V"), + (0x1C38, "X"), + (0x1C3B, "V"), + (0x1C4A, "X"), + (0x1C4D, "V"), + (0x1C80, "M", "в"), + ] + + +def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1C81, "M", "д"), + (0x1C82, "M", "о"), + (0x1C83, "M", "с"), + (0x1C84, "M", "т"), + (0x1C86, "M", "ъ"), + (0x1C87, "M", "ѣ"), + (0x1C88, "M", "ꙋ"), + (0x1C89, "X"), + (0x1C90, "M", "ა"), + (0x1C91, "M", "ბ"), + (0x1C92, "M", "გ"), + (0x1C93, "M", "დ"), + (0x1C94, "M", "ე"), + (0x1C95, "M", "ვ"), + (0x1C96, "M", "ზ"), + (0x1C97, "M", "თ"), + (0x1C98, "M", "ი"), + (0x1C99, "M", "კ"), + (0x1C9A, "M", "ლ"), + (0x1C9B, "M", "მ"), + (0x1C9C, "M", "ნ"), + (0x1C9D, "M", "ო"), + (0x1C9E, "M", "პ"), + (0x1C9F, "M", "ჟ"), + (0x1CA0, "M", "რ"), + (0x1CA1, "M", "ს"), + (0x1CA2, "M", "ტ"), + (0x1CA3, "M", "უ"), + (0x1CA4, "M", "ფ"), + (0x1CA5, "M", "ქ"), + (0x1CA6, "M", "ღ"), + (0x1CA7, "M", "ყ"), + (0x1CA8, "M", "შ"), + (0x1CA9, "M", "ჩ"), + (0x1CAA, "M", "ც"), + (0x1CAB, "M", "ძ"), + (0x1CAC, "M", "წ"), + (0x1CAD, "M", "ჭ"), + (0x1CAE, "M", "ხ"), + (0x1CAF, "M", "ჯ"), + (0x1CB0, "M", "ჰ"), + (0x1CB1, "M", "ჱ"), + (0x1CB2, "M", "ჲ"), + (0x1CB3, "M", "ჳ"), + (0x1CB4, "M", "ჴ"), + (0x1CB5, "M", "ჵ"), + (0x1CB6, "M", "ჶ"), + (0x1CB7, "M", "ჷ"), + (0x1CB8, "M", "ჸ"), + (0x1CB9, "M", "ჹ"), + (0x1CBA, "M", "ჺ"), + (0x1CBB, "X"), + (0x1CBD, "M", "ჽ"), + (0x1CBE, "M", "ჾ"), + (0x1CBF, "M", "ჿ"), + (0x1CC0, "V"), + (0x1CC8, "X"), + (0x1CD0, "V"), + (0x1CFB, "X"), + (0x1D00, "V"), + (0x1D2C, "M", "a"), + (0x1D2D, "M", "æ"), + (0x1D2E, "M", "b"), + (0x1D2F, "V"), + (0x1D30, "M", "d"), + (0x1D31, "M", "e"), + (0x1D32, "M", "ǝ"), + (0x1D33, "M", "g"), + (0x1D34, "M", "h"), + (0x1D35, "M", "i"), + (0x1D36, "M", "j"), + (0x1D37, "M", "k"), + (0x1D38, "M", "l"), + (0x1D39, "M", "m"), + (0x1D3A, "M", "n"), + (0x1D3B, "V"), + (0x1D3C, "M", "o"), + (0x1D3D, "M", "ȣ"), + (0x1D3E, "M", "p"), + (0x1D3F, "M", "r"), + (0x1D40, "M", "t"), + (0x1D41, "M", "u"), + (0x1D42, "M", "w"), + (0x1D43, "M", "a"), + (0x1D44, "M", "ɐ"), + (0x1D45, "M", "ɑ"), + (0x1D46, "M", "ᴂ"), + (0x1D47, "M", "b"), + (0x1D48, "M", "d"), + (0x1D49, "M", "e"), + (0x1D4A, "M", "ə"), + (0x1D4B, "M", "ɛ"), + (0x1D4C, "M", "ɜ"), + (0x1D4D, "M", "g"), + (0x1D4E, "V"), + (0x1D4F, "M", "k"), + (0x1D50, "M", "m"), + (0x1D51, "M", "ŋ"), + (0x1D52, "M", "o"), + (0x1D53, "M", "ɔ"), + ] + + +def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D54, "M", "ᴖ"), + (0x1D55, "M", "ᴗ"), + (0x1D56, "M", "p"), + (0x1D57, "M", "t"), + (0x1D58, "M", "u"), + (0x1D59, "M", "ᴝ"), + (0x1D5A, "M", "ɯ"), + (0x1D5B, "M", "v"), + (0x1D5C, "M", "ᴥ"), + (0x1D5D, "M", "β"), + (0x1D5E, "M", "γ"), + (0x1D5F, "M", "δ"), + (0x1D60, "M", "φ"), + (0x1D61, "M", "χ"), + (0x1D62, "M", "i"), + (0x1D63, "M", "r"), + (0x1D64, "M", "u"), + (0x1D65, "M", "v"), + (0x1D66, "M", "β"), + (0x1D67, "M", "γ"), + (0x1D68, "M", "ρ"), + (0x1D69, "M", "φ"), + (0x1D6A, "M", "χ"), + (0x1D6B, "V"), + (0x1D78, "M", "н"), + (0x1D79, "V"), + (0x1D9B, "M", "ɒ"), + (0x1D9C, "M", "c"), + (0x1D9D, "M", "ɕ"), + (0x1D9E, "M", "ð"), + (0x1D9F, "M", "ɜ"), + (0x1DA0, "M", "f"), + (0x1DA1, "M", "ɟ"), + (0x1DA2, "M", "ɡ"), + (0x1DA3, "M", "ɥ"), + (0x1DA4, "M", "ɨ"), + (0x1DA5, "M", "ɩ"), + (0x1DA6, "M", "ɪ"), + (0x1DA7, "M", "ᵻ"), + (0x1DA8, "M", "ʝ"), + (0x1DA9, "M", "ɭ"), + (0x1DAA, "M", "ᶅ"), + (0x1DAB, "M", "ʟ"), + (0x1DAC, "M", "ɱ"), + (0x1DAD, "M", "ɰ"), + (0x1DAE, "M", "ɲ"), + (0x1DAF, "M", "ɳ"), + (0x1DB0, "M", "ɴ"), + (0x1DB1, "M", "ɵ"), + (0x1DB2, "M", "ɸ"), + (0x1DB3, "M", "ʂ"), + (0x1DB4, "M", "ʃ"), + (0x1DB5, "M", "ƫ"), + (0x1DB6, "M", "ʉ"), + (0x1DB7, "M", "ʊ"), + (0x1DB8, "M", "ᴜ"), + (0x1DB9, "M", "ʋ"), + (0x1DBA, "M", "ʌ"), + (0x1DBB, "M", "z"), + (0x1DBC, "M", "ʐ"), + (0x1DBD, "M", "ʑ"), + (0x1DBE, "M", "ʒ"), + (0x1DBF, "M", "θ"), + (0x1DC0, "V"), + (0x1E00, "M", "ḁ"), + (0x1E01, "V"), + (0x1E02, "M", "ḃ"), + (0x1E03, "V"), + (0x1E04, "M", "ḅ"), + (0x1E05, "V"), + (0x1E06, "M", "ḇ"), + (0x1E07, "V"), + (0x1E08, "M", "ḉ"), + (0x1E09, "V"), + (0x1E0A, "M", "ḋ"), + (0x1E0B, "V"), + (0x1E0C, "M", "ḍ"), + (0x1E0D, "V"), + (0x1E0E, "M", "ḏ"), + (0x1E0F, "V"), + (0x1E10, "M", "ḑ"), + (0x1E11, "V"), + (0x1E12, "M", "ḓ"), + (0x1E13, "V"), + (0x1E14, "M", "ḕ"), + (0x1E15, "V"), + (0x1E16, "M", "ḗ"), + (0x1E17, "V"), + (0x1E18, "M", "ḙ"), + (0x1E19, "V"), + (0x1E1A, "M", "ḛ"), + (0x1E1B, "V"), + (0x1E1C, "M", "ḝ"), + (0x1E1D, "V"), + (0x1E1E, "M", "ḟ"), + (0x1E1F, "V"), + (0x1E20, "M", "ḡ"), + (0x1E21, "V"), + (0x1E22, "M", "ḣ"), + (0x1E23, "V"), + ] + + +def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E24, "M", "ḥ"), + (0x1E25, "V"), + (0x1E26, "M", "ḧ"), + (0x1E27, "V"), + (0x1E28, "M", "ḩ"), + (0x1E29, "V"), + (0x1E2A, "M", "ḫ"), + (0x1E2B, "V"), + (0x1E2C, "M", "ḭ"), + (0x1E2D, "V"), + (0x1E2E, "M", "ḯ"), + (0x1E2F, "V"), + (0x1E30, "M", "ḱ"), + (0x1E31, "V"), + (0x1E32, "M", "ḳ"), + (0x1E33, "V"), + (0x1E34, "M", "ḵ"), + (0x1E35, "V"), + (0x1E36, "M", "ḷ"), + (0x1E37, "V"), + (0x1E38, "M", "ḹ"), + (0x1E39, "V"), + (0x1E3A, "M", "ḻ"), + (0x1E3B, "V"), + (0x1E3C, "M", "ḽ"), + (0x1E3D, "V"), + (0x1E3E, "M", "ḿ"), + (0x1E3F, "V"), + (0x1E40, "M", "ṁ"), + (0x1E41, "V"), + (0x1E42, "M", "ṃ"), + (0x1E43, "V"), + (0x1E44, "M", "ṅ"), + (0x1E45, "V"), + (0x1E46, "M", "ṇ"), + (0x1E47, "V"), + (0x1E48, "M", "ṉ"), + (0x1E49, "V"), + (0x1E4A, "M", "ṋ"), + (0x1E4B, "V"), + (0x1E4C, "M", "ṍ"), + (0x1E4D, "V"), + (0x1E4E, "M", "ṏ"), + (0x1E4F, "V"), + (0x1E50, "M", "ṑ"), + (0x1E51, "V"), + (0x1E52, "M", "ṓ"), + (0x1E53, "V"), + (0x1E54, "M", "ṕ"), + (0x1E55, "V"), + (0x1E56, "M", "ṗ"), + (0x1E57, "V"), + (0x1E58, "M", "ṙ"), + (0x1E59, "V"), + (0x1E5A, "M", "ṛ"), + (0x1E5B, "V"), + (0x1E5C, "M", "ṝ"), + (0x1E5D, "V"), + (0x1E5E, "M", "ṟ"), + (0x1E5F, "V"), + (0x1E60, "M", "ṡ"), + (0x1E61, "V"), + (0x1E62, "M", "ṣ"), + (0x1E63, "V"), + (0x1E64, "M", "ṥ"), + (0x1E65, "V"), + (0x1E66, "M", "ṧ"), + (0x1E67, "V"), + (0x1E68, "M", "ṩ"), + (0x1E69, "V"), + (0x1E6A, "M", "ṫ"), + (0x1E6B, "V"), + (0x1E6C, "M", "ṭ"), + (0x1E6D, "V"), + (0x1E6E, "M", "ṯ"), + (0x1E6F, "V"), + (0x1E70, "M", "ṱ"), + (0x1E71, "V"), + (0x1E72, "M", "ṳ"), + (0x1E73, "V"), + (0x1E74, "M", "ṵ"), + (0x1E75, "V"), + (0x1E76, "M", "ṷ"), + (0x1E77, "V"), + (0x1E78, "M", "ṹ"), + (0x1E79, "V"), + (0x1E7A, "M", "ṻ"), + (0x1E7B, "V"), + (0x1E7C, "M", "ṽ"), + (0x1E7D, "V"), + (0x1E7E, "M", "ṿ"), + (0x1E7F, "V"), + (0x1E80, "M", "ẁ"), + (0x1E81, "V"), + (0x1E82, "M", "ẃ"), + (0x1E83, "V"), + (0x1E84, "M", "ẅ"), + (0x1E85, "V"), + (0x1E86, "M", "ẇ"), + (0x1E87, "V"), + ] + + +def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E88, "M", "ẉ"), + (0x1E89, "V"), + (0x1E8A, "M", "ẋ"), + (0x1E8B, "V"), + (0x1E8C, "M", "ẍ"), + (0x1E8D, "V"), + (0x1E8E, "M", "ẏ"), + (0x1E8F, "V"), + (0x1E90, "M", "ẑ"), + (0x1E91, "V"), + (0x1E92, "M", "ẓ"), + (0x1E93, "V"), + (0x1E94, "M", "ẕ"), + (0x1E95, "V"), + (0x1E9A, "M", "aʾ"), + (0x1E9B, "M", "ṡ"), + (0x1E9C, "V"), + (0x1E9E, "M", "ß"), + (0x1E9F, "V"), + (0x1EA0, "M", "ạ"), + (0x1EA1, "V"), + (0x1EA2, "M", "ả"), + (0x1EA3, "V"), + (0x1EA4, "M", "ấ"), + (0x1EA5, "V"), + (0x1EA6, "M", "ầ"), + (0x1EA7, "V"), + (0x1EA8, "M", "ẩ"), + (0x1EA9, "V"), + (0x1EAA, "M", "ẫ"), + (0x1EAB, "V"), + (0x1EAC, "M", "ậ"), + (0x1EAD, "V"), + (0x1EAE, "M", "ắ"), + (0x1EAF, "V"), + (0x1EB0, "M", "ằ"), + (0x1EB1, "V"), + (0x1EB2, "M", "ẳ"), + (0x1EB3, "V"), + (0x1EB4, "M", "ẵ"), + (0x1EB5, "V"), + (0x1EB6, "M", "ặ"), + (0x1EB7, "V"), + (0x1EB8, "M", "ẹ"), + (0x1EB9, "V"), + (0x1EBA, "M", "ẻ"), + (0x1EBB, "V"), + (0x1EBC, "M", "ẽ"), + (0x1EBD, "V"), + (0x1EBE, "M", "ế"), + (0x1EBF, "V"), + (0x1EC0, "M", "ề"), + (0x1EC1, "V"), + (0x1EC2, "M", "ể"), + (0x1EC3, "V"), + (0x1EC4, "M", "ễ"), + (0x1EC5, "V"), + (0x1EC6, "M", "ệ"), + (0x1EC7, "V"), + (0x1EC8, "M", "ỉ"), + (0x1EC9, "V"), + (0x1ECA, "M", "ị"), + (0x1ECB, "V"), + (0x1ECC, "M", "ọ"), + (0x1ECD, "V"), + (0x1ECE, "M", "ỏ"), + (0x1ECF, "V"), + (0x1ED0, "M", "ố"), + (0x1ED1, "V"), + (0x1ED2, "M", "ồ"), + (0x1ED3, "V"), + (0x1ED4, "M", "ổ"), + (0x1ED5, "V"), + (0x1ED6, "M", "ỗ"), + (0x1ED7, "V"), + (0x1ED8, "M", "ộ"), + (0x1ED9, "V"), + (0x1EDA, "M", "ớ"), + (0x1EDB, "V"), + (0x1EDC, "M", "ờ"), + (0x1EDD, "V"), + (0x1EDE, "M", "ở"), + (0x1EDF, "V"), + (0x1EE0, "M", "ỡ"), + (0x1EE1, "V"), + (0x1EE2, "M", "ợ"), + (0x1EE3, "V"), + (0x1EE4, "M", "ụ"), + (0x1EE5, "V"), + (0x1EE6, "M", "ủ"), + (0x1EE7, "V"), + (0x1EE8, "M", "ứ"), + (0x1EE9, "V"), + (0x1EEA, "M", "ừ"), + (0x1EEB, "V"), + (0x1EEC, "M", "ử"), + (0x1EED, "V"), + (0x1EEE, "M", "ữ"), + (0x1EEF, "V"), + (0x1EF0, "M", "ự"), + ] + + +def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EF1, "V"), + (0x1EF2, "M", "ỳ"), + (0x1EF3, "V"), + (0x1EF4, "M", "ỵ"), + (0x1EF5, "V"), + (0x1EF6, "M", "ỷ"), + (0x1EF7, "V"), + (0x1EF8, "M", "ỹ"), + (0x1EF9, "V"), + (0x1EFA, "M", "ỻ"), + (0x1EFB, "V"), + (0x1EFC, "M", "ỽ"), + (0x1EFD, "V"), + (0x1EFE, "M", "ỿ"), + (0x1EFF, "V"), + (0x1F08, "M", "ἀ"), + (0x1F09, "M", "ἁ"), + (0x1F0A, "M", "ἂ"), + (0x1F0B, "M", "ἃ"), + (0x1F0C, "M", "ἄ"), + (0x1F0D, "M", "ἅ"), + (0x1F0E, "M", "ἆ"), + (0x1F0F, "M", "ἇ"), + (0x1F10, "V"), + (0x1F16, "X"), + (0x1F18, "M", "ἐ"), + (0x1F19, "M", "ἑ"), + (0x1F1A, "M", "ἒ"), + (0x1F1B, "M", "ἓ"), + (0x1F1C, "M", "ἔ"), + (0x1F1D, "M", "ἕ"), + (0x1F1E, "X"), + (0x1F20, "V"), + (0x1F28, "M", "ἠ"), + (0x1F29, "M", "ἡ"), + (0x1F2A, "M", "ἢ"), + (0x1F2B, "M", "ἣ"), + (0x1F2C, "M", "ἤ"), + (0x1F2D, "M", "ἥ"), + (0x1F2E, "M", "ἦ"), + (0x1F2F, "M", "ἧ"), + (0x1F30, "V"), + (0x1F38, "M", "ἰ"), + (0x1F39, "M", "ἱ"), + (0x1F3A, "M", "ἲ"), + (0x1F3B, "M", "ἳ"), + (0x1F3C, "M", "ἴ"), + (0x1F3D, "M", "ἵ"), + (0x1F3E, "M", "ἶ"), + (0x1F3F, "M", "ἷ"), + (0x1F40, "V"), + (0x1F46, "X"), + (0x1F48, "M", "ὀ"), + (0x1F49, "M", "ὁ"), + (0x1F4A, "M", "ὂ"), + (0x1F4B, "M", "ὃ"), + (0x1F4C, "M", "ὄ"), + (0x1F4D, "M", "ὅ"), + (0x1F4E, "X"), + (0x1F50, "V"), + (0x1F58, "X"), + (0x1F59, "M", "ὑ"), + (0x1F5A, "X"), + (0x1F5B, "M", "ὓ"), + (0x1F5C, "X"), + (0x1F5D, "M", "ὕ"), + (0x1F5E, "X"), + (0x1F5F, "M", "ὗ"), + (0x1F60, "V"), + (0x1F68, "M", "ὠ"), + (0x1F69, "M", "ὡ"), + (0x1F6A, "M", "ὢ"), + (0x1F6B, "M", "ὣ"), + (0x1F6C, "M", "ὤ"), + (0x1F6D, "M", "ὥ"), + (0x1F6E, "M", "ὦ"), + (0x1F6F, "M", "ὧ"), + (0x1F70, "V"), + (0x1F71, "M", "ά"), + (0x1F72, "V"), + (0x1F73, "M", "έ"), + (0x1F74, "V"), + (0x1F75, "M", "ή"), + (0x1F76, "V"), + (0x1F77, "M", "ί"), + (0x1F78, "V"), + (0x1F79, "M", "ό"), + (0x1F7A, "V"), + (0x1F7B, "M", "ύ"), + (0x1F7C, "V"), + (0x1F7D, "M", "ώ"), + (0x1F7E, "X"), + (0x1F80, "M", "ἀι"), + (0x1F81, "M", "ἁι"), + (0x1F82, "M", "ἂι"), + (0x1F83, "M", "ἃι"), + (0x1F84, "M", "ἄι"), + (0x1F85, "M", "ἅι"), + (0x1F86, "M", "ἆι"), + (0x1F87, "M", "ἇι"), + ] + + +def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1F88, "M", "ἀι"), + (0x1F89, "M", "ἁι"), + (0x1F8A, "M", "ἂι"), + (0x1F8B, "M", "ἃι"), + (0x1F8C, "M", "ἄι"), + (0x1F8D, "M", "ἅι"), + (0x1F8E, "M", "ἆι"), + (0x1F8F, "M", "ἇι"), + (0x1F90, "M", "ἠι"), + (0x1F91, "M", "ἡι"), + (0x1F92, "M", "ἢι"), + (0x1F93, "M", "ἣι"), + (0x1F94, "M", "ἤι"), + (0x1F95, "M", "ἥι"), + (0x1F96, "M", "ἦι"), + (0x1F97, "M", "ἧι"), + (0x1F98, "M", "ἠι"), + (0x1F99, "M", "ἡι"), + (0x1F9A, "M", "ἢι"), + (0x1F9B, "M", "ἣι"), + (0x1F9C, "M", "ἤι"), + (0x1F9D, "M", "ἥι"), + (0x1F9E, "M", "ἦι"), + (0x1F9F, "M", "ἧι"), + (0x1FA0, "M", "ὠι"), + (0x1FA1, "M", "ὡι"), + (0x1FA2, "M", "ὢι"), + (0x1FA3, "M", "ὣι"), + (0x1FA4, "M", "ὤι"), + (0x1FA5, "M", "ὥι"), + (0x1FA6, "M", "ὦι"), + (0x1FA7, "M", "ὧι"), + (0x1FA8, "M", "ὠι"), + (0x1FA9, "M", "ὡι"), + (0x1FAA, "M", "ὢι"), + (0x1FAB, "M", "ὣι"), + (0x1FAC, "M", "ὤι"), + (0x1FAD, "M", "ὥι"), + (0x1FAE, "M", "ὦι"), + (0x1FAF, "M", "ὧι"), + (0x1FB0, "V"), + (0x1FB2, "M", "ὰι"), + (0x1FB3, "M", "αι"), + (0x1FB4, "M", "άι"), + (0x1FB5, "X"), + (0x1FB6, "V"), + (0x1FB7, "M", "ᾶι"), + (0x1FB8, "M", "ᾰ"), + (0x1FB9, "M", "ᾱ"), + (0x1FBA, "M", "ὰ"), + (0x1FBB, "M", "ά"), + (0x1FBC, "M", "αι"), + (0x1FBD, "3", " ̓"), + (0x1FBE, "M", "ι"), + (0x1FBF, "3", " ̓"), + (0x1FC0, "3", " ͂"), + (0x1FC1, "3", " ̈͂"), + (0x1FC2, "M", "ὴι"), + (0x1FC3, "M", "ηι"), + (0x1FC4, "M", "ήι"), + (0x1FC5, "X"), + (0x1FC6, "V"), + (0x1FC7, "M", "ῆι"), + (0x1FC8, "M", "ὲ"), + (0x1FC9, "M", "έ"), + (0x1FCA, "M", "ὴ"), + (0x1FCB, "M", "ή"), + (0x1FCC, "M", "ηι"), + (0x1FCD, "3", " ̓̀"), + (0x1FCE, "3", " ̓́"), + (0x1FCF, "3", " ̓͂"), + (0x1FD0, "V"), + (0x1FD3, "M", "ΐ"), + (0x1FD4, "X"), + (0x1FD6, "V"), + (0x1FD8, "M", "ῐ"), + (0x1FD9, "M", "ῑ"), + (0x1FDA, "M", "ὶ"), + (0x1FDB, "M", "ί"), + (0x1FDC, "X"), + (0x1FDD, "3", " ̔̀"), + (0x1FDE, "3", " ̔́"), + (0x1FDF, "3", " ̔͂"), + (0x1FE0, "V"), + (0x1FE3, "M", "ΰ"), + (0x1FE4, "V"), + (0x1FE8, "M", "ῠ"), + (0x1FE9, "M", "ῡ"), + (0x1FEA, "M", "ὺ"), + (0x1FEB, "M", "ύ"), + (0x1FEC, "M", "ῥ"), + (0x1FED, "3", " ̈̀"), + (0x1FEE, "3", " ̈́"), + (0x1FEF, "3", "`"), + (0x1FF0, "X"), + (0x1FF2, "M", "ὼι"), + (0x1FF3, "M", "ωι"), + (0x1FF4, "M", "ώι"), + (0x1FF5, "X"), + (0x1FF6, "V"), + ] + + +def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1FF7, "M", "ῶι"), + (0x1FF8, "M", "ὸ"), + (0x1FF9, "M", "ό"), + (0x1FFA, "M", "ὼ"), + (0x1FFB, "M", "ώ"), + (0x1FFC, "M", "ωι"), + (0x1FFD, "3", " ́"), + (0x1FFE, "3", " ̔"), + (0x1FFF, "X"), + (0x2000, "3", " "), + (0x200B, "I"), + (0x200C, "D", ""), + (0x200E, "X"), + (0x2010, "V"), + (0x2011, "M", "‐"), + (0x2012, "V"), + (0x2017, "3", " ̳"), + (0x2018, "V"), + (0x2024, "X"), + (0x2027, "V"), + (0x2028, "X"), + (0x202F, "3", " "), + (0x2030, "V"), + (0x2033, "M", "′′"), + (0x2034, "M", "′′′"), + (0x2035, "V"), + (0x2036, "M", "‵‵"), + (0x2037, "M", "‵‵‵"), + (0x2038, "V"), + (0x203C, "3", "!!"), + (0x203D, "V"), + (0x203E, "3", " ̅"), + (0x203F, "V"), + (0x2047, "3", "??"), + (0x2048, "3", "?!"), + (0x2049, "3", "!?"), + (0x204A, "V"), + (0x2057, "M", "′′′′"), + (0x2058, "V"), + (0x205F, "3", " "), + (0x2060, "I"), + (0x2061, "X"), + (0x2064, "I"), + (0x2065, "X"), + (0x2070, "M", "0"), + (0x2071, "M", "i"), + (0x2072, "X"), + (0x2074, "M", "4"), + (0x2075, "M", "5"), + (0x2076, "M", "6"), + (0x2077, "M", "7"), + (0x2078, "M", "8"), + (0x2079, "M", "9"), + (0x207A, "3", "+"), + (0x207B, "M", "−"), + (0x207C, "3", "="), + (0x207D, "3", "("), + (0x207E, "3", ")"), + (0x207F, "M", "n"), + (0x2080, "M", "0"), + (0x2081, "M", "1"), + (0x2082, "M", "2"), + (0x2083, "M", "3"), + (0x2084, "M", "4"), + (0x2085, "M", "5"), + (0x2086, "M", "6"), + (0x2087, "M", "7"), + (0x2088, "M", "8"), + (0x2089, "M", "9"), + (0x208A, "3", "+"), + (0x208B, "M", "−"), + (0x208C, "3", "="), + (0x208D, "3", "("), + (0x208E, "3", ")"), + (0x208F, "X"), + (0x2090, "M", "a"), + (0x2091, "M", "e"), + (0x2092, "M", "o"), + (0x2093, "M", "x"), + (0x2094, "M", "ə"), + (0x2095, "M", "h"), + (0x2096, "M", "k"), + (0x2097, "M", "l"), + (0x2098, "M", "m"), + (0x2099, "M", "n"), + (0x209A, "M", "p"), + (0x209B, "M", "s"), + (0x209C, "M", "t"), + (0x209D, "X"), + (0x20A0, "V"), + (0x20A8, "M", "rs"), + (0x20A9, "V"), + (0x20C1, "X"), + (0x20D0, "V"), + (0x20F1, "X"), + (0x2100, "3", "a/c"), + (0x2101, "3", "a/s"), + (0x2102, "M", "c"), + (0x2103, "M", "°c"), + (0x2104, "V"), + ] + + +def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2105, "3", "c/o"), + (0x2106, "3", "c/u"), + (0x2107, "M", "ɛ"), + (0x2108, "V"), + (0x2109, "M", "°f"), + (0x210A, "M", "g"), + (0x210B, "M", "h"), + (0x210F, "M", "ħ"), + (0x2110, "M", "i"), + (0x2112, "M", "l"), + (0x2114, "V"), + (0x2115, "M", "n"), + (0x2116, "M", "no"), + (0x2117, "V"), + (0x2119, "M", "p"), + (0x211A, "M", "q"), + (0x211B, "M", "r"), + (0x211E, "V"), + (0x2120, "M", "sm"), + (0x2121, "M", "tel"), + (0x2122, "M", "tm"), + (0x2123, "V"), + (0x2124, "M", "z"), + (0x2125, "V"), + (0x2126, "M", "ω"), + (0x2127, "V"), + (0x2128, "M", "z"), + (0x2129, "V"), + (0x212A, "M", "k"), + (0x212B, "M", "å"), + (0x212C, "M", "b"), + (0x212D, "M", "c"), + (0x212E, "V"), + (0x212F, "M", "e"), + (0x2131, "M", "f"), + (0x2132, "X"), + (0x2133, "M", "m"), + (0x2134, "M", "o"), + (0x2135, "M", "א"), + (0x2136, "M", "ב"), + (0x2137, "M", "ג"), + (0x2138, "M", "ד"), + (0x2139, "M", "i"), + (0x213A, "V"), + (0x213B, "M", "fax"), + (0x213C, "M", "π"), + (0x213D, "M", "γ"), + (0x213F, "M", "π"), + (0x2140, "M", "∑"), + (0x2141, "V"), + (0x2145, "M", "d"), + (0x2147, "M", "e"), + (0x2148, "M", "i"), + (0x2149, "M", "j"), + (0x214A, "V"), + (0x2150, "M", "1⁄7"), + (0x2151, "M", "1⁄9"), + (0x2152, "M", "1⁄10"), + (0x2153, "M", "1⁄3"), + (0x2154, "M", "2⁄3"), + (0x2155, "M", "1⁄5"), + (0x2156, "M", "2⁄5"), + (0x2157, "M", "3⁄5"), + (0x2158, "M", "4⁄5"), + (0x2159, "M", "1⁄6"), + (0x215A, "M", "5⁄6"), + (0x215B, "M", "1⁄8"), + (0x215C, "M", "3⁄8"), + (0x215D, "M", "5⁄8"), + (0x215E, "M", "7⁄8"), + (0x215F, "M", "1⁄"), + (0x2160, "M", "i"), + (0x2161, "M", "ii"), + (0x2162, "M", "iii"), + (0x2163, "M", "iv"), + (0x2164, "M", "v"), + (0x2165, "M", "vi"), + (0x2166, "M", "vii"), + (0x2167, "M", "viii"), + (0x2168, "M", "ix"), + (0x2169, "M", "x"), + (0x216A, "M", "xi"), + (0x216B, "M", "xii"), + (0x216C, "M", "l"), + (0x216D, "M", "c"), + (0x216E, "M", "d"), + (0x216F, "M", "m"), + (0x2170, "M", "i"), + (0x2171, "M", "ii"), + (0x2172, "M", "iii"), + (0x2173, "M", "iv"), + (0x2174, "M", "v"), + (0x2175, "M", "vi"), + (0x2176, "M", "vii"), + (0x2177, "M", "viii"), + (0x2178, "M", "ix"), + (0x2179, "M", "x"), + (0x217A, "M", "xi"), + (0x217B, "M", "xii"), + (0x217C, "M", "l"), + ] + + +def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x217D, "M", "c"), + (0x217E, "M", "d"), + (0x217F, "M", "m"), + (0x2180, "V"), + (0x2183, "X"), + (0x2184, "V"), + (0x2189, "M", "0⁄3"), + (0x218A, "V"), + (0x218C, "X"), + (0x2190, "V"), + (0x222C, "M", "∫∫"), + (0x222D, "M", "∫∫∫"), + (0x222E, "V"), + (0x222F, "M", "∮∮"), + (0x2230, "M", "∮∮∮"), + (0x2231, "V"), + (0x2329, "M", "〈"), + (0x232A, "M", "〉"), + (0x232B, "V"), + (0x2427, "X"), + (0x2440, "V"), + (0x244B, "X"), + (0x2460, "M", "1"), + (0x2461, "M", "2"), + (0x2462, "M", "3"), + (0x2463, "M", "4"), + (0x2464, "M", "5"), + (0x2465, "M", "6"), + (0x2466, "M", "7"), + (0x2467, "M", "8"), + (0x2468, "M", "9"), + (0x2469, "M", "10"), + (0x246A, "M", "11"), + (0x246B, "M", "12"), + (0x246C, "M", "13"), + (0x246D, "M", "14"), + (0x246E, "M", "15"), + (0x246F, "M", "16"), + (0x2470, "M", "17"), + (0x2471, "M", "18"), + (0x2472, "M", "19"), + (0x2473, "M", "20"), + (0x2474, "3", "(1)"), + (0x2475, "3", "(2)"), + (0x2476, "3", "(3)"), + (0x2477, "3", "(4)"), + (0x2478, "3", "(5)"), + (0x2479, "3", "(6)"), + (0x247A, "3", "(7)"), + (0x247B, "3", "(8)"), + (0x247C, "3", "(9)"), + (0x247D, "3", "(10)"), + (0x247E, "3", "(11)"), + (0x247F, "3", "(12)"), + (0x2480, "3", "(13)"), + (0x2481, "3", "(14)"), + (0x2482, "3", "(15)"), + (0x2483, "3", "(16)"), + (0x2484, "3", "(17)"), + (0x2485, "3", "(18)"), + (0x2486, "3", "(19)"), + (0x2487, "3", "(20)"), + (0x2488, "X"), + (0x249C, "3", "(a)"), + (0x249D, "3", "(b)"), + (0x249E, "3", "(c)"), + (0x249F, "3", "(d)"), + (0x24A0, "3", "(e)"), + (0x24A1, "3", "(f)"), + (0x24A2, "3", "(g)"), + (0x24A3, "3", "(h)"), + (0x24A4, "3", "(i)"), + (0x24A5, "3", "(j)"), + (0x24A6, "3", "(k)"), + (0x24A7, "3", "(l)"), + (0x24A8, "3", "(m)"), + (0x24A9, "3", "(n)"), + (0x24AA, "3", "(o)"), + (0x24AB, "3", "(p)"), + (0x24AC, "3", "(q)"), + (0x24AD, "3", "(r)"), + (0x24AE, "3", "(s)"), + (0x24AF, "3", "(t)"), + (0x24B0, "3", "(u)"), + (0x24B1, "3", "(v)"), + (0x24B2, "3", "(w)"), + (0x24B3, "3", "(x)"), + (0x24B4, "3", "(y)"), + (0x24B5, "3", "(z)"), + (0x24B6, "M", "a"), + (0x24B7, "M", "b"), + (0x24B8, "M", "c"), + (0x24B9, "M", "d"), + (0x24BA, "M", "e"), + (0x24BB, "M", "f"), + (0x24BC, "M", "g"), + (0x24BD, "M", "h"), + (0x24BE, "M", "i"), + (0x24BF, "M", "j"), + (0x24C0, "M", "k"), + ] + + +def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x24C1, "M", "l"), + (0x24C2, "M", "m"), + (0x24C3, "M", "n"), + (0x24C4, "M", "o"), + (0x24C5, "M", "p"), + (0x24C6, "M", "q"), + (0x24C7, "M", "r"), + (0x24C8, "M", "s"), + (0x24C9, "M", "t"), + (0x24CA, "M", "u"), + (0x24CB, "M", "v"), + (0x24CC, "M", "w"), + (0x24CD, "M", "x"), + (0x24CE, "M", "y"), + (0x24CF, "M", "z"), + (0x24D0, "M", "a"), + (0x24D1, "M", "b"), + (0x24D2, "M", "c"), + (0x24D3, "M", "d"), + (0x24D4, "M", "e"), + (0x24D5, "M", "f"), + (0x24D6, "M", "g"), + (0x24D7, "M", "h"), + (0x24D8, "M", "i"), + (0x24D9, "M", "j"), + (0x24DA, "M", "k"), + (0x24DB, "M", "l"), + (0x24DC, "M", "m"), + (0x24DD, "M", "n"), + (0x24DE, "M", "o"), + (0x24DF, "M", "p"), + (0x24E0, "M", "q"), + (0x24E1, "M", "r"), + (0x24E2, "M", "s"), + (0x24E3, "M", "t"), + (0x24E4, "M", "u"), + (0x24E5, "M", "v"), + (0x24E6, "M", "w"), + (0x24E7, "M", "x"), + (0x24E8, "M", "y"), + (0x24E9, "M", "z"), + (0x24EA, "M", "0"), + (0x24EB, "V"), + (0x2A0C, "M", "∫∫∫∫"), + (0x2A0D, "V"), + (0x2A74, "3", "::="), + (0x2A75, "3", "=="), + (0x2A76, "3", "==="), + (0x2A77, "V"), + (0x2ADC, "M", "⫝̸"), + (0x2ADD, "V"), + (0x2B74, "X"), + (0x2B76, "V"), + (0x2B96, "X"), + (0x2B97, "V"), + (0x2C00, "M", "ⰰ"), + (0x2C01, "M", "ⰱ"), + (0x2C02, "M", "ⰲ"), + (0x2C03, "M", "ⰳ"), + (0x2C04, "M", "ⰴ"), + (0x2C05, "M", "ⰵ"), + (0x2C06, "M", "ⰶ"), + (0x2C07, "M", "ⰷ"), + (0x2C08, "M", "ⰸ"), + (0x2C09, "M", "ⰹ"), + (0x2C0A, "M", "ⰺ"), + (0x2C0B, "M", "ⰻ"), + (0x2C0C, "M", "ⰼ"), + (0x2C0D, "M", "ⰽ"), + (0x2C0E, "M", "ⰾ"), + (0x2C0F, "M", "ⰿ"), + (0x2C10, "M", "ⱀ"), + (0x2C11, "M", "ⱁ"), + (0x2C12, "M", "ⱂ"), + (0x2C13, "M", "ⱃ"), + (0x2C14, "M", "ⱄ"), + (0x2C15, "M", "ⱅ"), + (0x2C16, "M", "ⱆ"), + (0x2C17, "M", "ⱇ"), + (0x2C18, "M", "ⱈ"), + (0x2C19, "M", "ⱉ"), + (0x2C1A, "M", "ⱊ"), + (0x2C1B, "M", "ⱋ"), + (0x2C1C, "M", "ⱌ"), + (0x2C1D, "M", "ⱍ"), + (0x2C1E, "M", "ⱎ"), + (0x2C1F, "M", "ⱏ"), + (0x2C20, "M", "ⱐ"), + (0x2C21, "M", "ⱑ"), + (0x2C22, "M", "ⱒ"), + (0x2C23, "M", "ⱓ"), + (0x2C24, "M", "ⱔ"), + (0x2C25, "M", "ⱕ"), + (0x2C26, "M", "ⱖ"), + (0x2C27, "M", "ⱗ"), + (0x2C28, "M", "ⱘ"), + (0x2C29, "M", "ⱙ"), + (0x2C2A, "M", "ⱚ"), + (0x2C2B, "M", "ⱛ"), + (0x2C2C, "M", "ⱜ"), + ] + + +def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2C2D, "M", "ⱝ"), + (0x2C2E, "M", "ⱞ"), + (0x2C2F, "M", "ⱟ"), + (0x2C30, "V"), + (0x2C60, "M", "ⱡ"), + (0x2C61, "V"), + (0x2C62, "M", "ɫ"), + (0x2C63, "M", "ᵽ"), + (0x2C64, "M", "ɽ"), + (0x2C65, "V"), + (0x2C67, "M", "ⱨ"), + (0x2C68, "V"), + (0x2C69, "M", "ⱪ"), + (0x2C6A, "V"), + (0x2C6B, "M", "ⱬ"), + (0x2C6C, "V"), + (0x2C6D, "M", "ɑ"), + (0x2C6E, "M", "ɱ"), + (0x2C6F, "M", "ɐ"), + (0x2C70, "M", "ɒ"), + (0x2C71, "V"), + (0x2C72, "M", "ⱳ"), + (0x2C73, "V"), + (0x2C75, "M", "ⱶ"), + (0x2C76, "V"), + (0x2C7C, "M", "j"), + (0x2C7D, "M", "v"), + (0x2C7E, "M", "ȿ"), + (0x2C7F, "M", "ɀ"), + (0x2C80, "M", "ⲁ"), + (0x2C81, "V"), + (0x2C82, "M", "ⲃ"), + (0x2C83, "V"), + (0x2C84, "M", "ⲅ"), + (0x2C85, "V"), + (0x2C86, "M", "ⲇ"), + (0x2C87, "V"), + (0x2C88, "M", "ⲉ"), + (0x2C89, "V"), + (0x2C8A, "M", "ⲋ"), + (0x2C8B, "V"), + (0x2C8C, "M", "ⲍ"), + (0x2C8D, "V"), + (0x2C8E, "M", "ⲏ"), + (0x2C8F, "V"), + (0x2C90, "M", "ⲑ"), + (0x2C91, "V"), + (0x2C92, "M", "ⲓ"), + (0x2C93, "V"), + (0x2C94, "M", "ⲕ"), + (0x2C95, "V"), + (0x2C96, "M", "ⲗ"), + (0x2C97, "V"), + (0x2C98, "M", "ⲙ"), + (0x2C99, "V"), + (0x2C9A, "M", "ⲛ"), + (0x2C9B, "V"), + (0x2C9C, "M", "ⲝ"), + (0x2C9D, "V"), + (0x2C9E, "M", "ⲟ"), + (0x2C9F, "V"), + (0x2CA0, "M", "ⲡ"), + (0x2CA1, "V"), + (0x2CA2, "M", "ⲣ"), + (0x2CA3, "V"), + (0x2CA4, "M", "ⲥ"), + (0x2CA5, "V"), + (0x2CA6, "M", "ⲧ"), + (0x2CA7, "V"), + (0x2CA8, "M", "ⲩ"), + (0x2CA9, "V"), + (0x2CAA, "M", "ⲫ"), + (0x2CAB, "V"), + (0x2CAC, "M", "ⲭ"), + (0x2CAD, "V"), + (0x2CAE, "M", "ⲯ"), + (0x2CAF, "V"), + (0x2CB0, "M", "ⲱ"), + (0x2CB1, "V"), + (0x2CB2, "M", "ⲳ"), + (0x2CB3, "V"), + (0x2CB4, "M", "ⲵ"), + (0x2CB5, "V"), + (0x2CB6, "M", "ⲷ"), + (0x2CB7, "V"), + (0x2CB8, "M", "ⲹ"), + (0x2CB9, "V"), + (0x2CBA, "M", "ⲻ"), + (0x2CBB, "V"), + (0x2CBC, "M", "ⲽ"), + (0x2CBD, "V"), + (0x2CBE, "M", "ⲿ"), + (0x2CBF, "V"), + (0x2CC0, "M", "ⳁ"), + (0x2CC1, "V"), + (0x2CC2, "M", "ⳃ"), + (0x2CC3, "V"), + (0x2CC4, "M", "ⳅ"), + (0x2CC5, "V"), + (0x2CC6, "M", "ⳇ"), + ] + + +def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2CC7, "V"), + (0x2CC8, "M", "ⳉ"), + (0x2CC9, "V"), + (0x2CCA, "M", "ⳋ"), + (0x2CCB, "V"), + (0x2CCC, "M", "ⳍ"), + (0x2CCD, "V"), + (0x2CCE, "M", "ⳏ"), + (0x2CCF, "V"), + (0x2CD0, "M", "ⳑ"), + (0x2CD1, "V"), + (0x2CD2, "M", "ⳓ"), + (0x2CD3, "V"), + (0x2CD4, "M", "ⳕ"), + (0x2CD5, "V"), + (0x2CD6, "M", "ⳗ"), + (0x2CD7, "V"), + (0x2CD8, "M", "ⳙ"), + (0x2CD9, "V"), + (0x2CDA, "M", "ⳛ"), + (0x2CDB, "V"), + (0x2CDC, "M", "ⳝ"), + (0x2CDD, "V"), + (0x2CDE, "M", "ⳟ"), + (0x2CDF, "V"), + (0x2CE0, "M", "ⳡ"), + (0x2CE1, "V"), + (0x2CE2, "M", "ⳣ"), + (0x2CE3, "V"), + (0x2CEB, "M", "ⳬ"), + (0x2CEC, "V"), + (0x2CED, "M", "ⳮ"), + (0x2CEE, "V"), + (0x2CF2, "M", "ⳳ"), + (0x2CF3, "V"), + (0x2CF4, "X"), + (0x2CF9, "V"), + (0x2D26, "X"), + (0x2D27, "V"), + (0x2D28, "X"), + (0x2D2D, "V"), + (0x2D2E, "X"), + (0x2D30, "V"), + (0x2D68, "X"), + (0x2D6F, "M", "ⵡ"), + (0x2D70, "V"), + (0x2D71, "X"), + (0x2D7F, "V"), + (0x2D97, "X"), + (0x2DA0, "V"), + (0x2DA7, "X"), + (0x2DA8, "V"), + (0x2DAF, "X"), + (0x2DB0, "V"), + (0x2DB7, "X"), + (0x2DB8, "V"), + (0x2DBF, "X"), + (0x2DC0, "V"), + (0x2DC7, "X"), + (0x2DC8, "V"), + (0x2DCF, "X"), + (0x2DD0, "V"), + (0x2DD7, "X"), + (0x2DD8, "V"), + (0x2DDF, "X"), + (0x2DE0, "V"), + (0x2E5E, "X"), + (0x2E80, "V"), + (0x2E9A, "X"), + (0x2E9B, "V"), + (0x2E9F, "M", "母"), + (0x2EA0, "V"), + (0x2EF3, "M", "龟"), + (0x2EF4, "X"), + (0x2F00, "M", "一"), + (0x2F01, "M", "丨"), + (0x2F02, "M", "丶"), + (0x2F03, "M", "丿"), + (0x2F04, "M", "乙"), + (0x2F05, "M", "亅"), + (0x2F06, "M", "二"), + (0x2F07, "M", "亠"), + (0x2F08, "M", "人"), + (0x2F09, "M", "儿"), + (0x2F0A, "M", "入"), + (0x2F0B, "M", "八"), + (0x2F0C, "M", "冂"), + (0x2F0D, "M", "冖"), + (0x2F0E, "M", "冫"), + (0x2F0F, "M", "几"), + (0x2F10, "M", "凵"), + (0x2F11, "M", "刀"), + (0x2F12, "M", "力"), + (0x2F13, "M", "勹"), + (0x2F14, "M", "匕"), + (0x2F15, "M", "匚"), + (0x2F16, "M", "匸"), + (0x2F17, "M", "十"), + (0x2F18, "M", "卜"), + (0x2F19, "M", "卩"), + ] + + +def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F1A, "M", "厂"), + (0x2F1B, "M", "厶"), + (0x2F1C, "M", "又"), + (0x2F1D, "M", "口"), + (0x2F1E, "M", "囗"), + (0x2F1F, "M", "土"), + (0x2F20, "M", "士"), + (0x2F21, "M", "夂"), + (0x2F22, "M", "夊"), + (0x2F23, "M", "夕"), + (0x2F24, "M", "大"), + (0x2F25, "M", "女"), + (0x2F26, "M", "子"), + (0x2F27, "M", "宀"), + (0x2F28, "M", "寸"), + (0x2F29, "M", "小"), + (0x2F2A, "M", "尢"), + (0x2F2B, "M", "尸"), + (0x2F2C, "M", "屮"), + (0x2F2D, "M", "山"), + (0x2F2E, "M", "巛"), + (0x2F2F, "M", "工"), + (0x2F30, "M", "己"), + (0x2F31, "M", "巾"), + (0x2F32, "M", "干"), + (0x2F33, "M", "幺"), + (0x2F34, "M", "广"), + (0x2F35, "M", "廴"), + (0x2F36, "M", "廾"), + (0x2F37, "M", "弋"), + (0x2F38, "M", "弓"), + (0x2F39, "M", "彐"), + (0x2F3A, "M", "彡"), + (0x2F3B, "M", "彳"), + (0x2F3C, "M", "心"), + (0x2F3D, "M", "戈"), + (0x2F3E, "M", "戶"), + (0x2F3F, "M", "手"), + (0x2F40, "M", "支"), + (0x2F41, "M", "攴"), + (0x2F42, "M", "文"), + (0x2F43, "M", "斗"), + (0x2F44, "M", "斤"), + (0x2F45, "M", "方"), + (0x2F46, "M", "无"), + (0x2F47, "M", "日"), + (0x2F48, "M", "曰"), + (0x2F49, "M", "月"), + (0x2F4A, "M", "木"), + (0x2F4B, "M", "欠"), + (0x2F4C, "M", "止"), + (0x2F4D, "M", "歹"), + (0x2F4E, "M", "殳"), + (0x2F4F, "M", "毋"), + (0x2F50, "M", "比"), + (0x2F51, "M", "毛"), + (0x2F52, "M", "氏"), + (0x2F53, "M", "气"), + (0x2F54, "M", "水"), + (0x2F55, "M", "火"), + (0x2F56, "M", "爪"), + (0x2F57, "M", "父"), + (0x2F58, "M", "爻"), + (0x2F59, "M", "爿"), + (0x2F5A, "M", "片"), + (0x2F5B, "M", "牙"), + (0x2F5C, "M", "牛"), + (0x2F5D, "M", "犬"), + (0x2F5E, "M", "玄"), + (0x2F5F, "M", "玉"), + (0x2F60, "M", "瓜"), + (0x2F61, "M", "瓦"), + (0x2F62, "M", "甘"), + (0x2F63, "M", "生"), + (0x2F64, "M", "用"), + (0x2F65, "M", "田"), + (0x2F66, "M", "疋"), + (0x2F67, "M", "疒"), + (0x2F68, "M", "癶"), + (0x2F69, "M", "白"), + (0x2F6A, "M", "皮"), + (0x2F6B, "M", "皿"), + (0x2F6C, "M", "目"), + (0x2F6D, "M", "矛"), + (0x2F6E, "M", "矢"), + (0x2F6F, "M", "石"), + (0x2F70, "M", "示"), + (0x2F71, "M", "禸"), + (0x2F72, "M", "禾"), + (0x2F73, "M", "穴"), + (0x2F74, "M", "立"), + (0x2F75, "M", "竹"), + (0x2F76, "M", "米"), + (0x2F77, "M", "糸"), + (0x2F78, "M", "缶"), + (0x2F79, "M", "网"), + (0x2F7A, "M", "羊"), + (0x2F7B, "M", "羽"), + (0x2F7C, "M", "老"), + (0x2F7D, "M", "而"), + ] + + +def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F7E, "M", "耒"), + (0x2F7F, "M", "耳"), + (0x2F80, "M", "聿"), + (0x2F81, "M", "肉"), + (0x2F82, "M", "臣"), + (0x2F83, "M", "自"), + (0x2F84, "M", "至"), + (0x2F85, "M", "臼"), + (0x2F86, "M", "舌"), + (0x2F87, "M", "舛"), + (0x2F88, "M", "舟"), + (0x2F89, "M", "艮"), + (0x2F8A, "M", "色"), + (0x2F8B, "M", "艸"), + (0x2F8C, "M", "虍"), + (0x2F8D, "M", "虫"), + (0x2F8E, "M", "血"), + (0x2F8F, "M", "行"), + (0x2F90, "M", "衣"), + (0x2F91, "M", "襾"), + (0x2F92, "M", "見"), + (0x2F93, "M", "角"), + (0x2F94, "M", "言"), + (0x2F95, "M", "谷"), + (0x2F96, "M", "豆"), + (0x2F97, "M", "豕"), + (0x2F98, "M", "豸"), + (0x2F99, "M", "貝"), + (0x2F9A, "M", "赤"), + (0x2F9B, "M", "走"), + (0x2F9C, "M", "足"), + (0x2F9D, "M", "身"), + (0x2F9E, "M", "車"), + (0x2F9F, "M", "辛"), + (0x2FA0, "M", "辰"), + (0x2FA1, "M", "辵"), + (0x2FA2, "M", "邑"), + (0x2FA3, "M", "酉"), + (0x2FA4, "M", "釆"), + (0x2FA5, "M", "里"), + (0x2FA6, "M", "金"), + (0x2FA7, "M", "長"), + (0x2FA8, "M", "門"), + (0x2FA9, "M", "阜"), + (0x2FAA, "M", "隶"), + (0x2FAB, "M", "隹"), + (0x2FAC, "M", "雨"), + (0x2FAD, "M", "靑"), + (0x2FAE, "M", "非"), + (0x2FAF, "M", "面"), + (0x2FB0, "M", "革"), + (0x2FB1, "M", "韋"), + (0x2FB2, "M", "韭"), + (0x2FB3, "M", "音"), + (0x2FB4, "M", "頁"), + (0x2FB5, "M", "風"), + (0x2FB6, "M", "飛"), + (0x2FB7, "M", "食"), + (0x2FB8, "M", "首"), + (0x2FB9, "M", "香"), + (0x2FBA, "M", "馬"), + (0x2FBB, "M", "骨"), + (0x2FBC, "M", "高"), + (0x2FBD, "M", "髟"), + (0x2FBE, "M", "鬥"), + (0x2FBF, "M", "鬯"), + (0x2FC0, "M", "鬲"), + (0x2FC1, "M", "鬼"), + (0x2FC2, "M", "魚"), + (0x2FC3, "M", "鳥"), + (0x2FC4, "M", "鹵"), + (0x2FC5, "M", "鹿"), + (0x2FC6, "M", "麥"), + (0x2FC7, "M", "麻"), + (0x2FC8, "M", "黃"), + (0x2FC9, "M", "黍"), + (0x2FCA, "M", "黑"), + (0x2FCB, "M", "黹"), + (0x2FCC, "M", "黽"), + (0x2FCD, "M", "鼎"), + (0x2FCE, "M", "鼓"), + (0x2FCF, "M", "鼠"), + (0x2FD0, "M", "鼻"), + (0x2FD1, "M", "齊"), + (0x2FD2, "M", "齒"), + (0x2FD3, "M", "龍"), + (0x2FD4, "M", "龜"), + (0x2FD5, "M", "龠"), + (0x2FD6, "X"), + (0x3000, "3", " "), + (0x3001, "V"), + (0x3002, "M", "."), + (0x3003, "V"), + (0x3036, "M", "〒"), + (0x3037, "V"), + (0x3038, "M", "十"), + (0x3039, "M", "卄"), + (0x303A, "M", "卅"), + (0x303B, "V"), + (0x3040, "X"), + ] + + +def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3041, "V"), + (0x3097, "X"), + (0x3099, "V"), + (0x309B, "3", " ゙"), + (0x309C, "3", " ゚"), + (0x309D, "V"), + (0x309F, "M", "より"), + (0x30A0, "V"), + (0x30FF, "M", "コト"), + (0x3100, "X"), + (0x3105, "V"), + (0x3130, "X"), + (0x3131, "M", "ᄀ"), + (0x3132, "M", "ᄁ"), + (0x3133, "M", "ᆪ"), + (0x3134, "M", "ᄂ"), + (0x3135, "M", "ᆬ"), + (0x3136, "M", "ᆭ"), + (0x3137, "M", "ᄃ"), + (0x3138, "M", "ᄄ"), + (0x3139, "M", "ᄅ"), + (0x313A, "M", "ᆰ"), + (0x313B, "M", "ᆱ"), + (0x313C, "M", "ᆲ"), + (0x313D, "M", "ᆳ"), + (0x313E, "M", "ᆴ"), + (0x313F, "M", "ᆵ"), + (0x3140, "M", "ᄚ"), + (0x3141, "M", "ᄆ"), + (0x3142, "M", "ᄇ"), + (0x3143, "M", "ᄈ"), + (0x3144, "M", "ᄡ"), + (0x3145, "M", "ᄉ"), + (0x3146, "M", "ᄊ"), + (0x3147, "M", "ᄋ"), + (0x3148, "M", "ᄌ"), + (0x3149, "M", "ᄍ"), + (0x314A, "M", "ᄎ"), + (0x314B, "M", "ᄏ"), + (0x314C, "M", "ᄐ"), + (0x314D, "M", "ᄑ"), + (0x314E, "M", "ᄒ"), + (0x314F, "M", "ᅡ"), + (0x3150, "M", "ᅢ"), + (0x3151, "M", "ᅣ"), + (0x3152, "M", "ᅤ"), + (0x3153, "M", "ᅥ"), + (0x3154, "M", "ᅦ"), + (0x3155, "M", "ᅧ"), + (0x3156, "M", "ᅨ"), + (0x3157, "M", "ᅩ"), + (0x3158, "M", "ᅪ"), + (0x3159, "M", "ᅫ"), + (0x315A, "M", "ᅬ"), + (0x315B, "M", "ᅭ"), + (0x315C, "M", "ᅮ"), + (0x315D, "M", "ᅯ"), + (0x315E, "M", "ᅰ"), + (0x315F, "M", "ᅱ"), + (0x3160, "M", "ᅲ"), + (0x3161, "M", "ᅳ"), + (0x3162, "M", "ᅴ"), + (0x3163, "M", "ᅵ"), + (0x3164, "X"), + (0x3165, "M", "ᄔ"), + (0x3166, "M", "ᄕ"), + (0x3167, "M", "ᇇ"), + (0x3168, "M", "ᇈ"), + (0x3169, "M", "ᇌ"), + (0x316A, "M", "ᇎ"), + (0x316B, "M", "ᇓ"), + (0x316C, "M", "ᇗ"), + (0x316D, "M", "ᇙ"), + (0x316E, "M", "ᄜ"), + (0x316F, "M", "ᇝ"), + (0x3170, "M", "ᇟ"), + (0x3171, "M", "ᄝ"), + (0x3172, "M", "ᄞ"), + (0x3173, "M", "ᄠ"), + (0x3174, "M", "ᄢ"), + (0x3175, "M", "ᄣ"), + (0x3176, "M", "ᄧ"), + (0x3177, "M", "ᄩ"), + (0x3178, "M", "ᄫ"), + (0x3179, "M", "ᄬ"), + (0x317A, "M", "ᄭ"), + (0x317B, "M", "ᄮ"), + (0x317C, "M", "ᄯ"), + (0x317D, "M", "ᄲ"), + (0x317E, "M", "ᄶ"), + (0x317F, "M", "ᅀ"), + (0x3180, "M", "ᅇ"), + (0x3181, "M", "ᅌ"), + (0x3182, "M", "ᇱ"), + (0x3183, "M", "ᇲ"), + (0x3184, "M", "ᅗ"), + (0x3185, "M", "ᅘ"), + (0x3186, "M", "ᅙ"), + (0x3187, "M", "ᆄ"), + (0x3188, "M", "ᆅ"), + ] + + +def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3189, "M", "ᆈ"), + (0x318A, "M", "ᆑ"), + (0x318B, "M", "ᆒ"), + (0x318C, "M", "ᆔ"), + (0x318D, "M", "ᆞ"), + (0x318E, "M", "ᆡ"), + (0x318F, "X"), + (0x3190, "V"), + (0x3192, "M", "一"), + (0x3193, "M", "二"), + (0x3194, "M", "三"), + (0x3195, "M", "四"), + (0x3196, "M", "上"), + (0x3197, "M", "中"), + (0x3198, "M", "下"), + (0x3199, "M", "甲"), + (0x319A, "M", "乙"), + (0x319B, "M", "丙"), + (0x319C, "M", "丁"), + (0x319D, "M", "天"), + (0x319E, "M", "地"), + (0x319F, "M", "人"), + (0x31A0, "V"), + (0x31E4, "X"), + (0x31F0, "V"), + (0x3200, "3", "(ᄀ)"), + (0x3201, "3", "(ᄂ)"), + (0x3202, "3", "(ᄃ)"), + (0x3203, "3", "(ᄅ)"), + (0x3204, "3", "(ᄆ)"), + (0x3205, "3", "(ᄇ)"), + (0x3206, "3", "(ᄉ)"), + (0x3207, "3", "(ᄋ)"), + (0x3208, "3", "(ᄌ)"), + (0x3209, "3", "(ᄎ)"), + (0x320A, "3", "(ᄏ)"), + (0x320B, "3", "(ᄐ)"), + (0x320C, "3", "(ᄑ)"), + (0x320D, "3", "(ᄒ)"), + (0x320E, "3", "(가)"), + (0x320F, "3", "(나)"), + (0x3210, "3", "(다)"), + (0x3211, "3", "(라)"), + (0x3212, "3", "(마)"), + (0x3213, "3", "(바)"), + (0x3214, "3", "(사)"), + (0x3215, "3", "(아)"), + (0x3216, "3", "(자)"), + (0x3217, "3", "(차)"), + (0x3218, "3", "(카)"), + (0x3219, "3", "(타)"), + (0x321A, "3", "(파)"), + (0x321B, "3", "(하)"), + (0x321C, "3", "(주)"), + (0x321D, "3", "(오전)"), + (0x321E, "3", "(오후)"), + (0x321F, "X"), + (0x3220, "3", "(一)"), + (0x3221, "3", "(二)"), + (0x3222, "3", "(三)"), + (0x3223, "3", "(四)"), + (0x3224, "3", "(五)"), + (0x3225, "3", "(六)"), + (0x3226, "3", "(七)"), + (0x3227, "3", "(八)"), + (0x3228, "3", "(九)"), + (0x3229, "3", "(十)"), + (0x322A, "3", "(月)"), + (0x322B, "3", "(火)"), + (0x322C, "3", "(水)"), + (0x322D, "3", "(木)"), + (0x322E, "3", "(金)"), + (0x322F, "3", "(土)"), + (0x3230, "3", "(日)"), + (0x3231, "3", "(株)"), + (0x3232, "3", "(有)"), + (0x3233, "3", "(社)"), + (0x3234, "3", "(名)"), + (0x3235, "3", "(特)"), + (0x3236, "3", "(財)"), + (0x3237, "3", "(祝)"), + (0x3238, "3", "(労)"), + (0x3239, "3", "(代)"), + (0x323A, "3", "(呼)"), + (0x323B, "3", "(学)"), + (0x323C, "3", "(監)"), + (0x323D, "3", "(企)"), + (0x323E, "3", "(資)"), + (0x323F, "3", "(協)"), + (0x3240, "3", "(祭)"), + (0x3241, "3", "(休)"), + (0x3242, "3", "(自)"), + (0x3243, "3", "(至)"), + (0x3244, "M", "問"), + (0x3245, "M", "幼"), + (0x3246, "M", "文"), + (0x3247, "M", "箏"), + (0x3248, "V"), + (0x3250, "M", "pte"), + (0x3251, "M", "21"), + ] + + +def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3252, "M", "22"), + (0x3253, "M", "23"), + (0x3254, "M", "24"), + (0x3255, "M", "25"), + (0x3256, "M", "26"), + (0x3257, "M", "27"), + (0x3258, "M", "28"), + (0x3259, "M", "29"), + (0x325A, "M", "30"), + (0x325B, "M", "31"), + (0x325C, "M", "32"), + (0x325D, "M", "33"), + (0x325E, "M", "34"), + (0x325F, "M", "35"), + (0x3260, "M", "ᄀ"), + (0x3261, "M", "ᄂ"), + (0x3262, "M", "ᄃ"), + (0x3263, "M", "ᄅ"), + (0x3264, "M", "ᄆ"), + (0x3265, "M", "ᄇ"), + (0x3266, "M", "ᄉ"), + (0x3267, "M", "ᄋ"), + (0x3268, "M", "ᄌ"), + (0x3269, "M", "ᄎ"), + (0x326A, "M", "ᄏ"), + (0x326B, "M", "ᄐ"), + (0x326C, "M", "ᄑ"), + (0x326D, "M", "ᄒ"), + (0x326E, "M", "가"), + (0x326F, "M", "나"), + (0x3270, "M", "다"), + (0x3271, "M", "라"), + (0x3272, "M", "마"), + (0x3273, "M", "바"), + (0x3274, "M", "사"), + (0x3275, "M", "아"), + (0x3276, "M", "자"), + (0x3277, "M", "차"), + (0x3278, "M", "카"), + (0x3279, "M", "타"), + (0x327A, "M", "파"), + (0x327B, "M", "하"), + (0x327C, "M", "참고"), + (0x327D, "M", "주의"), + (0x327E, "M", "우"), + (0x327F, "V"), + (0x3280, "M", "一"), + (0x3281, "M", "二"), + (0x3282, "M", "三"), + (0x3283, "M", "四"), + (0x3284, "M", "五"), + (0x3285, "M", "六"), + (0x3286, "M", "七"), + (0x3287, "M", "八"), + (0x3288, "M", "九"), + (0x3289, "M", "十"), + (0x328A, "M", "月"), + (0x328B, "M", "火"), + (0x328C, "M", "水"), + (0x328D, "M", "木"), + (0x328E, "M", "金"), + (0x328F, "M", "土"), + (0x3290, "M", "日"), + (0x3291, "M", "株"), + (0x3292, "M", "有"), + (0x3293, "M", "社"), + (0x3294, "M", "名"), + (0x3295, "M", "特"), + (0x3296, "M", "財"), + (0x3297, "M", "祝"), + (0x3298, "M", "労"), + (0x3299, "M", "秘"), + (0x329A, "M", "男"), + (0x329B, "M", "女"), + (0x329C, "M", "適"), + (0x329D, "M", "優"), + (0x329E, "M", "印"), + (0x329F, "M", "注"), + (0x32A0, "M", "項"), + (0x32A1, "M", "休"), + (0x32A2, "M", "写"), + (0x32A3, "M", "正"), + (0x32A4, "M", "上"), + (0x32A5, "M", "中"), + (0x32A6, "M", "下"), + (0x32A7, "M", "左"), + (0x32A8, "M", "右"), + (0x32A9, "M", "医"), + (0x32AA, "M", "宗"), + (0x32AB, "M", "学"), + (0x32AC, "M", "監"), + (0x32AD, "M", "企"), + (0x32AE, "M", "資"), + (0x32AF, "M", "協"), + (0x32B0, "M", "夜"), + (0x32B1, "M", "36"), + (0x32B2, "M", "37"), + (0x32B3, "M", "38"), + (0x32B4, "M", "39"), + (0x32B5, "M", "40"), + ] + + +def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x32B6, "M", "41"), + (0x32B7, "M", "42"), + (0x32B8, "M", "43"), + (0x32B9, "M", "44"), + (0x32BA, "M", "45"), + (0x32BB, "M", "46"), + (0x32BC, "M", "47"), + (0x32BD, "M", "48"), + (0x32BE, "M", "49"), + (0x32BF, "M", "50"), + (0x32C0, "M", "1月"), + (0x32C1, "M", "2月"), + (0x32C2, "M", "3月"), + (0x32C3, "M", "4月"), + (0x32C4, "M", "5月"), + (0x32C5, "M", "6月"), + (0x32C6, "M", "7月"), + (0x32C7, "M", "8月"), + (0x32C8, "M", "9月"), + (0x32C9, "M", "10月"), + (0x32CA, "M", "11月"), + (0x32CB, "M", "12月"), + (0x32CC, "M", "hg"), + (0x32CD, "M", "erg"), + (0x32CE, "M", "ev"), + (0x32CF, "M", "ltd"), + (0x32D0, "M", "ア"), + (0x32D1, "M", "イ"), + (0x32D2, "M", "ウ"), + (0x32D3, "M", "エ"), + (0x32D4, "M", "オ"), + (0x32D5, "M", "カ"), + (0x32D6, "M", "キ"), + (0x32D7, "M", "ク"), + (0x32D8, "M", "ケ"), + (0x32D9, "M", "コ"), + (0x32DA, "M", "サ"), + (0x32DB, "M", "シ"), + (0x32DC, "M", "ス"), + (0x32DD, "M", "セ"), + (0x32DE, "M", "ソ"), + (0x32DF, "M", "タ"), + (0x32E0, "M", "チ"), + (0x32E1, "M", "ツ"), + (0x32E2, "M", "テ"), + (0x32E3, "M", "ト"), + (0x32E4, "M", "ナ"), + (0x32E5, "M", "ニ"), + (0x32E6, "M", "ヌ"), + (0x32E7, "M", "ネ"), + (0x32E8, "M", "ノ"), + (0x32E9, "M", "ハ"), + (0x32EA, "M", "ヒ"), + (0x32EB, "M", "フ"), + (0x32EC, "M", "ヘ"), + (0x32ED, "M", "ホ"), + (0x32EE, "M", "マ"), + (0x32EF, "M", "ミ"), + (0x32F0, "M", "ム"), + (0x32F1, "M", "メ"), + (0x32F2, "M", "モ"), + (0x32F3, "M", "ヤ"), + (0x32F4, "M", "ユ"), + (0x32F5, "M", "ヨ"), + (0x32F6, "M", "ラ"), + (0x32F7, "M", "リ"), + (0x32F8, "M", "ル"), + (0x32F9, "M", "レ"), + (0x32FA, "M", "ロ"), + (0x32FB, "M", "ワ"), + (0x32FC, "M", "ヰ"), + (0x32FD, "M", "ヱ"), + (0x32FE, "M", "ヲ"), + (0x32FF, "M", "令和"), + (0x3300, "M", "アパート"), + (0x3301, "M", "アルファ"), + (0x3302, "M", "アンペア"), + (0x3303, "M", "アール"), + (0x3304, "M", "イニング"), + (0x3305, "M", "インチ"), + (0x3306, "M", "ウォン"), + (0x3307, "M", "エスクード"), + (0x3308, "M", "エーカー"), + (0x3309, "M", "オンス"), + (0x330A, "M", "オーム"), + (0x330B, "M", "カイリ"), + (0x330C, "M", "カラット"), + (0x330D, "M", "カロリー"), + (0x330E, "M", "ガロン"), + (0x330F, "M", "ガンマ"), + (0x3310, "M", "ギガ"), + (0x3311, "M", "ギニー"), + (0x3312, "M", "キュリー"), + (0x3313, "M", "ギルダー"), + (0x3314, "M", "キロ"), + (0x3315, "M", "キログラム"), + (0x3316, "M", "キロメートル"), + (0x3317, "M", "キロワット"), + (0x3318, "M", "グラム"), + (0x3319, "M", "グラムトン"), + ] + + +def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x331A, "M", "クルゼイロ"), + (0x331B, "M", "クローネ"), + (0x331C, "M", "ケース"), + (0x331D, "M", "コルナ"), + (0x331E, "M", "コーポ"), + (0x331F, "M", "サイクル"), + (0x3320, "M", "サンチーム"), + (0x3321, "M", "シリング"), + (0x3322, "M", "センチ"), + (0x3323, "M", "セント"), + (0x3324, "M", "ダース"), + (0x3325, "M", "デシ"), + (0x3326, "M", "ドル"), + (0x3327, "M", "トン"), + (0x3328, "M", "ナノ"), + (0x3329, "M", "ノット"), + (0x332A, "M", "ハイツ"), + (0x332B, "M", "パーセント"), + (0x332C, "M", "パーツ"), + (0x332D, "M", "バーレル"), + (0x332E, "M", "ピアストル"), + (0x332F, "M", "ピクル"), + (0x3330, "M", "ピコ"), + (0x3331, "M", "ビル"), + (0x3332, "M", "ファラッド"), + (0x3333, "M", "フィート"), + (0x3334, "M", "ブッシェル"), + (0x3335, "M", "フラン"), + (0x3336, "M", "ヘクタール"), + (0x3337, "M", "ペソ"), + (0x3338, "M", "ペニヒ"), + (0x3339, "M", "ヘルツ"), + (0x333A, "M", "ペンス"), + (0x333B, "M", "ページ"), + (0x333C, "M", "ベータ"), + (0x333D, "M", "ポイント"), + (0x333E, "M", "ボルト"), + (0x333F, "M", "ホン"), + (0x3340, "M", "ポンド"), + (0x3341, "M", "ホール"), + (0x3342, "M", "ホーン"), + (0x3343, "M", "マイクロ"), + (0x3344, "M", "マイル"), + (0x3345, "M", "マッハ"), + (0x3346, "M", "マルク"), + (0x3347, "M", "マンション"), + (0x3348, "M", "ミクロン"), + (0x3349, "M", "ミリ"), + (0x334A, "M", "ミリバール"), + (0x334B, "M", "メガ"), + (0x334C, "M", "メガトン"), + (0x334D, "M", "メートル"), + (0x334E, "M", "ヤード"), + (0x334F, "M", "ヤール"), + (0x3350, "M", "ユアン"), + (0x3351, "M", "リットル"), + (0x3352, "M", "リラ"), + (0x3353, "M", "ルピー"), + (0x3354, "M", "ルーブル"), + (0x3355, "M", "レム"), + (0x3356, "M", "レントゲン"), + (0x3357, "M", "ワット"), + (0x3358, "M", "0点"), + (0x3359, "M", "1点"), + (0x335A, "M", "2点"), + (0x335B, "M", "3点"), + (0x335C, "M", "4点"), + (0x335D, "M", "5点"), + (0x335E, "M", "6点"), + (0x335F, "M", "7点"), + (0x3360, "M", "8点"), + (0x3361, "M", "9点"), + (0x3362, "M", "10点"), + (0x3363, "M", "11点"), + (0x3364, "M", "12点"), + (0x3365, "M", "13点"), + (0x3366, "M", "14点"), + (0x3367, "M", "15点"), + (0x3368, "M", "16点"), + (0x3369, "M", "17点"), + (0x336A, "M", "18点"), + (0x336B, "M", "19点"), + (0x336C, "M", "20点"), + (0x336D, "M", "21点"), + (0x336E, "M", "22点"), + (0x336F, "M", "23点"), + (0x3370, "M", "24点"), + (0x3371, "M", "hpa"), + (0x3372, "M", "da"), + (0x3373, "M", "au"), + (0x3374, "M", "bar"), + (0x3375, "M", "ov"), + (0x3376, "M", "pc"), + (0x3377, "M", "dm"), + (0x3378, "M", "dm2"), + (0x3379, "M", "dm3"), + (0x337A, "M", "iu"), + (0x337B, "M", "平成"), + (0x337C, "M", "昭和"), + (0x337D, "M", "大正"), + ] + + +def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x337E, "M", "明治"), + (0x337F, "M", "株式会社"), + (0x3380, "M", "pa"), + (0x3381, "M", "na"), + (0x3382, "M", "μa"), + (0x3383, "M", "ma"), + (0x3384, "M", "ka"), + (0x3385, "M", "kb"), + (0x3386, "M", "mb"), + (0x3387, "M", "gb"), + (0x3388, "M", "cal"), + (0x3389, "M", "kcal"), + (0x338A, "M", "pf"), + (0x338B, "M", "nf"), + (0x338C, "M", "μf"), + (0x338D, "M", "μg"), + (0x338E, "M", "mg"), + (0x338F, "M", "kg"), + (0x3390, "M", "hz"), + (0x3391, "M", "khz"), + (0x3392, "M", "mhz"), + (0x3393, "M", "ghz"), + (0x3394, "M", "thz"), + (0x3395, "M", "μl"), + (0x3396, "M", "ml"), + (0x3397, "M", "dl"), + (0x3398, "M", "kl"), + (0x3399, "M", "fm"), + (0x339A, "M", "nm"), + (0x339B, "M", "μm"), + (0x339C, "M", "mm"), + (0x339D, "M", "cm"), + (0x339E, "M", "km"), + (0x339F, "M", "mm2"), + (0x33A0, "M", "cm2"), + (0x33A1, "M", "m2"), + (0x33A2, "M", "km2"), + (0x33A3, "M", "mm3"), + (0x33A4, "M", "cm3"), + (0x33A5, "M", "m3"), + (0x33A6, "M", "km3"), + (0x33A7, "M", "m∕s"), + (0x33A8, "M", "m∕s2"), + (0x33A9, "M", "pa"), + (0x33AA, "M", "kpa"), + (0x33AB, "M", "mpa"), + (0x33AC, "M", "gpa"), + (0x33AD, "M", "rad"), + (0x33AE, "M", "rad∕s"), + (0x33AF, "M", "rad∕s2"), + (0x33B0, "M", "ps"), + (0x33B1, "M", "ns"), + (0x33B2, "M", "μs"), + (0x33B3, "M", "ms"), + (0x33B4, "M", "pv"), + (0x33B5, "M", "nv"), + (0x33B6, "M", "μv"), + (0x33B7, "M", "mv"), + (0x33B8, "M", "kv"), + (0x33B9, "M", "mv"), + (0x33BA, "M", "pw"), + (0x33BB, "M", "nw"), + (0x33BC, "M", "μw"), + (0x33BD, "M", "mw"), + (0x33BE, "M", "kw"), + (0x33BF, "M", "mw"), + (0x33C0, "M", "kω"), + (0x33C1, "M", "mω"), + (0x33C2, "X"), + (0x33C3, "M", "bq"), + (0x33C4, "M", "cc"), + (0x33C5, "M", "cd"), + (0x33C6, "M", "c∕kg"), + (0x33C7, "X"), + (0x33C8, "M", "db"), + (0x33C9, "M", "gy"), + (0x33CA, "M", "ha"), + (0x33CB, "M", "hp"), + (0x33CC, "M", "in"), + (0x33CD, "M", "kk"), + (0x33CE, "M", "km"), + (0x33CF, "M", "kt"), + (0x33D0, "M", "lm"), + (0x33D1, "M", "ln"), + (0x33D2, "M", "log"), + (0x33D3, "M", "lx"), + (0x33D4, "M", "mb"), + (0x33D5, "M", "mil"), + (0x33D6, "M", "mol"), + (0x33D7, "M", "ph"), + (0x33D8, "X"), + (0x33D9, "M", "ppm"), + (0x33DA, "M", "pr"), + (0x33DB, "M", "sr"), + (0x33DC, "M", "sv"), + (0x33DD, "M", "wb"), + (0x33DE, "M", "v∕m"), + (0x33DF, "M", "a∕m"), + (0x33E0, "M", "1日"), + (0x33E1, "M", "2日"), + ] + + +def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x33E2, "M", "3日"), + (0x33E3, "M", "4日"), + (0x33E4, "M", "5日"), + (0x33E5, "M", "6日"), + (0x33E6, "M", "7日"), + (0x33E7, "M", "8日"), + (0x33E8, "M", "9日"), + (0x33E9, "M", "10日"), + (0x33EA, "M", "11日"), + (0x33EB, "M", "12日"), + (0x33EC, "M", "13日"), + (0x33ED, "M", "14日"), + (0x33EE, "M", "15日"), + (0x33EF, "M", "16日"), + (0x33F0, "M", "17日"), + (0x33F1, "M", "18日"), + (0x33F2, "M", "19日"), + (0x33F3, "M", "20日"), + (0x33F4, "M", "21日"), + (0x33F5, "M", "22日"), + (0x33F6, "M", "23日"), + (0x33F7, "M", "24日"), + (0x33F8, "M", "25日"), + (0x33F9, "M", "26日"), + (0x33FA, "M", "27日"), + (0x33FB, "M", "28日"), + (0x33FC, "M", "29日"), + (0x33FD, "M", "30日"), + (0x33FE, "M", "31日"), + (0x33FF, "M", "gal"), + (0x3400, "V"), + (0xA48D, "X"), + (0xA490, "V"), + (0xA4C7, "X"), + (0xA4D0, "V"), + (0xA62C, "X"), + (0xA640, "M", "ꙁ"), + (0xA641, "V"), + (0xA642, "M", "ꙃ"), + (0xA643, "V"), + (0xA644, "M", "ꙅ"), + (0xA645, "V"), + (0xA646, "M", "ꙇ"), + (0xA647, "V"), + (0xA648, "M", "ꙉ"), + (0xA649, "V"), + (0xA64A, "M", "ꙋ"), + (0xA64B, "V"), + (0xA64C, "M", "ꙍ"), + (0xA64D, "V"), + (0xA64E, "M", "ꙏ"), + (0xA64F, "V"), + (0xA650, "M", "ꙑ"), + (0xA651, "V"), + (0xA652, "M", "ꙓ"), + (0xA653, "V"), + (0xA654, "M", "ꙕ"), + (0xA655, "V"), + (0xA656, "M", "ꙗ"), + (0xA657, "V"), + (0xA658, "M", "ꙙ"), + (0xA659, "V"), + (0xA65A, "M", "ꙛ"), + (0xA65B, "V"), + (0xA65C, "M", "ꙝ"), + (0xA65D, "V"), + (0xA65E, "M", "ꙟ"), + (0xA65F, "V"), + (0xA660, "M", "ꙡ"), + (0xA661, "V"), + (0xA662, "M", "ꙣ"), + (0xA663, "V"), + (0xA664, "M", "ꙥ"), + (0xA665, "V"), + (0xA666, "M", "ꙧ"), + (0xA667, "V"), + (0xA668, "M", "ꙩ"), + (0xA669, "V"), + (0xA66A, "M", "ꙫ"), + (0xA66B, "V"), + (0xA66C, "M", "ꙭ"), + (0xA66D, "V"), + (0xA680, "M", "ꚁ"), + (0xA681, "V"), + (0xA682, "M", "ꚃ"), + (0xA683, "V"), + (0xA684, "M", "ꚅ"), + (0xA685, "V"), + (0xA686, "M", "ꚇ"), + (0xA687, "V"), + (0xA688, "M", "ꚉ"), + (0xA689, "V"), + (0xA68A, "M", "ꚋ"), + (0xA68B, "V"), + (0xA68C, "M", "ꚍ"), + (0xA68D, "V"), + (0xA68E, "M", "ꚏ"), + (0xA68F, "V"), + (0xA690, "M", "ꚑ"), + (0xA691, "V"), + ] + + +def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA692, "M", "ꚓ"), + (0xA693, "V"), + (0xA694, "M", "ꚕ"), + (0xA695, "V"), + (0xA696, "M", "ꚗ"), + (0xA697, "V"), + (0xA698, "M", "ꚙ"), + (0xA699, "V"), + (0xA69A, "M", "ꚛ"), + (0xA69B, "V"), + (0xA69C, "M", "ъ"), + (0xA69D, "M", "ь"), + (0xA69E, "V"), + (0xA6F8, "X"), + (0xA700, "V"), + (0xA722, "M", "ꜣ"), + (0xA723, "V"), + (0xA724, "M", "ꜥ"), + (0xA725, "V"), + (0xA726, "M", "ꜧ"), + (0xA727, "V"), + (0xA728, "M", "ꜩ"), + (0xA729, "V"), + (0xA72A, "M", "ꜫ"), + (0xA72B, "V"), + (0xA72C, "M", "ꜭ"), + (0xA72D, "V"), + (0xA72E, "M", "ꜯ"), + (0xA72F, "V"), + (0xA732, "M", "ꜳ"), + (0xA733, "V"), + (0xA734, "M", "ꜵ"), + (0xA735, "V"), + (0xA736, "M", "ꜷ"), + (0xA737, "V"), + (0xA738, "M", "ꜹ"), + (0xA739, "V"), + (0xA73A, "M", "ꜻ"), + (0xA73B, "V"), + (0xA73C, "M", "ꜽ"), + (0xA73D, "V"), + (0xA73E, "M", "ꜿ"), + (0xA73F, "V"), + (0xA740, "M", "ꝁ"), + (0xA741, "V"), + (0xA742, "M", "ꝃ"), + (0xA743, "V"), + (0xA744, "M", "ꝅ"), + (0xA745, "V"), + (0xA746, "M", "ꝇ"), + (0xA747, "V"), + (0xA748, "M", "ꝉ"), + (0xA749, "V"), + (0xA74A, "M", "ꝋ"), + (0xA74B, "V"), + (0xA74C, "M", "ꝍ"), + (0xA74D, "V"), + (0xA74E, "M", "ꝏ"), + (0xA74F, "V"), + (0xA750, "M", "ꝑ"), + (0xA751, "V"), + (0xA752, "M", "ꝓ"), + (0xA753, "V"), + (0xA754, "M", "ꝕ"), + (0xA755, "V"), + (0xA756, "M", "ꝗ"), + (0xA757, "V"), + (0xA758, "M", "ꝙ"), + (0xA759, "V"), + (0xA75A, "M", "ꝛ"), + (0xA75B, "V"), + (0xA75C, "M", "ꝝ"), + (0xA75D, "V"), + (0xA75E, "M", "ꝟ"), + (0xA75F, "V"), + (0xA760, "M", "ꝡ"), + (0xA761, "V"), + (0xA762, "M", "ꝣ"), + (0xA763, "V"), + (0xA764, "M", "ꝥ"), + (0xA765, "V"), + (0xA766, "M", "ꝧ"), + (0xA767, "V"), + (0xA768, "M", "ꝩ"), + (0xA769, "V"), + (0xA76A, "M", "ꝫ"), + (0xA76B, "V"), + (0xA76C, "M", "ꝭ"), + (0xA76D, "V"), + (0xA76E, "M", "ꝯ"), + (0xA76F, "V"), + (0xA770, "M", "ꝯ"), + (0xA771, "V"), + (0xA779, "M", "ꝺ"), + (0xA77A, "V"), + (0xA77B, "M", "ꝼ"), + (0xA77C, "V"), + (0xA77D, "M", "ᵹ"), + (0xA77E, "M", "ꝿ"), + (0xA77F, "V"), + ] + + +def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA780, "M", "ꞁ"), + (0xA781, "V"), + (0xA782, "M", "ꞃ"), + (0xA783, "V"), + (0xA784, "M", "ꞅ"), + (0xA785, "V"), + (0xA786, "M", "ꞇ"), + (0xA787, "V"), + (0xA78B, "M", "ꞌ"), + (0xA78C, "V"), + (0xA78D, "M", "ɥ"), + (0xA78E, "V"), + (0xA790, "M", "ꞑ"), + (0xA791, "V"), + (0xA792, "M", "ꞓ"), + (0xA793, "V"), + (0xA796, "M", "ꞗ"), + (0xA797, "V"), + (0xA798, "M", "ꞙ"), + (0xA799, "V"), + (0xA79A, "M", "ꞛ"), + (0xA79B, "V"), + (0xA79C, "M", "ꞝ"), + (0xA79D, "V"), + (0xA79E, "M", "ꞟ"), + (0xA79F, "V"), + (0xA7A0, "M", "ꞡ"), + (0xA7A1, "V"), + (0xA7A2, "M", "ꞣ"), + (0xA7A3, "V"), + (0xA7A4, "M", "ꞥ"), + (0xA7A5, "V"), + (0xA7A6, "M", "ꞧ"), + (0xA7A7, "V"), + (0xA7A8, "M", "ꞩ"), + (0xA7A9, "V"), + (0xA7AA, "M", "ɦ"), + (0xA7AB, "M", "ɜ"), + (0xA7AC, "M", "ɡ"), + (0xA7AD, "M", "ɬ"), + (0xA7AE, "M", "ɪ"), + (0xA7AF, "V"), + (0xA7B0, "M", "ʞ"), + (0xA7B1, "M", "ʇ"), + (0xA7B2, "M", "ʝ"), + (0xA7B3, "M", "ꭓ"), + (0xA7B4, "M", "ꞵ"), + (0xA7B5, "V"), + (0xA7B6, "M", "ꞷ"), + (0xA7B7, "V"), + (0xA7B8, "M", "ꞹ"), + (0xA7B9, "V"), + (0xA7BA, "M", "ꞻ"), + (0xA7BB, "V"), + (0xA7BC, "M", "ꞽ"), + (0xA7BD, "V"), + (0xA7BE, "M", "ꞿ"), + (0xA7BF, "V"), + (0xA7C0, "M", "ꟁ"), + (0xA7C1, "V"), + (0xA7C2, "M", "ꟃ"), + (0xA7C3, "V"), + (0xA7C4, "M", "ꞔ"), + (0xA7C5, "M", "ʂ"), + (0xA7C6, "M", "ᶎ"), + (0xA7C7, "M", "ꟈ"), + (0xA7C8, "V"), + (0xA7C9, "M", "ꟊ"), + (0xA7CA, "V"), + (0xA7CB, "X"), + (0xA7D0, "M", "ꟑ"), + (0xA7D1, "V"), + (0xA7D2, "X"), + (0xA7D3, "V"), + (0xA7D4, "X"), + (0xA7D5, "V"), + (0xA7D6, "M", "ꟗ"), + (0xA7D7, "V"), + (0xA7D8, "M", "ꟙ"), + (0xA7D9, "V"), + (0xA7DA, "X"), + (0xA7F2, "M", "c"), + (0xA7F3, "M", "f"), + (0xA7F4, "M", "q"), + (0xA7F5, "M", "ꟶ"), + (0xA7F6, "V"), + (0xA7F8, "M", "ħ"), + (0xA7F9, "M", "œ"), + (0xA7FA, "V"), + (0xA82D, "X"), + (0xA830, "V"), + (0xA83A, "X"), + (0xA840, "V"), + (0xA878, "X"), + (0xA880, "V"), + (0xA8C6, "X"), + (0xA8CE, "V"), + (0xA8DA, "X"), + (0xA8E0, "V"), + (0xA954, "X"), + ] + + +def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA95F, "V"), + (0xA97D, "X"), + (0xA980, "V"), + (0xA9CE, "X"), + (0xA9CF, "V"), + (0xA9DA, "X"), + (0xA9DE, "V"), + (0xA9FF, "X"), + (0xAA00, "V"), + (0xAA37, "X"), + (0xAA40, "V"), + (0xAA4E, "X"), + (0xAA50, "V"), + (0xAA5A, "X"), + (0xAA5C, "V"), + (0xAAC3, "X"), + (0xAADB, "V"), + (0xAAF7, "X"), + (0xAB01, "V"), + (0xAB07, "X"), + (0xAB09, "V"), + (0xAB0F, "X"), + (0xAB11, "V"), + (0xAB17, "X"), + (0xAB20, "V"), + (0xAB27, "X"), + (0xAB28, "V"), + (0xAB2F, "X"), + (0xAB30, "V"), + (0xAB5C, "M", "ꜧ"), + (0xAB5D, "M", "ꬷ"), + (0xAB5E, "M", "ɫ"), + (0xAB5F, "M", "ꭒ"), + (0xAB60, "V"), + (0xAB69, "M", "ʍ"), + (0xAB6A, "V"), + (0xAB6C, "X"), + (0xAB70, "M", "Ꭰ"), + (0xAB71, "M", "Ꭱ"), + (0xAB72, "M", "Ꭲ"), + (0xAB73, "M", "Ꭳ"), + (0xAB74, "M", "Ꭴ"), + (0xAB75, "M", "Ꭵ"), + (0xAB76, "M", "Ꭶ"), + (0xAB77, "M", "Ꭷ"), + (0xAB78, "M", "Ꭸ"), + (0xAB79, "M", "Ꭹ"), + (0xAB7A, "M", "Ꭺ"), + (0xAB7B, "M", "Ꭻ"), + (0xAB7C, "M", "Ꭼ"), + (0xAB7D, "M", "Ꭽ"), + (0xAB7E, "M", "Ꭾ"), + (0xAB7F, "M", "Ꭿ"), + (0xAB80, "M", "Ꮀ"), + (0xAB81, "M", "Ꮁ"), + (0xAB82, "M", "Ꮂ"), + (0xAB83, "M", "Ꮃ"), + (0xAB84, "M", "Ꮄ"), + (0xAB85, "M", "Ꮅ"), + (0xAB86, "M", "Ꮆ"), + (0xAB87, "M", "Ꮇ"), + (0xAB88, "M", "Ꮈ"), + (0xAB89, "M", "Ꮉ"), + (0xAB8A, "M", "Ꮊ"), + (0xAB8B, "M", "Ꮋ"), + (0xAB8C, "M", "Ꮌ"), + (0xAB8D, "M", "Ꮍ"), + (0xAB8E, "M", "Ꮎ"), + (0xAB8F, "M", "Ꮏ"), + (0xAB90, "M", "Ꮐ"), + (0xAB91, "M", "Ꮑ"), + (0xAB92, "M", "Ꮒ"), + (0xAB93, "M", "Ꮓ"), + (0xAB94, "M", "Ꮔ"), + (0xAB95, "M", "Ꮕ"), + (0xAB96, "M", "Ꮖ"), + (0xAB97, "M", "Ꮗ"), + (0xAB98, "M", "Ꮘ"), + (0xAB99, "M", "Ꮙ"), + (0xAB9A, "M", "Ꮚ"), + (0xAB9B, "M", "Ꮛ"), + (0xAB9C, "M", "Ꮜ"), + (0xAB9D, "M", "Ꮝ"), + (0xAB9E, "M", "Ꮞ"), + (0xAB9F, "M", "Ꮟ"), + (0xABA0, "M", "Ꮠ"), + (0xABA1, "M", "Ꮡ"), + (0xABA2, "M", "Ꮢ"), + (0xABA3, "M", "Ꮣ"), + (0xABA4, "M", "Ꮤ"), + (0xABA5, "M", "Ꮥ"), + (0xABA6, "M", "Ꮦ"), + (0xABA7, "M", "Ꮧ"), + (0xABA8, "M", "Ꮨ"), + (0xABA9, "M", "Ꮩ"), + (0xABAA, "M", "Ꮪ"), + (0xABAB, "M", "Ꮫ"), + (0xABAC, "M", "Ꮬ"), + (0xABAD, "M", "Ꮭ"), + (0xABAE, "M", "Ꮮ"), + ] + + +def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xABAF, "M", "Ꮯ"), + (0xABB0, "M", "Ꮰ"), + (0xABB1, "M", "Ꮱ"), + (0xABB2, "M", "Ꮲ"), + (0xABB3, "M", "Ꮳ"), + (0xABB4, "M", "Ꮴ"), + (0xABB5, "M", "Ꮵ"), + (0xABB6, "M", "Ꮶ"), + (0xABB7, "M", "Ꮷ"), + (0xABB8, "M", "Ꮸ"), + (0xABB9, "M", "Ꮹ"), + (0xABBA, "M", "Ꮺ"), + (0xABBB, "M", "Ꮻ"), + (0xABBC, "M", "Ꮼ"), + (0xABBD, "M", "Ꮽ"), + (0xABBE, "M", "Ꮾ"), + (0xABBF, "M", "Ꮿ"), + (0xABC0, "V"), + (0xABEE, "X"), + (0xABF0, "V"), + (0xABFA, "X"), + (0xAC00, "V"), + (0xD7A4, "X"), + (0xD7B0, "V"), + (0xD7C7, "X"), + (0xD7CB, "V"), + (0xD7FC, "X"), + (0xF900, "M", "豈"), + (0xF901, "M", "更"), + (0xF902, "M", "車"), + (0xF903, "M", "賈"), + (0xF904, "M", "滑"), + (0xF905, "M", "串"), + (0xF906, "M", "句"), + (0xF907, "M", "龜"), + (0xF909, "M", "契"), + (0xF90A, "M", "金"), + (0xF90B, "M", "喇"), + (0xF90C, "M", "奈"), + (0xF90D, "M", "懶"), + (0xF90E, "M", "癩"), + (0xF90F, "M", "羅"), + (0xF910, "M", "蘿"), + (0xF911, "M", "螺"), + (0xF912, "M", "裸"), + (0xF913, "M", "邏"), + (0xF914, "M", "樂"), + (0xF915, "M", "洛"), + (0xF916, "M", "烙"), + (0xF917, "M", "珞"), + (0xF918, "M", "落"), + (0xF919, "M", "酪"), + (0xF91A, "M", "駱"), + (0xF91B, "M", "亂"), + (0xF91C, "M", "卵"), + (0xF91D, "M", "欄"), + (0xF91E, "M", "爛"), + (0xF91F, "M", "蘭"), + (0xF920, "M", "鸞"), + (0xF921, "M", "嵐"), + (0xF922, "M", "濫"), + (0xF923, "M", "藍"), + (0xF924, "M", "襤"), + (0xF925, "M", "拉"), + (0xF926, "M", "臘"), + (0xF927, "M", "蠟"), + (0xF928, "M", "廊"), + (0xF929, "M", "朗"), + (0xF92A, "M", "浪"), + (0xF92B, "M", "狼"), + (0xF92C, "M", "郎"), + (0xF92D, "M", "來"), + (0xF92E, "M", "冷"), + (0xF92F, "M", "勞"), + (0xF930, "M", "擄"), + (0xF931, "M", "櫓"), + (0xF932, "M", "爐"), + (0xF933, "M", "盧"), + (0xF934, "M", "老"), + (0xF935, "M", "蘆"), + (0xF936, "M", "虜"), + (0xF937, "M", "路"), + (0xF938, "M", "露"), + (0xF939, "M", "魯"), + (0xF93A, "M", "鷺"), + (0xF93B, "M", "碌"), + (0xF93C, "M", "祿"), + (0xF93D, "M", "綠"), + (0xF93E, "M", "菉"), + (0xF93F, "M", "錄"), + (0xF940, "M", "鹿"), + (0xF941, "M", "論"), + (0xF942, "M", "壟"), + (0xF943, "M", "弄"), + (0xF944, "M", "籠"), + (0xF945, "M", "聾"), + (0xF946, "M", "牢"), + (0xF947, "M", "磊"), + (0xF948, "M", "賂"), + (0xF949, "M", "雷"), + ] + + +def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xF94A, "M", "壘"), + (0xF94B, "M", "屢"), + (0xF94C, "M", "樓"), + (0xF94D, "M", "淚"), + (0xF94E, "M", "漏"), + (0xF94F, "M", "累"), + (0xF950, "M", "縷"), + (0xF951, "M", "陋"), + (0xF952, "M", "勒"), + (0xF953, "M", "肋"), + (0xF954, "M", "凜"), + (0xF955, "M", "凌"), + (0xF956, "M", "稜"), + (0xF957, "M", "綾"), + (0xF958, "M", "菱"), + (0xF959, "M", "陵"), + (0xF95A, "M", "讀"), + (0xF95B, "M", "拏"), + (0xF95C, "M", "樂"), + (0xF95D, "M", "諾"), + (0xF95E, "M", "丹"), + (0xF95F, "M", "寧"), + (0xF960, "M", "怒"), + (0xF961, "M", "率"), + (0xF962, "M", "異"), + (0xF963, "M", "北"), + (0xF964, "M", "磻"), + (0xF965, "M", "便"), + (0xF966, "M", "復"), + (0xF967, "M", "不"), + (0xF968, "M", "泌"), + (0xF969, "M", "數"), + (0xF96A, "M", "索"), + (0xF96B, "M", "參"), + (0xF96C, "M", "塞"), + (0xF96D, "M", "省"), + (0xF96E, "M", "葉"), + (0xF96F, "M", "說"), + (0xF970, "M", "殺"), + (0xF971, "M", "辰"), + (0xF972, "M", "沈"), + (0xF973, "M", "拾"), + (0xF974, "M", "若"), + (0xF975, "M", "掠"), + (0xF976, "M", "略"), + (0xF977, "M", "亮"), + (0xF978, "M", "兩"), + (0xF979, "M", "凉"), + (0xF97A, "M", "梁"), + (0xF97B, "M", "糧"), + (0xF97C, "M", "良"), + (0xF97D, "M", "諒"), + (0xF97E, "M", "量"), + (0xF97F, "M", "勵"), + (0xF980, "M", "呂"), + (0xF981, "M", "女"), + (0xF982, "M", "廬"), + (0xF983, "M", "旅"), + (0xF984, "M", "濾"), + (0xF985, "M", "礪"), + (0xF986, "M", "閭"), + (0xF987, "M", "驪"), + (0xF988, "M", "麗"), + (0xF989, "M", "黎"), + (0xF98A, "M", "力"), + (0xF98B, "M", "曆"), + (0xF98C, "M", "歷"), + (0xF98D, "M", "轢"), + (0xF98E, "M", "年"), + (0xF98F, "M", "憐"), + (0xF990, "M", "戀"), + (0xF991, "M", "撚"), + (0xF992, "M", "漣"), + (0xF993, "M", "煉"), + (0xF994, "M", "璉"), + (0xF995, "M", "秊"), + (0xF996, "M", "練"), + (0xF997, "M", "聯"), + (0xF998, "M", "輦"), + (0xF999, "M", "蓮"), + (0xF99A, "M", "連"), + (0xF99B, "M", "鍊"), + (0xF99C, "M", "列"), + (0xF99D, "M", "劣"), + (0xF99E, "M", "咽"), + (0xF99F, "M", "烈"), + (0xF9A0, "M", "裂"), + (0xF9A1, "M", "說"), + (0xF9A2, "M", "廉"), + (0xF9A3, "M", "念"), + (0xF9A4, "M", "捻"), + (0xF9A5, "M", "殮"), + (0xF9A6, "M", "簾"), + (0xF9A7, "M", "獵"), + (0xF9A8, "M", "令"), + (0xF9A9, "M", "囹"), + (0xF9AA, "M", "寧"), + (0xF9AB, "M", "嶺"), + (0xF9AC, "M", "怜"), + (0xF9AD, "M", "玲"), + ] + + +def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xF9AE, "M", "瑩"), + (0xF9AF, "M", "羚"), + (0xF9B0, "M", "聆"), + (0xF9B1, "M", "鈴"), + (0xF9B2, "M", "零"), + (0xF9B3, "M", "靈"), + (0xF9B4, "M", "領"), + (0xF9B5, "M", "例"), + (0xF9B6, "M", "禮"), + (0xF9B7, "M", "醴"), + (0xF9B8, "M", "隸"), + (0xF9B9, "M", "惡"), + (0xF9BA, "M", "了"), + (0xF9BB, "M", "僚"), + (0xF9BC, "M", "寮"), + (0xF9BD, "M", "尿"), + (0xF9BE, "M", "料"), + (0xF9BF, "M", "樂"), + (0xF9C0, "M", "燎"), + (0xF9C1, "M", "療"), + (0xF9C2, "M", "蓼"), + (0xF9C3, "M", "遼"), + (0xF9C4, "M", "龍"), + (0xF9C5, "M", "暈"), + (0xF9C6, "M", "阮"), + (0xF9C7, "M", "劉"), + (0xF9C8, "M", "杻"), + (0xF9C9, "M", "柳"), + (0xF9CA, "M", "流"), + (0xF9CB, "M", "溜"), + (0xF9CC, "M", "琉"), + (0xF9CD, "M", "留"), + (0xF9CE, "M", "硫"), + (0xF9CF, "M", "紐"), + (0xF9D0, "M", "類"), + (0xF9D1, "M", "六"), + (0xF9D2, "M", "戮"), + (0xF9D3, "M", "陸"), + (0xF9D4, "M", "倫"), + (0xF9D5, "M", "崙"), + (0xF9D6, "M", "淪"), + (0xF9D7, "M", "輪"), + (0xF9D8, "M", "律"), + (0xF9D9, "M", "慄"), + (0xF9DA, "M", "栗"), + (0xF9DB, "M", "率"), + (0xF9DC, "M", "隆"), + (0xF9DD, "M", "利"), + (0xF9DE, "M", "吏"), + (0xF9DF, "M", "履"), + (0xF9E0, "M", "易"), + (0xF9E1, "M", "李"), + (0xF9E2, "M", "梨"), + (0xF9E3, "M", "泥"), + (0xF9E4, "M", "理"), + (0xF9E5, "M", "痢"), + (0xF9E6, "M", "罹"), + (0xF9E7, "M", "裏"), + (0xF9E8, "M", "裡"), + (0xF9E9, "M", "里"), + (0xF9EA, "M", "離"), + (0xF9EB, "M", "匿"), + (0xF9EC, "M", "溺"), + (0xF9ED, "M", "吝"), + (0xF9EE, "M", "燐"), + (0xF9EF, "M", "璘"), + (0xF9F0, "M", "藺"), + (0xF9F1, "M", "隣"), + (0xF9F2, "M", "鱗"), + (0xF9F3, "M", "麟"), + (0xF9F4, "M", "林"), + (0xF9F5, "M", "淋"), + (0xF9F6, "M", "臨"), + (0xF9F7, "M", "立"), + (0xF9F8, "M", "笠"), + (0xF9F9, "M", "粒"), + (0xF9FA, "M", "狀"), + (0xF9FB, "M", "炙"), + (0xF9FC, "M", "識"), + (0xF9FD, "M", "什"), + (0xF9FE, "M", "茶"), + (0xF9FF, "M", "刺"), + (0xFA00, "M", "切"), + (0xFA01, "M", "度"), + (0xFA02, "M", "拓"), + (0xFA03, "M", "糖"), + (0xFA04, "M", "宅"), + (0xFA05, "M", "洞"), + (0xFA06, "M", "暴"), + (0xFA07, "M", "輻"), + (0xFA08, "M", "行"), + (0xFA09, "M", "降"), + (0xFA0A, "M", "見"), + (0xFA0B, "M", "廓"), + (0xFA0C, "M", "兀"), + (0xFA0D, "M", "嗀"), + (0xFA0E, "V"), + (0xFA10, "M", "塚"), + (0xFA11, "V"), + (0xFA12, "M", "晴"), + ] + + +def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFA13, "V"), + (0xFA15, "M", "凞"), + (0xFA16, "M", "猪"), + (0xFA17, "M", "益"), + (0xFA18, "M", "礼"), + (0xFA19, "M", "神"), + (0xFA1A, "M", "祥"), + (0xFA1B, "M", "福"), + (0xFA1C, "M", "靖"), + (0xFA1D, "M", "精"), + (0xFA1E, "M", "羽"), + (0xFA1F, "V"), + (0xFA20, "M", "蘒"), + (0xFA21, "V"), + (0xFA22, "M", "諸"), + (0xFA23, "V"), + (0xFA25, "M", "逸"), + (0xFA26, "M", "都"), + (0xFA27, "V"), + (0xFA2A, "M", "飯"), + (0xFA2B, "M", "飼"), + (0xFA2C, "M", "館"), + (0xFA2D, "M", "鶴"), + (0xFA2E, "M", "郞"), + (0xFA2F, "M", "隷"), + (0xFA30, "M", "侮"), + (0xFA31, "M", "僧"), + (0xFA32, "M", "免"), + (0xFA33, "M", "勉"), + (0xFA34, "M", "勤"), + (0xFA35, "M", "卑"), + (0xFA36, "M", "喝"), + (0xFA37, "M", "嘆"), + (0xFA38, "M", "器"), + (0xFA39, "M", "塀"), + (0xFA3A, "M", "墨"), + (0xFA3B, "M", "層"), + (0xFA3C, "M", "屮"), + (0xFA3D, "M", "悔"), + (0xFA3E, "M", "慨"), + (0xFA3F, "M", "憎"), + (0xFA40, "M", "懲"), + (0xFA41, "M", "敏"), + (0xFA42, "M", "既"), + (0xFA43, "M", "暑"), + (0xFA44, "M", "梅"), + (0xFA45, "M", "海"), + (0xFA46, "M", "渚"), + (0xFA47, "M", "漢"), + (0xFA48, "M", "煮"), + (0xFA49, "M", "爫"), + (0xFA4A, "M", "琢"), + (0xFA4B, "M", "碑"), + (0xFA4C, "M", "社"), + (0xFA4D, "M", "祉"), + (0xFA4E, "M", "祈"), + (0xFA4F, "M", "祐"), + (0xFA50, "M", "祖"), + (0xFA51, "M", "祝"), + (0xFA52, "M", "禍"), + (0xFA53, "M", "禎"), + (0xFA54, "M", "穀"), + (0xFA55, "M", "突"), + (0xFA56, "M", "節"), + (0xFA57, "M", "練"), + (0xFA58, "M", "縉"), + (0xFA59, "M", "繁"), + (0xFA5A, "M", "署"), + (0xFA5B, "M", "者"), + (0xFA5C, "M", "臭"), + (0xFA5D, "M", "艹"), + (0xFA5F, "M", "著"), + (0xFA60, "M", "褐"), + (0xFA61, "M", "視"), + (0xFA62, "M", "謁"), + (0xFA63, "M", "謹"), + (0xFA64, "M", "賓"), + (0xFA65, "M", "贈"), + (0xFA66, "M", "辶"), + (0xFA67, "M", "逸"), + (0xFA68, "M", "難"), + (0xFA69, "M", "響"), + (0xFA6A, "M", "頻"), + (0xFA6B, "M", "恵"), + (0xFA6C, "M", "𤋮"), + (0xFA6D, "M", "舘"), + (0xFA6E, "X"), + (0xFA70, "M", "並"), + (0xFA71, "M", "况"), + (0xFA72, "M", "全"), + (0xFA73, "M", "侀"), + (0xFA74, "M", "充"), + (0xFA75, "M", "冀"), + (0xFA76, "M", "勇"), + (0xFA77, "M", "勺"), + (0xFA78, "M", "喝"), + (0xFA79, "M", "啕"), + (0xFA7A, "M", "喙"), + (0xFA7B, "M", "嗢"), + (0xFA7C, "M", "塚"), + ] + + +def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFA7D, "M", "墳"), + (0xFA7E, "M", "奄"), + (0xFA7F, "M", "奔"), + (0xFA80, "M", "婢"), + (0xFA81, "M", "嬨"), + (0xFA82, "M", "廒"), + (0xFA83, "M", "廙"), + (0xFA84, "M", "彩"), + (0xFA85, "M", "徭"), + (0xFA86, "M", "惘"), + (0xFA87, "M", "慎"), + (0xFA88, "M", "愈"), + (0xFA89, "M", "憎"), + (0xFA8A, "M", "慠"), + (0xFA8B, "M", "懲"), + (0xFA8C, "M", "戴"), + (0xFA8D, "M", "揄"), + (0xFA8E, "M", "搜"), + (0xFA8F, "M", "摒"), + (0xFA90, "M", "敖"), + (0xFA91, "M", "晴"), + (0xFA92, "M", "朗"), + (0xFA93, "M", "望"), + (0xFA94, "M", "杖"), + (0xFA95, "M", "歹"), + (0xFA96, "M", "殺"), + (0xFA97, "M", "流"), + (0xFA98, "M", "滛"), + (0xFA99, "M", "滋"), + (0xFA9A, "M", "漢"), + (0xFA9B, "M", "瀞"), + (0xFA9C, "M", "煮"), + (0xFA9D, "M", "瞧"), + (0xFA9E, "M", "爵"), + (0xFA9F, "M", "犯"), + (0xFAA0, "M", "猪"), + (0xFAA1, "M", "瑱"), + (0xFAA2, "M", "甆"), + (0xFAA3, "M", "画"), + (0xFAA4, "M", "瘝"), + (0xFAA5, "M", "瘟"), + (0xFAA6, "M", "益"), + (0xFAA7, "M", "盛"), + (0xFAA8, "M", "直"), + (0xFAA9, "M", "睊"), + (0xFAAA, "M", "着"), + (0xFAAB, "M", "磌"), + (0xFAAC, "M", "窱"), + (0xFAAD, "M", "節"), + (0xFAAE, "M", "类"), + (0xFAAF, "M", "絛"), + (0xFAB0, "M", "練"), + (0xFAB1, "M", "缾"), + (0xFAB2, "M", "者"), + (0xFAB3, "M", "荒"), + (0xFAB4, "M", "華"), + (0xFAB5, "M", "蝹"), + (0xFAB6, "M", "襁"), + (0xFAB7, "M", "覆"), + (0xFAB8, "M", "視"), + (0xFAB9, "M", "調"), + (0xFABA, "M", "諸"), + (0xFABB, "M", "請"), + (0xFABC, "M", "謁"), + (0xFABD, "M", "諾"), + (0xFABE, "M", "諭"), + (0xFABF, "M", "謹"), + (0xFAC0, "M", "變"), + (0xFAC1, "M", "贈"), + (0xFAC2, "M", "輸"), + (0xFAC3, "M", "遲"), + (0xFAC4, "M", "醙"), + (0xFAC5, "M", "鉶"), + (0xFAC6, "M", "陼"), + (0xFAC7, "M", "難"), + (0xFAC8, "M", "靖"), + (0xFAC9, "M", "韛"), + (0xFACA, "M", "響"), + (0xFACB, "M", "頋"), + (0xFACC, "M", "頻"), + (0xFACD, "M", "鬒"), + (0xFACE, "M", "龜"), + (0xFACF, "M", "𢡊"), + (0xFAD0, "M", "𢡄"), + (0xFAD1, "M", "𣏕"), + (0xFAD2, "M", "㮝"), + (0xFAD3, "M", "䀘"), + (0xFAD4, "M", "䀹"), + (0xFAD5, "M", "𥉉"), + (0xFAD6, "M", "𥳐"), + (0xFAD7, "M", "𧻓"), + (0xFAD8, "M", "齃"), + (0xFAD9, "M", "龎"), + (0xFADA, "X"), + (0xFB00, "M", "ff"), + (0xFB01, "M", "fi"), + (0xFB02, "M", "fl"), + (0xFB03, "M", "ffi"), + (0xFB04, "M", "ffl"), + (0xFB05, "M", "st"), + ] + + +def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFB07, "X"), + (0xFB13, "M", "մն"), + (0xFB14, "M", "մե"), + (0xFB15, "M", "մի"), + (0xFB16, "M", "վն"), + (0xFB17, "M", "մխ"), + (0xFB18, "X"), + (0xFB1D, "M", "יִ"), + (0xFB1E, "V"), + (0xFB1F, "M", "ײַ"), + (0xFB20, "M", "ע"), + (0xFB21, "M", "א"), + (0xFB22, "M", "ד"), + (0xFB23, "M", "ה"), + (0xFB24, "M", "כ"), + (0xFB25, "M", "ל"), + (0xFB26, "M", "ם"), + (0xFB27, "M", "ר"), + (0xFB28, "M", "ת"), + (0xFB29, "3", "+"), + (0xFB2A, "M", "שׁ"), + (0xFB2B, "M", "שׂ"), + (0xFB2C, "M", "שּׁ"), + (0xFB2D, "M", "שּׂ"), + (0xFB2E, "M", "אַ"), + (0xFB2F, "M", "אָ"), + (0xFB30, "M", "אּ"), + (0xFB31, "M", "בּ"), + (0xFB32, "M", "גּ"), + (0xFB33, "M", "דּ"), + (0xFB34, "M", "הּ"), + (0xFB35, "M", "וּ"), + (0xFB36, "M", "זּ"), + (0xFB37, "X"), + (0xFB38, "M", "טּ"), + (0xFB39, "M", "יּ"), + (0xFB3A, "M", "ךּ"), + (0xFB3B, "M", "כּ"), + (0xFB3C, "M", "לּ"), + (0xFB3D, "X"), + (0xFB3E, "M", "מּ"), + (0xFB3F, "X"), + (0xFB40, "M", "נּ"), + (0xFB41, "M", "סּ"), + (0xFB42, "X"), + (0xFB43, "M", "ףּ"), + (0xFB44, "M", "פּ"), + (0xFB45, "X"), + (0xFB46, "M", "צּ"), + (0xFB47, "M", "קּ"), + (0xFB48, "M", "רּ"), + (0xFB49, "M", "שּ"), + (0xFB4A, "M", "תּ"), + (0xFB4B, "M", "וֹ"), + (0xFB4C, "M", "בֿ"), + (0xFB4D, "M", "כֿ"), + (0xFB4E, "M", "פֿ"), + (0xFB4F, "M", "אל"), + (0xFB50, "M", "ٱ"), + (0xFB52, "M", "ٻ"), + (0xFB56, "M", "پ"), + (0xFB5A, "M", "ڀ"), + (0xFB5E, "M", "ٺ"), + (0xFB62, "M", "ٿ"), + (0xFB66, "M", "ٹ"), + (0xFB6A, "M", "ڤ"), + (0xFB6E, "M", "ڦ"), + (0xFB72, "M", "ڄ"), + (0xFB76, "M", "ڃ"), + (0xFB7A, "M", "چ"), + (0xFB7E, "M", "ڇ"), + (0xFB82, "M", "ڍ"), + (0xFB84, "M", "ڌ"), + (0xFB86, "M", "ڎ"), + (0xFB88, "M", "ڈ"), + (0xFB8A, "M", "ژ"), + (0xFB8C, "M", "ڑ"), + (0xFB8E, "M", "ک"), + (0xFB92, "M", "گ"), + (0xFB96, "M", "ڳ"), + (0xFB9A, "M", "ڱ"), + (0xFB9E, "M", "ں"), + (0xFBA0, "M", "ڻ"), + (0xFBA4, "M", "ۀ"), + (0xFBA6, "M", "ہ"), + (0xFBAA, "M", "ھ"), + (0xFBAE, "M", "ے"), + (0xFBB0, "M", "ۓ"), + (0xFBB2, "V"), + (0xFBC3, "X"), + (0xFBD3, "M", "ڭ"), + (0xFBD7, "M", "ۇ"), + (0xFBD9, "M", "ۆ"), + (0xFBDB, "M", "ۈ"), + (0xFBDD, "M", "ۇٴ"), + (0xFBDE, "M", "ۋ"), + (0xFBE0, "M", "ۅ"), + (0xFBE2, "M", "ۉ"), + (0xFBE4, "M", "ې"), + (0xFBE8, "M", "ى"), + ] + + +def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFBEA, "M", "ئا"), + (0xFBEC, "M", "ئە"), + (0xFBEE, "M", "ئو"), + (0xFBF0, "M", "ئۇ"), + (0xFBF2, "M", "ئۆ"), + (0xFBF4, "M", "ئۈ"), + (0xFBF6, "M", "ئې"), + (0xFBF9, "M", "ئى"), + (0xFBFC, "M", "ی"), + (0xFC00, "M", "ئج"), + (0xFC01, "M", "ئح"), + (0xFC02, "M", "ئم"), + (0xFC03, "M", "ئى"), + (0xFC04, "M", "ئي"), + (0xFC05, "M", "بج"), + (0xFC06, "M", "بح"), + (0xFC07, "M", "بخ"), + (0xFC08, "M", "بم"), + (0xFC09, "M", "بى"), + (0xFC0A, "M", "بي"), + (0xFC0B, "M", "تج"), + (0xFC0C, "M", "تح"), + (0xFC0D, "M", "تخ"), + (0xFC0E, "M", "تم"), + (0xFC0F, "M", "تى"), + (0xFC10, "M", "تي"), + (0xFC11, "M", "ثج"), + (0xFC12, "M", "ثم"), + (0xFC13, "M", "ثى"), + (0xFC14, "M", "ثي"), + (0xFC15, "M", "جح"), + (0xFC16, "M", "جم"), + (0xFC17, "M", "حج"), + (0xFC18, "M", "حم"), + (0xFC19, "M", "خج"), + (0xFC1A, "M", "خح"), + (0xFC1B, "M", "خم"), + (0xFC1C, "M", "سج"), + (0xFC1D, "M", "سح"), + (0xFC1E, "M", "سخ"), + (0xFC1F, "M", "سم"), + (0xFC20, "M", "صح"), + (0xFC21, "M", "صم"), + (0xFC22, "M", "ضج"), + (0xFC23, "M", "ضح"), + (0xFC24, "M", "ضخ"), + (0xFC25, "M", "ضم"), + (0xFC26, "M", "طح"), + (0xFC27, "M", "طم"), + (0xFC28, "M", "ظم"), + (0xFC29, "M", "عج"), + (0xFC2A, "M", "عم"), + (0xFC2B, "M", "غج"), + (0xFC2C, "M", "غم"), + (0xFC2D, "M", "فج"), + (0xFC2E, "M", "فح"), + (0xFC2F, "M", "فخ"), + (0xFC30, "M", "فم"), + (0xFC31, "M", "فى"), + (0xFC32, "M", "في"), + (0xFC33, "M", "قح"), + (0xFC34, "M", "قم"), + (0xFC35, "M", "قى"), + (0xFC36, "M", "قي"), + (0xFC37, "M", "كا"), + (0xFC38, "M", "كج"), + (0xFC39, "M", "كح"), + (0xFC3A, "M", "كخ"), + (0xFC3B, "M", "كل"), + (0xFC3C, "M", "كم"), + (0xFC3D, "M", "كى"), + (0xFC3E, "M", "كي"), + (0xFC3F, "M", "لج"), + (0xFC40, "M", "لح"), + (0xFC41, "M", "لخ"), + (0xFC42, "M", "لم"), + (0xFC43, "M", "لى"), + (0xFC44, "M", "لي"), + (0xFC45, "M", "مج"), + (0xFC46, "M", "مح"), + (0xFC47, "M", "مخ"), + (0xFC48, "M", "مم"), + (0xFC49, "M", "مى"), + (0xFC4A, "M", "مي"), + (0xFC4B, "M", "نج"), + (0xFC4C, "M", "نح"), + (0xFC4D, "M", "نخ"), + (0xFC4E, "M", "نم"), + (0xFC4F, "M", "نى"), + (0xFC50, "M", "ني"), + (0xFC51, "M", "هج"), + (0xFC52, "M", "هم"), + (0xFC53, "M", "هى"), + (0xFC54, "M", "هي"), + (0xFC55, "M", "يج"), + (0xFC56, "M", "يح"), + (0xFC57, "M", "يخ"), + (0xFC58, "M", "يم"), + (0xFC59, "M", "يى"), + (0xFC5A, "M", "يي"), + ] + + +def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFC5B, "M", "ذٰ"), + (0xFC5C, "M", "رٰ"), + (0xFC5D, "M", "ىٰ"), + (0xFC5E, "3", " ٌّ"), + (0xFC5F, "3", " ٍّ"), + (0xFC60, "3", " َّ"), + (0xFC61, "3", " ُّ"), + (0xFC62, "3", " ِّ"), + (0xFC63, "3", " ّٰ"), + (0xFC64, "M", "ئر"), + (0xFC65, "M", "ئز"), + (0xFC66, "M", "ئم"), + (0xFC67, "M", "ئن"), + (0xFC68, "M", "ئى"), + (0xFC69, "M", "ئي"), + (0xFC6A, "M", "بر"), + (0xFC6B, "M", "بز"), + (0xFC6C, "M", "بم"), + (0xFC6D, "M", "بن"), + (0xFC6E, "M", "بى"), + (0xFC6F, "M", "بي"), + (0xFC70, "M", "تر"), + (0xFC71, "M", "تز"), + (0xFC72, "M", "تم"), + (0xFC73, "M", "تن"), + (0xFC74, "M", "تى"), + (0xFC75, "M", "تي"), + (0xFC76, "M", "ثر"), + (0xFC77, "M", "ثز"), + (0xFC78, "M", "ثم"), + (0xFC79, "M", "ثن"), + (0xFC7A, "M", "ثى"), + (0xFC7B, "M", "ثي"), + (0xFC7C, "M", "فى"), + (0xFC7D, "M", "في"), + (0xFC7E, "M", "قى"), + (0xFC7F, "M", "قي"), + (0xFC80, "M", "كا"), + (0xFC81, "M", "كل"), + (0xFC82, "M", "كم"), + (0xFC83, "M", "كى"), + (0xFC84, "M", "كي"), + (0xFC85, "M", "لم"), + (0xFC86, "M", "لى"), + (0xFC87, "M", "لي"), + (0xFC88, "M", "ما"), + (0xFC89, "M", "مم"), + (0xFC8A, "M", "نر"), + (0xFC8B, "M", "نز"), + (0xFC8C, "M", "نم"), + (0xFC8D, "M", "نن"), + (0xFC8E, "M", "نى"), + (0xFC8F, "M", "ني"), + (0xFC90, "M", "ىٰ"), + (0xFC91, "M", "ير"), + (0xFC92, "M", "يز"), + (0xFC93, "M", "يم"), + (0xFC94, "M", "ين"), + (0xFC95, "M", "يى"), + (0xFC96, "M", "يي"), + (0xFC97, "M", "ئج"), + (0xFC98, "M", "ئح"), + (0xFC99, "M", "ئخ"), + (0xFC9A, "M", "ئم"), + (0xFC9B, "M", "ئه"), + (0xFC9C, "M", "بج"), + (0xFC9D, "M", "بح"), + (0xFC9E, "M", "بخ"), + (0xFC9F, "M", "بم"), + (0xFCA0, "M", "به"), + (0xFCA1, "M", "تج"), + (0xFCA2, "M", "تح"), + (0xFCA3, "M", "تخ"), + (0xFCA4, "M", "تم"), + (0xFCA5, "M", "ته"), + (0xFCA6, "M", "ثم"), + (0xFCA7, "M", "جح"), + (0xFCA8, "M", "جم"), + (0xFCA9, "M", "حج"), + (0xFCAA, "M", "حم"), + (0xFCAB, "M", "خج"), + (0xFCAC, "M", "خم"), + (0xFCAD, "M", "سج"), + (0xFCAE, "M", "سح"), + (0xFCAF, "M", "سخ"), + (0xFCB0, "M", "سم"), + (0xFCB1, "M", "صح"), + (0xFCB2, "M", "صخ"), + (0xFCB3, "M", "صم"), + (0xFCB4, "M", "ضج"), + (0xFCB5, "M", "ضح"), + (0xFCB6, "M", "ضخ"), + (0xFCB7, "M", "ضم"), + (0xFCB8, "M", "طح"), + (0xFCB9, "M", "ظم"), + (0xFCBA, "M", "عج"), + (0xFCBB, "M", "عم"), + (0xFCBC, "M", "غج"), + (0xFCBD, "M", "غم"), + (0xFCBE, "M", "فج"), + ] + + +def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFCBF, "M", "فح"), + (0xFCC0, "M", "فخ"), + (0xFCC1, "M", "فم"), + (0xFCC2, "M", "قح"), + (0xFCC3, "M", "قم"), + (0xFCC4, "M", "كج"), + (0xFCC5, "M", "كح"), + (0xFCC6, "M", "كخ"), + (0xFCC7, "M", "كل"), + (0xFCC8, "M", "كم"), + (0xFCC9, "M", "لج"), + (0xFCCA, "M", "لح"), + (0xFCCB, "M", "لخ"), + (0xFCCC, "M", "لم"), + (0xFCCD, "M", "له"), + (0xFCCE, "M", "مج"), + (0xFCCF, "M", "مح"), + (0xFCD0, "M", "مخ"), + (0xFCD1, "M", "مم"), + (0xFCD2, "M", "نج"), + (0xFCD3, "M", "نح"), + (0xFCD4, "M", "نخ"), + (0xFCD5, "M", "نم"), + (0xFCD6, "M", "نه"), + (0xFCD7, "M", "هج"), + (0xFCD8, "M", "هم"), + (0xFCD9, "M", "هٰ"), + (0xFCDA, "M", "يج"), + (0xFCDB, "M", "يح"), + (0xFCDC, "M", "يخ"), + (0xFCDD, "M", "يم"), + (0xFCDE, "M", "يه"), + (0xFCDF, "M", "ئم"), + (0xFCE0, "M", "ئه"), + (0xFCE1, "M", "بم"), + (0xFCE2, "M", "به"), + (0xFCE3, "M", "تم"), + (0xFCE4, "M", "ته"), + (0xFCE5, "M", "ثم"), + (0xFCE6, "M", "ثه"), + (0xFCE7, "M", "سم"), + (0xFCE8, "M", "سه"), + (0xFCE9, "M", "شم"), + (0xFCEA, "M", "شه"), + (0xFCEB, "M", "كل"), + (0xFCEC, "M", "كم"), + (0xFCED, "M", "لم"), + (0xFCEE, "M", "نم"), + (0xFCEF, "M", "نه"), + (0xFCF0, "M", "يم"), + (0xFCF1, "M", "يه"), + (0xFCF2, "M", "ـَّ"), + (0xFCF3, "M", "ـُّ"), + (0xFCF4, "M", "ـِّ"), + (0xFCF5, "M", "طى"), + (0xFCF6, "M", "طي"), + (0xFCF7, "M", "عى"), + (0xFCF8, "M", "عي"), + (0xFCF9, "M", "غى"), + (0xFCFA, "M", "غي"), + (0xFCFB, "M", "سى"), + (0xFCFC, "M", "سي"), + (0xFCFD, "M", "شى"), + (0xFCFE, "M", "شي"), + (0xFCFF, "M", "حى"), + (0xFD00, "M", "حي"), + (0xFD01, "M", "جى"), + (0xFD02, "M", "جي"), + (0xFD03, "M", "خى"), + (0xFD04, "M", "خي"), + (0xFD05, "M", "صى"), + (0xFD06, "M", "صي"), + (0xFD07, "M", "ضى"), + (0xFD08, "M", "ضي"), + (0xFD09, "M", "شج"), + (0xFD0A, "M", "شح"), + (0xFD0B, "M", "شخ"), + (0xFD0C, "M", "شم"), + (0xFD0D, "M", "شر"), + (0xFD0E, "M", "سر"), + (0xFD0F, "M", "صر"), + (0xFD10, "M", "ضر"), + (0xFD11, "M", "طى"), + (0xFD12, "M", "طي"), + (0xFD13, "M", "عى"), + (0xFD14, "M", "عي"), + (0xFD15, "M", "غى"), + (0xFD16, "M", "غي"), + (0xFD17, "M", "سى"), + (0xFD18, "M", "سي"), + (0xFD19, "M", "شى"), + (0xFD1A, "M", "شي"), + (0xFD1B, "M", "حى"), + (0xFD1C, "M", "حي"), + (0xFD1D, "M", "جى"), + (0xFD1E, "M", "جي"), + (0xFD1F, "M", "خى"), + (0xFD20, "M", "خي"), + (0xFD21, "M", "صى"), + (0xFD22, "M", "صي"), + ] + + +def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFD23, "M", "ضى"), + (0xFD24, "M", "ضي"), + (0xFD25, "M", "شج"), + (0xFD26, "M", "شح"), + (0xFD27, "M", "شخ"), + (0xFD28, "M", "شم"), + (0xFD29, "M", "شر"), + (0xFD2A, "M", "سر"), + (0xFD2B, "M", "صر"), + (0xFD2C, "M", "ضر"), + (0xFD2D, "M", "شج"), + (0xFD2E, "M", "شح"), + (0xFD2F, "M", "شخ"), + (0xFD30, "M", "شم"), + (0xFD31, "M", "سه"), + (0xFD32, "M", "شه"), + (0xFD33, "M", "طم"), + (0xFD34, "M", "سج"), + (0xFD35, "M", "سح"), + (0xFD36, "M", "سخ"), + (0xFD37, "M", "شج"), + (0xFD38, "M", "شح"), + (0xFD39, "M", "شخ"), + (0xFD3A, "M", "طم"), + (0xFD3B, "M", "ظم"), + (0xFD3C, "M", "اً"), + (0xFD3E, "V"), + (0xFD50, "M", "تجم"), + (0xFD51, "M", "تحج"), + (0xFD53, "M", "تحم"), + (0xFD54, "M", "تخم"), + (0xFD55, "M", "تمج"), + (0xFD56, "M", "تمح"), + (0xFD57, "M", "تمخ"), + (0xFD58, "M", "جمح"), + (0xFD5A, "M", "حمي"), + (0xFD5B, "M", "حمى"), + (0xFD5C, "M", "سحج"), + (0xFD5D, "M", "سجح"), + (0xFD5E, "M", "سجى"), + (0xFD5F, "M", "سمح"), + (0xFD61, "M", "سمج"), + (0xFD62, "M", "سمم"), + (0xFD64, "M", "صحح"), + (0xFD66, "M", "صمم"), + (0xFD67, "M", "شحم"), + (0xFD69, "M", "شجي"), + (0xFD6A, "M", "شمخ"), + (0xFD6C, "M", "شمم"), + (0xFD6E, "M", "ضحى"), + (0xFD6F, "M", "ضخم"), + (0xFD71, "M", "طمح"), + (0xFD73, "M", "طمم"), + (0xFD74, "M", "طمي"), + (0xFD75, "M", "عجم"), + (0xFD76, "M", "عمم"), + (0xFD78, "M", "عمى"), + (0xFD79, "M", "غمم"), + (0xFD7A, "M", "غمي"), + (0xFD7B, "M", "غمى"), + (0xFD7C, "M", "فخم"), + (0xFD7E, "M", "قمح"), + (0xFD7F, "M", "قمم"), + (0xFD80, "M", "لحم"), + (0xFD81, "M", "لحي"), + (0xFD82, "M", "لحى"), + (0xFD83, "M", "لجج"), + (0xFD85, "M", "لخم"), + (0xFD87, "M", "لمح"), + (0xFD89, "M", "محج"), + (0xFD8A, "M", "محم"), + (0xFD8B, "M", "محي"), + (0xFD8C, "M", "مجح"), + (0xFD8D, "M", "مجم"), + (0xFD8E, "M", "مخج"), + (0xFD8F, "M", "مخم"), + (0xFD90, "X"), + (0xFD92, "M", "مجخ"), + (0xFD93, "M", "همج"), + (0xFD94, "M", "همم"), + (0xFD95, "M", "نحم"), + (0xFD96, "M", "نحى"), + (0xFD97, "M", "نجم"), + (0xFD99, "M", "نجى"), + (0xFD9A, "M", "نمي"), + (0xFD9B, "M", "نمى"), + (0xFD9C, "M", "يمم"), + (0xFD9E, "M", "بخي"), + (0xFD9F, "M", "تجي"), + (0xFDA0, "M", "تجى"), + (0xFDA1, "M", "تخي"), + (0xFDA2, "M", "تخى"), + (0xFDA3, "M", "تمي"), + (0xFDA4, "M", "تمى"), + (0xFDA5, "M", "جمي"), + (0xFDA6, "M", "جحى"), + (0xFDA7, "M", "جمى"), + (0xFDA8, "M", "سخى"), + (0xFDA9, "M", "صحي"), + (0xFDAA, "M", "شحي"), + ] + + +def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFDAB, "M", "ضحي"), + (0xFDAC, "M", "لجي"), + (0xFDAD, "M", "لمي"), + (0xFDAE, "M", "يحي"), + (0xFDAF, "M", "يجي"), + (0xFDB0, "M", "يمي"), + (0xFDB1, "M", "ممي"), + (0xFDB2, "M", "قمي"), + (0xFDB3, "M", "نحي"), + (0xFDB4, "M", "قمح"), + (0xFDB5, "M", "لحم"), + (0xFDB6, "M", "عمي"), + (0xFDB7, "M", "كمي"), + (0xFDB8, "M", "نجح"), + (0xFDB9, "M", "مخي"), + (0xFDBA, "M", "لجم"), + (0xFDBB, "M", "كمم"), + (0xFDBC, "M", "لجم"), + (0xFDBD, "M", "نجح"), + (0xFDBE, "M", "جحي"), + (0xFDBF, "M", "حجي"), + (0xFDC0, "M", "مجي"), + (0xFDC1, "M", "فمي"), + (0xFDC2, "M", "بحي"), + (0xFDC3, "M", "كمم"), + (0xFDC4, "M", "عجم"), + (0xFDC5, "M", "صمم"), + (0xFDC6, "M", "سخي"), + (0xFDC7, "M", "نجي"), + (0xFDC8, "X"), + (0xFDCF, "V"), + (0xFDD0, "X"), + (0xFDF0, "M", "صلے"), + (0xFDF1, "M", "قلے"), + (0xFDF2, "M", "الله"), + (0xFDF3, "M", "اكبر"), + (0xFDF4, "M", "محمد"), + (0xFDF5, "M", "صلعم"), + (0xFDF6, "M", "رسول"), + (0xFDF7, "M", "عليه"), + (0xFDF8, "M", "وسلم"), + (0xFDF9, "M", "صلى"), + (0xFDFA, "3", "صلى الله عليه وسلم"), + (0xFDFB, "3", "جل جلاله"), + (0xFDFC, "M", "ریال"), + (0xFDFD, "V"), + (0xFE00, "I"), + (0xFE10, "3", ","), + (0xFE11, "M", "、"), + (0xFE12, "X"), + (0xFE13, "3", ":"), + (0xFE14, "3", ";"), + (0xFE15, "3", "!"), + (0xFE16, "3", "?"), + (0xFE17, "M", "〖"), + (0xFE18, "M", "〗"), + (0xFE19, "X"), + (0xFE20, "V"), + (0xFE30, "X"), + (0xFE31, "M", "—"), + (0xFE32, "M", "–"), + (0xFE33, "3", "_"), + (0xFE35, "3", "("), + (0xFE36, "3", ")"), + (0xFE37, "3", "{"), + (0xFE38, "3", "}"), + (0xFE39, "M", "〔"), + (0xFE3A, "M", "〕"), + (0xFE3B, "M", "【"), + (0xFE3C, "M", "】"), + (0xFE3D, "M", "《"), + (0xFE3E, "M", "》"), + (0xFE3F, "M", "〈"), + (0xFE40, "M", "〉"), + (0xFE41, "M", "「"), + (0xFE42, "M", "」"), + (0xFE43, "M", "『"), + (0xFE44, "M", "』"), + (0xFE45, "V"), + (0xFE47, "3", "["), + (0xFE48, "3", "]"), + (0xFE49, "3", " ̅"), + (0xFE4D, "3", "_"), + (0xFE50, "3", ","), + (0xFE51, "M", "、"), + (0xFE52, "X"), + (0xFE54, "3", ";"), + (0xFE55, "3", ":"), + (0xFE56, "3", "?"), + (0xFE57, "3", "!"), + (0xFE58, "M", "—"), + (0xFE59, "3", "("), + (0xFE5A, "3", ")"), + (0xFE5B, "3", "{"), + (0xFE5C, "3", "}"), + (0xFE5D, "M", "〔"), + (0xFE5E, "M", "〕"), + (0xFE5F, "3", "#"), + (0xFE60, "3", "&"), + (0xFE61, "3", "*"), + ] + + +def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFE62, "3", "+"), + (0xFE63, "M", "-"), + (0xFE64, "3", "<"), + (0xFE65, "3", ">"), + (0xFE66, "3", "="), + (0xFE67, "X"), + (0xFE68, "3", "\\"), + (0xFE69, "3", "$"), + (0xFE6A, "3", "%"), + (0xFE6B, "3", "@"), + (0xFE6C, "X"), + (0xFE70, "3", " ً"), + (0xFE71, "M", "ـً"), + (0xFE72, "3", " ٌ"), + (0xFE73, "V"), + (0xFE74, "3", " ٍ"), + (0xFE75, "X"), + (0xFE76, "3", " َ"), + (0xFE77, "M", "ـَ"), + (0xFE78, "3", " ُ"), + (0xFE79, "M", "ـُ"), + (0xFE7A, "3", " ِ"), + (0xFE7B, "M", "ـِ"), + (0xFE7C, "3", " ّ"), + (0xFE7D, "M", "ـّ"), + (0xFE7E, "3", " ْ"), + (0xFE7F, "M", "ـْ"), + (0xFE80, "M", "ء"), + (0xFE81, "M", "آ"), + (0xFE83, "M", "أ"), + (0xFE85, "M", "ؤ"), + (0xFE87, "M", "إ"), + (0xFE89, "M", "ئ"), + (0xFE8D, "M", "ا"), + (0xFE8F, "M", "ب"), + (0xFE93, "M", "ة"), + (0xFE95, "M", "ت"), + (0xFE99, "M", "ث"), + (0xFE9D, "M", "ج"), + (0xFEA1, "M", "ح"), + (0xFEA5, "M", "خ"), + (0xFEA9, "M", "د"), + (0xFEAB, "M", "ذ"), + (0xFEAD, "M", "ر"), + (0xFEAF, "M", "ز"), + (0xFEB1, "M", "س"), + (0xFEB5, "M", "ش"), + (0xFEB9, "M", "ص"), + (0xFEBD, "M", "ض"), + (0xFEC1, "M", "ط"), + (0xFEC5, "M", "ظ"), + (0xFEC9, "M", "ع"), + (0xFECD, "M", "غ"), + (0xFED1, "M", "ف"), + (0xFED5, "M", "ق"), + (0xFED9, "M", "ك"), + (0xFEDD, "M", "ل"), + (0xFEE1, "M", "م"), + (0xFEE5, "M", "ن"), + (0xFEE9, "M", "ه"), + (0xFEED, "M", "و"), + (0xFEEF, "M", "ى"), + (0xFEF1, "M", "ي"), + (0xFEF5, "M", "لآ"), + (0xFEF7, "M", "لأ"), + (0xFEF9, "M", "لإ"), + (0xFEFB, "M", "لا"), + (0xFEFD, "X"), + (0xFEFF, "I"), + (0xFF00, "X"), + (0xFF01, "3", "!"), + (0xFF02, "3", '"'), + (0xFF03, "3", "#"), + (0xFF04, "3", "$"), + (0xFF05, "3", "%"), + (0xFF06, "3", "&"), + (0xFF07, "3", "'"), + (0xFF08, "3", "("), + (0xFF09, "3", ")"), + (0xFF0A, "3", "*"), + (0xFF0B, "3", "+"), + (0xFF0C, "3", ","), + (0xFF0D, "M", "-"), + (0xFF0E, "M", "."), + (0xFF0F, "3", "/"), + (0xFF10, "M", "0"), + (0xFF11, "M", "1"), + (0xFF12, "M", "2"), + (0xFF13, "M", "3"), + (0xFF14, "M", "4"), + (0xFF15, "M", "5"), + (0xFF16, "M", "6"), + (0xFF17, "M", "7"), + (0xFF18, "M", "8"), + (0xFF19, "M", "9"), + (0xFF1A, "3", ":"), + (0xFF1B, "3", ";"), + (0xFF1C, "3", "<"), + (0xFF1D, "3", "="), + (0xFF1E, "3", ">"), + ] + + +def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFF1F, "3", "?"), + (0xFF20, "3", "@"), + (0xFF21, "M", "a"), + (0xFF22, "M", "b"), + (0xFF23, "M", "c"), + (0xFF24, "M", "d"), + (0xFF25, "M", "e"), + (0xFF26, "M", "f"), + (0xFF27, "M", "g"), + (0xFF28, "M", "h"), + (0xFF29, "M", "i"), + (0xFF2A, "M", "j"), + (0xFF2B, "M", "k"), + (0xFF2C, "M", "l"), + (0xFF2D, "M", "m"), + (0xFF2E, "M", "n"), + (0xFF2F, "M", "o"), + (0xFF30, "M", "p"), + (0xFF31, "M", "q"), + (0xFF32, "M", "r"), + (0xFF33, "M", "s"), + (0xFF34, "M", "t"), + (0xFF35, "M", "u"), + (0xFF36, "M", "v"), + (0xFF37, "M", "w"), + (0xFF38, "M", "x"), + (0xFF39, "M", "y"), + (0xFF3A, "M", "z"), + (0xFF3B, "3", "["), + (0xFF3C, "3", "\\"), + (0xFF3D, "3", "]"), + (0xFF3E, "3", "^"), + (0xFF3F, "3", "_"), + (0xFF40, "3", "`"), + (0xFF41, "M", "a"), + (0xFF42, "M", "b"), + (0xFF43, "M", "c"), + (0xFF44, "M", "d"), + (0xFF45, "M", "e"), + (0xFF46, "M", "f"), + (0xFF47, "M", "g"), + (0xFF48, "M", "h"), + (0xFF49, "M", "i"), + (0xFF4A, "M", "j"), + (0xFF4B, "M", "k"), + (0xFF4C, "M", "l"), + (0xFF4D, "M", "m"), + (0xFF4E, "M", "n"), + (0xFF4F, "M", "o"), + (0xFF50, "M", "p"), + (0xFF51, "M", "q"), + (0xFF52, "M", "r"), + (0xFF53, "M", "s"), + (0xFF54, "M", "t"), + (0xFF55, "M", "u"), + (0xFF56, "M", "v"), + (0xFF57, "M", "w"), + (0xFF58, "M", "x"), + (0xFF59, "M", "y"), + (0xFF5A, "M", "z"), + (0xFF5B, "3", "{"), + (0xFF5C, "3", "|"), + (0xFF5D, "3", "}"), + (0xFF5E, "3", "~"), + (0xFF5F, "M", "⦅"), + (0xFF60, "M", "⦆"), + (0xFF61, "M", "."), + (0xFF62, "M", "「"), + (0xFF63, "M", "」"), + (0xFF64, "M", "、"), + (0xFF65, "M", "・"), + (0xFF66, "M", "ヲ"), + (0xFF67, "M", "ァ"), + (0xFF68, "M", "ィ"), + (0xFF69, "M", "ゥ"), + (0xFF6A, "M", "ェ"), + (0xFF6B, "M", "ォ"), + (0xFF6C, "M", "ャ"), + (0xFF6D, "M", "ュ"), + (0xFF6E, "M", "ョ"), + (0xFF6F, "M", "ッ"), + (0xFF70, "M", "ー"), + (0xFF71, "M", "ア"), + (0xFF72, "M", "イ"), + (0xFF73, "M", "ウ"), + (0xFF74, "M", "エ"), + (0xFF75, "M", "オ"), + (0xFF76, "M", "カ"), + (0xFF77, "M", "キ"), + (0xFF78, "M", "ク"), + (0xFF79, "M", "ケ"), + (0xFF7A, "M", "コ"), + (0xFF7B, "M", "サ"), + (0xFF7C, "M", "シ"), + (0xFF7D, "M", "ス"), + (0xFF7E, "M", "セ"), + (0xFF7F, "M", "ソ"), + (0xFF80, "M", "タ"), + (0xFF81, "M", "チ"), + (0xFF82, "M", "ツ"), + ] + + +def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFF83, "M", "テ"), + (0xFF84, "M", "ト"), + (0xFF85, "M", "ナ"), + (0xFF86, "M", "ニ"), + (0xFF87, "M", "ヌ"), + (0xFF88, "M", "ネ"), + (0xFF89, "M", "ノ"), + (0xFF8A, "M", "ハ"), + (0xFF8B, "M", "ヒ"), + (0xFF8C, "M", "フ"), + (0xFF8D, "M", "ヘ"), + (0xFF8E, "M", "ホ"), + (0xFF8F, "M", "マ"), + (0xFF90, "M", "ミ"), + (0xFF91, "M", "ム"), + (0xFF92, "M", "メ"), + (0xFF93, "M", "モ"), + (0xFF94, "M", "ヤ"), + (0xFF95, "M", "ユ"), + (0xFF96, "M", "ヨ"), + (0xFF97, "M", "ラ"), + (0xFF98, "M", "リ"), + (0xFF99, "M", "ル"), + (0xFF9A, "M", "レ"), + (0xFF9B, "M", "ロ"), + (0xFF9C, "M", "ワ"), + (0xFF9D, "M", "ン"), + (0xFF9E, "M", "゙"), + (0xFF9F, "M", "゚"), + (0xFFA0, "X"), + (0xFFA1, "M", "ᄀ"), + (0xFFA2, "M", "ᄁ"), + (0xFFA3, "M", "ᆪ"), + (0xFFA4, "M", "ᄂ"), + (0xFFA5, "M", "ᆬ"), + (0xFFA6, "M", "ᆭ"), + (0xFFA7, "M", "ᄃ"), + (0xFFA8, "M", "ᄄ"), + (0xFFA9, "M", "ᄅ"), + (0xFFAA, "M", "ᆰ"), + (0xFFAB, "M", "ᆱ"), + (0xFFAC, "M", "ᆲ"), + (0xFFAD, "M", "ᆳ"), + (0xFFAE, "M", "ᆴ"), + (0xFFAF, "M", "ᆵ"), + (0xFFB0, "M", "ᄚ"), + (0xFFB1, "M", "ᄆ"), + (0xFFB2, "M", "ᄇ"), + (0xFFB3, "M", "ᄈ"), + (0xFFB4, "M", "ᄡ"), + (0xFFB5, "M", "ᄉ"), + (0xFFB6, "M", "ᄊ"), + (0xFFB7, "M", "ᄋ"), + (0xFFB8, "M", "ᄌ"), + (0xFFB9, "M", "ᄍ"), + (0xFFBA, "M", "ᄎ"), + (0xFFBB, "M", "ᄏ"), + (0xFFBC, "M", "ᄐ"), + (0xFFBD, "M", "ᄑ"), + (0xFFBE, "M", "ᄒ"), + (0xFFBF, "X"), + (0xFFC2, "M", "ᅡ"), + (0xFFC3, "M", "ᅢ"), + (0xFFC4, "M", "ᅣ"), + (0xFFC5, "M", "ᅤ"), + (0xFFC6, "M", "ᅥ"), + (0xFFC7, "M", "ᅦ"), + (0xFFC8, "X"), + (0xFFCA, "M", "ᅧ"), + (0xFFCB, "M", "ᅨ"), + (0xFFCC, "M", "ᅩ"), + (0xFFCD, "M", "ᅪ"), + (0xFFCE, "M", "ᅫ"), + (0xFFCF, "M", "ᅬ"), + (0xFFD0, "X"), + (0xFFD2, "M", "ᅭ"), + (0xFFD3, "M", "ᅮ"), + (0xFFD4, "M", "ᅯ"), + (0xFFD5, "M", "ᅰ"), + (0xFFD6, "M", "ᅱ"), + (0xFFD7, "M", "ᅲ"), + (0xFFD8, "X"), + (0xFFDA, "M", "ᅳ"), + (0xFFDB, "M", "ᅴ"), + (0xFFDC, "M", "ᅵ"), + (0xFFDD, "X"), + (0xFFE0, "M", "¢"), + (0xFFE1, "M", "£"), + (0xFFE2, "M", "¬"), + (0xFFE3, "3", " ̄"), + (0xFFE4, "M", "¦"), + (0xFFE5, "M", "¥"), + (0xFFE6, "M", "₩"), + (0xFFE7, "X"), + (0xFFE8, "M", "│"), + (0xFFE9, "M", "←"), + (0xFFEA, "M", "↑"), + (0xFFEB, "M", "→"), + (0xFFEC, "M", "↓"), + (0xFFED, "M", "■"), + ] + + +def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFFEE, "M", "○"), + (0xFFEF, "X"), + (0x10000, "V"), + (0x1000C, "X"), + (0x1000D, "V"), + (0x10027, "X"), + (0x10028, "V"), + (0x1003B, "X"), + (0x1003C, "V"), + (0x1003E, "X"), + (0x1003F, "V"), + (0x1004E, "X"), + (0x10050, "V"), + (0x1005E, "X"), + (0x10080, "V"), + (0x100FB, "X"), + (0x10100, "V"), + (0x10103, "X"), + (0x10107, "V"), + (0x10134, "X"), + (0x10137, "V"), + (0x1018F, "X"), + (0x10190, "V"), + (0x1019D, "X"), + (0x101A0, "V"), + (0x101A1, "X"), + (0x101D0, "V"), + (0x101FE, "X"), + (0x10280, "V"), + (0x1029D, "X"), + (0x102A0, "V"), + (0x102D1, "X"), + (0x102E0, "V"), + (0x102FC, "X"), + (0x10300, "V"), + (0x10324, "X"), + (0x1032D, "V"), + (0x1034B, "X"), + (0x10350, "V"), + (0x1037B, "X"), + (0x10380, "V"), + (0x1039E, "X"), + (0x1039F, "V"), + (0x103C4, "X"), + (0x103C8, "V"), + (0x103D6, "X"), + (0x10400, "M", "𐐨"), + (0x10401, "M", "𐐩"), + (0x10402, "M", "𐐪"), + (0x10403, "M", "𐐫"), + (0x10404, "M", "𐐬"), + (0x10405, "M", "𐐭"), + (0x10406, "M", "𐐮"), + (0x10407, "M", "𐐯"), + (0x10408, "M", "𐐰"), + (0x10409, "M", "𐐱"), + (0x1040A, "M", "𐐲"), + (0x1040B, "M", "𐐳"), + (0x1040C, "M", "𐐴"), + (0x1040D, "M", "𐐵"), + (0x1040E, "M", "𐐶"), + (0x1040F, "M", "𐐷"), + (0x10410, "M", "𐐸"), + (0x10411, "M", "𐐹"), + (0x10412, "M", "𐐺"), + (0x10413, "M", "𐐻"), + (0x10414, "M", "𐐼"), + (0x10415, "M", "𐐽"), + (0x10416, "M", "𐐾"), + (0x10417, "M", "𐐿"), + (0x10418, "M", "𐑀"), + (0x10419, "M", "𐑁"), + (0x1041A, "M", "𐑂"), + (0x1041B, "M", "𐑃"), + (0x1041C, "M", "𐑄"), + (0x1041D, "M", "𐑅"), + (0x1041E, "M", "𐑆"), + (0x1041F, "M", "𐑇"), + (0x10420, "M", "𐑈"), + (0x10421, "M", "𐑉"), + (0x10422, "M", "𐑊"), + (0x10423, "M", "𐑋"), + (0x10424, "M", "𐑌"), + (0x10425, "M", "𐑍"), + (0x10426, "M", "𐑎"), + (0x10427, "M", "𐑏"), + (0x10428, "V"), + (0x1049E, "X"), + (0x104A0, "V"), + (0x104AA, "X"), + (0x104B0, "M", "𐓘"), + (0x104B1, "M", "𐓙"), + (0x104B2, "M", "𐓚"), + (0x104B3, "M", "𐓛"), + (0x104B4, "M", "𐓜"), + (0x104B5, "M", "𐓝"), + (0x104B6, "M", "𐓞"), + (0x104B7, "M", "𐓟"), + (0x104B8, "M", "𐓠"), + (0x104B9, "M", "𐓡"), + ] + + +def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x104BA, "M", "𐓢"), + (0x104BB, "M", "𐓣"), + (0x104BC, "M", "𐓤"), + (0x104BD, "M", "𐓥"), + (0x104BE, "M", "𐓦"), + (0x104BF, "M", "𐓧"), + (0x104C0, "M", "𐓨"), + (0x104C1, "M", "𐓩"), + (0x104C2, "M", "𐓪"), + (0x104C3, "M", "𐓫"), + (0x104C4, "M", "𐓬"), + (0x104C5, "M", "𐓭"), + (0x104C6, "M", "𐓮"), + (0x104C7, "M", "𐓯"), + (0x104C8, "M", "𐓰"), + (0x104C9, "M", "𐓱"), + (0x104CA, "M", "𐓲"), + (0x104CB, "M", "𐓳"), + (0x104CC, "M", "𐓴"), + (0x104CD, "M", "𐓵"), + (0x104CE, "M", "𐓶"), + (0x104CF, "M", "𐓷"), + (0x104D0, "M", "𐓸"), + (0x104D1, "M", "𐓹"), + (0x104D2, "M", "𐓺"), + (0x104D3, "M", "𐓻"), + (0x104D4, "X"), + (0x104D8, "V"), + (0x104FC, "X"), + (0x10500, "V"), + (0x10528, "X"), + (0x10530, "V"), + (0x10564, "X"), + (0x1056F, "V"), + (0x10570, "M", "𐖗"), + (0x10571, "M", "𐖘"), + (0x10572, "M", "𐖙"), + (0x10573, "M", "𐖚"), + (0x10574, "M", "𐖛"), + (0x10575, "M", "𐖜"), + (0x10576, "M", "𐖝"), + (0x10577, "M", "𐖞"), + (0x10578, "M", "𐖟"), + (0x10579, "M", "𐖠"), + (0x1057A, "M", "𐖡"), + (0x1057B, "X"), + (0x1057C, "M", "𐖣"), + (0x1057D, "M", "𐖤"), + (0x1057E, "M", "𐖥"), + (0x1057F, "M", "𐖦"), + (0x10580, "M", "𐖧"), + (0x10581, "M", "𐖨"), + (0x10582, "M", "𐖩"), + (0x10583, "M", "𐖪"), + (0x10584, "M", "𐖫"), + (0x10585, "M", "𐖬"), + (0x10586, "M", "𐖭"), + (0x10587, "M", "𐖮"), + (0x10588, "M", "𐖯"), + (0x10589, "M", "𐖰"), + (0x1058A, "M", "𐖱"), + (0x1058B, "X"), + (0x1058C, "M", "𐖳"), + (0x1058D, "M", "𐖴"), + (0x1058E, "M", "𐖵"), + (0x1058F, "M", "𐖶"), + (0x10590, "M", "𐖷"), + (0x10591, "M", "𐖸"), + (0x10592, "M", "𐖹"), + (0x10593, "X"), + (0x10594, "M", "𐖻"), + (0x10595, "M", "𐖼"), + (0x10596, "X"), + (0x10597, "V"), + (0x105A2, "X"), + (0x105A3, "V"), + (0x105B2, "X"), + (0x105B3, "V"), + (0x105BA, "X"), + (0x105BB, "V"), + (0x105BD, "X"), + (0x10600, "V"), + (0x10737, "X"), + (0x10740, "V"), + (0x10756, "X"), + (0x10760, "V"), + (0x10768, "X"), + (0x10780, "V"), + (0x10781, "M", "ː"), + (0x10782, "M", "ˑ"), + (0x10783, "M", "æ"), + (0x10784, "M", "ʙ"), + (0x10785, "M", "ɓ"), + (0x10786, "X"), + (0x10787, "M", "ʣ"), + (0x10788, "M", "ꭦ"), + (0x10789, "M", "ʥ"), + (0x1078A, "M", "ʤ"), + (0x1078B, "M", "ɖ"), + (0x1078C, "M", "ɗ"), + ] + + +def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1078D, "M", "ᶑ"), + (0x1078E, "M", "ɘ"), + (0x1078F, "M", "ɞ"), + (0x10790, "M", "ʩ"), + (0x10791, "M", "ɤ"), + (0x10792, "M", "ɢ"), + (0x10793, "M", "ɠ"), + (0x10794, "M", "ʛ"), + (0x10795, "M", "ħ"), + (0x10796, "M", "ʜ"), + (0x10797, "M", "ɧ"), + (0x10798, "M", "ʄ"), + (0x10799, "M", "ʪ"), + (0x1079A, "M", "ʫ"), + (0x1079B, "M", "ɬ"), + (0x1079C, "M", "𝼄"), + (0x1079D, "M", "ꞎ"), + (0x1079E, "M", "ɮ"), + (0x1079F, "M", "𝼅"), + (0x107A0, "M", "ʎ"), + (0x107A1, "M", "𝼆"), + (0x107A2, "M", "ø"), + (0x107A3, "M", "ɶ"), + (0x107A4, "M", "ɷ"), + (0x107A5, "M", "q"), + (0x107A6, "M", "ɺ"), + (0x107A7, "M", "𝼈"), + (0x107A8, "M", "ɽ"), + (0x107A9, "M", "ɾ"), + (0x107AA, "M", "ʀ"), + (0x107AB, "M", "ʨ"), + (0x107AC, "M", "ʦ"), + (0x107AD, "M", "ꭧ"), + (0x107AE, "M", "ʧ"), + (0x107AF, "M", "ʈ"), + (0x107B0, "M", "ⱱ"), + (0x107B1, "X"), + (0x107B2, "M", "ʏ"), + (0x107B3, "M", "ʡ"), + (0x107B4, "M", "ʢ"), + (0x107B5, "M", "ʘ"), + (0x107B6, "M", "ǀ"), + (0x107B7, "M", "ǁ"), + (0x107B8, "M", "ǂ"), + (0x107B9, "M", "𝼊"), + (0x107BA, "M", "𝼞"), + (0x107BB, "X"), + (0x10800, "V"), + (0x10806, "X"), + (0x10808, "V"), + (0x10809, "X"), + (0x1080A, "V"), + (0x10836, "X"), + (0x10837, "V"), + (0x10839, "X"), + (0x1083C, "V"), + (0x1083D, "X"), + (0x1083F, "V"), + (0x10856, "X"), + (0x10857, "V"), + (0x1089F, "X"), + (0x108A7, "V"), + (0x108B0, "X"), + (0x108E0, "V"), + (0x108F3, "X"), + (0x108F4, "V"), + (0x108F6, "X"), + (0x108FB, "V"), + (0x1091C, "X"), + (0x1091F, "V"), + (0x1093A, "X"), + (0x1093F, "V"), + (0x10940, "X"), + (0x10980, "V"), + (0x109B8, "X"), + (0x109BC, "V"), + (0x109D0, "X"), + (0x109D2, "V"), + (0x10A04, "X"), + (0x10A05, "V"), + (0x10A07, "X"), + (0x10A0C, "V"), + (0x10A14, "X"), + (0x10A15, "V"), + (0x10A18, "X"), + (0x10A19, "V"), + (0x10A36, "X"), + (0x10A38, "V"), + (0x10A3B, "X"), + (0x10A3F, "V"), + (0x10A49, "X"), + (0x10A50, "V"), + (0x10A59, "X"), + (0x10A60, "V"), + (0x10AA0, "X"), + (0x10AC0, "V"), + (0x10AE7, "X"), + (0x10AEB, "V"), + (0x10AF7, "X"), + (0x10B00, "V"), + ] + + +def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x10B36, "X"), + (0x10B39, "V"), + (0x10B56, "X"), + (0x10B58, "V"), + (0x10B73, "X"), + (0x10B78, "V"), + (0x10B92, "X"), + (0x10B99, "V"), + (0x10B9D, "X"), + (0x10BA9, "V"), + (0x10BB0, "X"), + (0x10C00, "V"), + (0x10C49, "X"), + (0x10C80, "M", "𐳀"), + (0x10C81, "M", "𐳁"), + (0x10C82, "M", "𐳂"), + (0x10C83, "M", "𐳃"), + (0x10C84, "M", "𐳄"), + (0x10C85, "M", "𐳅"), + (0x10C86, "M", "𐳆"), + (0x10C87, "M", "𐳇"), + (0x10C88, "M", "𐳈"), + (0x10C89, "M", "𐳉"), + (0x10C8A, "M", "𐳊"), + (0x10C8B, "M", "𐳋"), + (0x10C8C, "M", "𐳌"), + (0x10C8D, "M", "𐳍"), + (0x10C8E, "M", "𐳎"), + (0x10C8F, "M", "𐳏"), + (0x10C90, "M", "𐳐"), + (0x10C91, "M", "𐳑"), + (0x10C92, "M", "𐳒"), + (0x10C93, "M", "𐳓"), + (0x10C94, "M", "𐳔"), + (0x10C95, "M", "𐳕"), + (0x10C96, "M", "𐳖"), + (0x10C97, "M", "𐳗"), + (0x10C98, "M", "𐳘"), + (0x10C99, "M", "𐳙"), + (0x10C9A, "M", "𐳚"), + (0x10C9B, "M", "𐳛"), + (0x10C9C, "M", "𐳜"), + (0x10C9D, "M", "𐳝"), + (0x10C9E, "M", "𐳞"), + (0x10C9F, "M", "𐳟"), + (0x10CA0, "M", "𐳠"), + (0x10CA1, "M", "𐳡"), + (0x10CA2, "M", "𐳢"), + (0x10CA3, "M", "𐳣"), + (0x10CA4, "M", "𐳤"), + (0x10CA5, "M", "𐳥"), + (0x10CA6, "M", "𐳦"), + (0x10CA7, "M", "𐳧"), + (0x10CA8, "M", "𐳨"), + (0x10CA9, "M", "𐳩"), + (0x10CAA, "M", "𐳪"), + (0x10CAB, "M", "𐳫"), + (0x10CAC, "M", "𐳬"), + (0x10CAD, "M", "𐳭"), + (0x10CAE, "M", "𐳮"), + (0x10CAF, "M", "𐳯"), + (0x10CB0, "M", "𐳰"), + (0x10CB1, "M", "𐳱"), + (0x10CB2, "M", "𐳲"), + (0x10CB3, "X"), + (0x10CC0, "V"), + (0x10CF3, "X"), + (0x10CFA, "V"), + (0x10D28, "X"), + (0x10D30, "V"), + (0x10D3A, "X"), + (0x10E60, "V"), + (0x10E7F, "X"), + (0x10E80, "V"), + (0x10EAA, "X"), + (0x10EAB, "V"), + (0x10EAE, "X"), + (0x10EB0, "V"), + (0x10EB2, "X"), + (0x10EFD, "V"), + (0x10F28, "X"), + (0x10F30, "V"), + (0x10F5A, "X"), + (0x10F70, "V"), + (0x10F8A, "X"), + (0x10FB0, "V"), + (0x10FCC, "X"), + (0x10FE0, "V"), + (0x10FF7, "X"), + (0x11000, "V"), + (0x1104E, "X"), + (0x11052, "V"), + (0x11076, "X"), + (0x1107F, "V"), + (0x110BD, "X"), + (0x110BE, "V"), + (0x110C3, "X"), + (0x110D0, "V"), + (0x110E9, "X"), + (0x110F0, "V"), + ] + + +def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x110FA, "X"), + (0x11100, "V"), + (0x11135, "X"), + (0x11136, "V"), + (0x11148, "X"), + (0x11150, "V"), + (0x11177, "X"), + (0x11180, "V"), + (0x111E0, "X"), + (0x111E1, "V"), + (0x111F5, "X"), + (0x11200, "V"), + (0x11212, "X"), + (0x11213, "V"), + (0x11242, "X"), + (0x11280, "V"), + (0x11287, "X"), + (0x11288, "V"), + (0x11289, "X"), + (0x1128A, "V"), + (0x1128E, "X"), + (0x1128F, "V"), + (0x1129E, "X"), + (0x1129F, "V"), + (0x112AA, "X"), + (0x112B0, "V"), + (0x112EB, "X"), + (0x112F0, "V"), + (0x112FA, "X"), + (0x11300, "V"), + (0x11304, "X"), + (0x11305, "V"), + (0x1130D, "X"), + (0x1130F, "V"), + (0x11311, "X"), + (0x11313, "V"), + (0x11329, "X"), + (0x1132A, "V"), + (0x11331, "X"), + (0x11332, "V"), + (0x11334, "X"), + (0x11335, "V"), + (0x1133A, "X"), + (0x1133B, "V"), + (0x11345, "X"), + (0x11347, "V"), + (0x11349, "X"), + (0x1134B, "V"), + (0x1134E, "X"), + (0x11350, "V"), + (0x11351, "X"), + (0x11357, "V"), + (0x11358, "X"), + (0x1135D, "V"), + (0x11364, "X"), + (0x11366, "V"), + (0x1136D, "X"), + (0x11370, "V"), + (0x11375, "X"), + (0x11400, "V"), + (0x1145C, "X"), + (0x1145D, "V"), + (0x11462, "X"), + (0x11480, "V"), + (0x114C8, "X"), + (0x114D0, "V"), + (0x114DA, "X"), + (0x11580, "V"), + (0x115B6, "X"), + (0x115B8, "V"), + (0x115DE, "X"), + (0x11600, "V"), + (0x11645, "X"), + (0x11650, "V"), + (0x1165A, "X"), + (0x11660, "V"), + (0x1166D, "X"), + (0x11680, "V"), + (0x116BA, "X"), + (0x116C0, "V"), + (0x116CA, "X"), + (0x11700, "V"), + (0x1171B, "X"), + (0x1171D, "V"), + (0x1172C, "X"), + (0x11730, "V"), + (0x11747, "X"), + (0x11800, "V"), + (0x1183C, "X"), + (0x118A0, "M", "𑣀"), + (0x118A1, "M", "𑣁"), + (0x118A2, "M", "𑣂"), + (0x118A3, "M", "𑣃"), + (0x118A4, "M", "𑣄"), + (0x118A5, "M", "𑣅"), + (0x118A6, "M", "𑣆"), + (0x118A7, "M", "𑣇"), + (0x118A8, "M", "𑣈"), + (0x118A9, "M", "𑣉"), + (0x118AA, "M", "𑣊"), + ] + + +def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x118AB, "M", "𑣋"), + (0x118AC, "M", "𑣌"), + (0x118AD, "M", "𑣍"), + (0x118AE, "M", "𑣎"), + (0x118AF, "M", "𑣏"), + (0x118B0, "M", "𑣐"), + (0x118B1, "M", "𑣑"), + (0x118B2, "M", "𑣒"), + (0x118B3, "M", "𑣓"), + (0x118B4, "M", "𑣔"), + (0x118B5, "M", "𑣕"), + (0x118B6, "M", "𑣖"), + (0x118B7, "M", "𑣗"), + (0x118B8, "M", "𑣘"), + (0x118B9, "M", "𑣙"), + (0x118BA, "M", "𑣚"), + (0x118BB, "M", "𑣛"), + (0x118BC, "M", "𑣜"), + (0x118BD, "M", "𑣝"), + (0x118BE, "M", "𑣞"), + (0x118BF, "M", "𑣟"), + (0x118C0, "V"), + (0x118F3, "X"), + (0x118FF, "V"), + (0x11907, "X"), + (0x11909, "V"), + (0x1190A, "X"), + (0x1190C, "V"), + (0x11914, "X"), + (0x11915, "V"), + (0x11917, "X"), + (0x11918, "V"), + (0x11936, "X"), + (0x11937, "V"), + (0x11939, "X"), + (0x1193B, "V"), + (0x11947, "X"), + (0x11950, "V"), + (0x1195A, "X"), + (0x119A0, "V"), + (0x119A8, "X"), + (0x119AA, "V"), + (0x119D8, "X"), + (0x119DA, "V"), + (0x119E5, "X"), + (0x11A00, "V"), + (0x11A48, "X"), + (0x11A50, "V"), + (0x11AA3, "X"), + (0x11AB0, "V"), + (0x11AF9, "X"), + (0x11B00, "V"), + (0x11B0A, "X"), + (0x11C00, "V"), + (0x11C09, "X"), + (0x11C0A, "V"), + (0x11C37, "X"), + (0x11C38, "V"), + (0x11C46, "X"), + (0x11C50, "V"), + (0x11C6D, "X"), + (0x11C70, "V"), + (0x11C90, "X"), + (0x11C92, "V"), + (0x11CA8, "X"), + (0x11CA9, "V"), + (0x11CB7, "X"), + (0x11D00, "V"), + (0x11D07, "X"), + (0x11D08, "V"), + (0x11D0A, "X"), + (0x11D0B, "V"), + (0x11D37, "X"), + (0x11D3A, "V"), + (0x11D3B, "X"), + (0x11D3C, "V"), + (0x11D3E, "X"), + (0x11D3F, "V"), + (0x11D48, "X"), + (0x11D50, "V"), + (0x11D5A, "X"), + (0x11D60, "V"), + (0x11D66, "X"), + (0x11D67, "V"), + (0x11D69, "X"), + (0x11D6A, "V"), + (0x11D8F, "X"), + (0x11D90, "V"), + (0x11D92, "X"), + (0x11D93, "V"), + (0x11D99, "X"), + (0x11DA0, "V"), + (0x11DAA, "X"), + (0x11EE0, "V"), + (0x11EF9, "X"), + (0x11F00, "V"), + (0x11F11, "X"), + (0x11F12, "V"), + (0x11F3B, "X"), + (0x11F3E, "V"), + ] + + +def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x11F5A, "X"), + (0x11FB0, "V"), + (0x11FB1, "X"), + (0x11FC0, "V"), + (0x11FF2, "X"), + (0x11FFF, "V"), + (0x1239A, "X"), + (0x12400, "V"), + (0x1246F, "X"), + (0x12470, "V"), + (0x12475, "X"), + (0x12480, "V"), + (0x12544, "X"), + (0x12F90, "V"), + (0x12FF3, "X"), + (0x13000, "V"), + (0x13430, "X"), + (0x13440, "V"), + (0x13456, "X"), + (0x14400, "V"), + (0x14647, "X"), + (0x16800, "V"), + (0x16A39, "X"), + (0x16A40, "V"), + (0x16A5F, "X"), + (0x16A60, "V"), + (0x16A6A, "X"), + (0x16A6E, "V"), + (0x16ABF, "X"), + (0x16AC0, "V"), + (0x16ACA, "X"), + (0x16AD0, "V"), + (0x16AEE, "X"), + (0x16AF0, "V"), + (0x16AF6, "X"), + (0x16B00, "V"), + (0x16B46, "X"), + (0x16B50, "V"), + (0x16B5A, "X"), + (0x16B5B, "V"), + (0x16B62, "X"), + (0x16B63, "V"), + (0x16B78, "X"), + (0x16B7D, "V"), + (0x16B90, "X"), + (0x16E40, "M", "𖹠"), + (0x16E41, "M", "𖹡"), + (0x16E42, "M", "𖹢"), + (0x16E43, "M", "𖹣"), + (0x16E44, "M", "𖹤"), + (0x16E45, "M", "𖹥"), + (0x16E46, "M", "𖹦"), + (0x16E47, "M", "𖹧"), + (0x16E48, "M", "𖹨"), + (0x16E49, "M", "𖹩"), + (0x16E4A, "M", "𖹪"), + (0x16E4B, "M", "𖹫"), + (0x16E4C, "M", "𖹬"), + (0x16E4D, "M", "𖹭"), + (0x16E4E, "M", "𖹮"), + (0x16E4F, "M", "𖹯"), + (0x16E50, "M", "𖹰"), + (0x16E51, "M", "𖹱"), + (0x16E52, "M", "𖹲"), + (0x16E53, "M", "𖹳"), + (0x16E54, "M", "𖹴"), + (0x16E55, "M", "𖹵"), + (0x16E56, "M", "𖹶"), + (0x16E57, "M", "𖹷"), + (0x16E58, "M", "𖹸"), + (0x16E59, "M", "𖹹"), + (0x16E5A, "M", "𖹺"), + (0x16E5B, "M", "𖹻"), + (0x16E5C, "M", "𖹼"), + (0x16E5D, "M", "𖹽"), + (0x16E5E, "M", "𖹾"), + (0x16E5F, "M", "𖹿"), + (0x16E60, "V"), + (0x16E9B, "X"), + (0x16F00, "V"), + (0x16F4B, "X"), + (0x16F4F, "V"), + (0x16F88, "X"), + (0x16F8F, "V"), + (0x16FA0, "X"), + (0x16FE0, "V"), + (0x16FE5, "X"), + (0x16FF0, "V"), + (0x16FF2, "X"), + (0x17000, "V"), + (0x187F8, "X"), + (0x18800, "V"), + (0x18CD6, "X"), + (0x18D00, "V"), + (0x18D09, "X"), + (0x1AFF0, "V"), + (0x1AFF4, "X"), + (0x1AFF5, "V"), + (0x1AFFC, "X"), + (0x1AFFD, "V"), + ] + + +def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1AFFF, "X"), + (0x1B000, "V"), + (0x1B123, "X"), + (0x1B132, "V"), + (0x1B133, "X"), + (0x1B150, "V"), + (0x1B153, "X"), + (0x1B155, "V"), + (0x1B156, "X"), + (0x1B164, "V"), + (0x1B168, "X"), + (0x1B170, "V"), + (0x1B2FC, "X"), + (0x1BC00, "V"), + (0x1BC6B, "X"), + (0x1BC70, "V"), + (0x1BC7D, "X"), + (0x1BC80, "V"), + (0x1BC89, "X"), + (0x1BC90, "V"), + (0x1BC9A, "X"), + (0x1BC9C, "V"), + (0x1BCA0, "I"), + (0x1BCA4, "X"), + (0x1CF00, "V"), + (0x1CF2E, "X"), + (0x1CF30, "V"), + (0x1CF47, "X"), + (0x1CF50, "V"), + (0x1CFC4, "X"), + (0x1D000, "V"), + (0x1D0F6, "X"), + (0x1D100, "V"), + (0x1D127, "X"), + (0x1D129, "V"), + (0x1D15E, "M", "𝅗𝅥"), + (0x1D15F, "M", "𝅘𝅥"), + (0x1D160, "M", "𝅘𝅥𝅮"), + (0x1D161, "M", "𝅘𝅥𝅯"), + (0x1D162, "M", "𝅘𝅥𝅰"), + (0x1D163, "M", "𝅘𝅥𝅱"), + (0x1D164, "M", "𝅘𝅥𝅲"), + (0x1D165, "V"), + (0x1D173, "X"), + (0x1D17B, "V"), + (0x1D1BB, "M", "𝆹𝅥"), + (0x1D1BC, "M", "𝆺𝅥"), + (0x1D1BD, "M", "𝆹𝅥𝅮"), + (0x1D1BE, "M", "𝆺𝅥𝅮"), + (0x1D1BF, "M", "𝆹𝅥𝅯"), + (0x1D1C0, "M", "𝆺𝅥𝅯"), + (0x1D1C1, "V"), + (0x1D1EB, "X"), + (0x1D200, "V"), + (0x1D246, "X"), + (0x1D2C0, "V"), + (0x1D2D4, "X"), + (0x1D2E0, "V"), + (0x1D2F4, "X"), + (0x1D300, "V"), + (0x1D357, "X"), + (0x1D360, "V"), + (0x1D379, "X"), + (0x1D400, "M", "a"), + (0x1D401, "M", "b"), + (0x1D402, "M", "c"), + (0x1D403, "M", "d"), + (0x1D404, "M", "e"), + (0x1D405, "M", "f"), + (0x1D406, "M", "g"), + (0x1D407, "M", "h"), + (0x1D408, "M", "i"), + (0x1D409, "M", "j"), + (0x1D40A, "M", "k"), + (0x1D40B, "M", "l"), + (0x1D40C, "M", "m"), + (0x1D40D, "M", "n"), + (0x1D40E, "M", "o"), + (0x1D40F, "M", "p"), + (0x1D410, "M", "q"), + (0x1D411, "M", "r"), + (0x1D412, "M", "s"), + (0x1D413, "M", "t"), + (0x1D414, "M", "u"), + (0x1D415, "M", "v"), + (0x1D416, "M", "w"), + (0x1D417, "M", "x"), + (0x1D418, "M", "y"), + (0x1D419, "M", "z"), + (0x1D41A, "M", "a"), + (0x1D41B, "M", "b"), + (0x1D41C, "M", "c"), + (0x1D41D, "M", "d"), + (0x1D41E, "M", "e"), + (0x1D41F, "M", "f"), + (0x1D420, "M", "g"), + (0x1D421, "M", "h"), + (0x1D422, "M", "i"), + (0x1D423, "M", "j"), + (0x1D424, "M", "k"), + ] + + +def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D425, "M", "l"), + (0x1D426, "M", "m"), + (0x1D427, "M", "n"), + (0x1D428, "M", "o"), + (0x1D429, "M", "p"), + (0x1D42A, "M", "q"), + (0x1D42B, "M", "r"), + (0x1D42C, "M", "s"), + (0x1D42D, "M", "t"), + (0x1D42E, "M", "u"), + (0x1D42F, "M", "v"), + (0x1D430, "M", "w"), + (0x1D431, "M", "x"), + (0x1D432, "M", "y"), + (0x1D433, "M", "z"), + (0x1D434, "M", "a"), + (0x1D435, "M", "b"), + (0x1D436, "M", "c"), + (0x1D437, "M", "d"), + (0x1D438, "M", "e"), + (0x1D439, "M", "f"), + (0x1D43A, "M", "g"), + (0x1D43B, "M", "h"), + (0x1D43C, "M", "i"), + (0x1D43D, "M", "j"), + (0x1D43E, "M", "k"), + (0x1D43F, "M", "l"), + (0x1D440, "M", "m"), + (0x1D441, "M", "n"), + (0x1D442, "M", "o"), + (0x1D443, "M", "p"), + (0x1D444, "M", "q"), + (0x1D445, "M", "r"), + (0x1D446, "M", "s"), + (0x1D447, "M", "t"), + (0x1D448, "M", "u"), + (0x1D449, "M", "v"), + (0x1D44A, "M", "w"), + (0x1D44B, "M", "x"), + (0x1D44C, "M", "y"), + (0x1D44D, "M", "z"), + (0x1D44E, "M", "a"), + (0x1D44F, "M", "b"), + (0x1D450, "M", "c"), + (0x1D451, "M", "d"), + (0x1D452, "M", "e"), + (0x1D453, "M", "f"), + (0x1D454, "M", "g"), + (0x1D455, "X"), + (0x1D456, "M", "i"), + (0x1D457, "M", "j"), + (0x1D458, "M", "k"), + (0x1D459, "M", "l"), + (0x1D45A, "M", "m"), + (0x1D45B, "M", "n"), + (0x1D45C, "M", "o"), + (0x1D45D, "M", "p"), + (0x1D45E, "M", "q"), + (0x1D45F, "M", "r"), + (0x1D460, "M", "s"), + (0x1D461, "M", "t"), + (0x1D462, "M", "u"), + (0x1D463, "M", "v"), + (0x1D464, "M", "w"), + (0x1D465, "M", "x"), + (0x1D466, "M", "y"), + (0x1D467, "M", "z"), + (0x1D468, "M", "a"), + (0x1D469, "M", "b"), + (0x1D46A, "M", "c"), + (0x1D46B, "M", "d"), + (0x1D46C, "M", "e"), + (0x1D46D, "M", "f"), + (0x1D46E, "M", "g"), + (0x1D46F, "M", "h"), + (0x1D470, "M", "i"), + (0x1D471, "M", "j"), + (0x1D472, "M", "k"), + (0x1D473, "M", "l"), + (0x1D474, "M", "m"), + (0x1D475, "M", "n"), + (0x1D476, "M", "o"), + (0x1D477, "M", "p"), + (0x1D478, "M", "q"), + (0x1D479, "M", "r"), + (0x1D47A, "M", "s"), + (0x1D47B, "M", "t"), + (0x1D47C, "M", "u"), + (0x1D47D, "M", "v"), + (0x1D47E, "M", "w"), + (0x1D47F, "M", "x"), + (0x1D480, "M", "y"), + (0x1D481, "M", "z"), + (0x1D482, "M", "a"), + (0x1D483, "M", "b"), + (0x1D484, "M", "c"), + (0x1D485, "M", "d"), + (0x1D486, "M", "e"), + (0x1D487, "M", "f"), + (0x1D488, "M", "g"), + ] + + +def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D489, "M", "h"), + (0x1D48A, "M", "i"), + (0x1D48B, "M", "j"), + (0x1D48C, "M", "k"), + (0x1D48D, "M", "l"), + (0x1D48E, "M", "m"), + (0x1D48F, "M", "n"), + (0x1D490, "M", "o"), + (0x1D491, "M", "p"), + (0x1D492, "M", "q"), + (0x1D493, "M", "r"), + (0x1D494, "M", "s"), + (0x1D495, "M", "t"), + (0x1D496, "M", "u"), + (0x1D497, "M", "v"), + (0x1D498, "M", "w"), + (0x1D499, "M", "x"), + (0x1D49A, "M", "y"), + (0x1D49B, "M", "z"), + (0x1D49C, "M", "a"), + (0x1D49D, "X"), + (0x1D49E, "M", "c"), + (0x1D49F, "M", "d"), + (0x1D4A0, "X"), + (0x1D4A2, "M", "g"), + (0x1D4A3, "X"), + (0x1D4A5, "M", "j"), + (0x1D4A6, "M", "k"), + (0x1D4A7, "X"), + (0x1D4A9, "M", "n"), + (0x1D4AA, "M", "o"), + (0x1D4AB, "M", "p"), + (0x1D4AC, "M", "q"), + (0x1D4AD, "X"), + (0x1D4AE, "M", "s"), + (0x1D4AF, "M", "t"), + (0x1D4B0, "M", "u"), + (0x1D4B1, "M", "v"), + (0x1D4B2, "M", "w"), + (0x1D4B3, "M", "x"), + (0x1D4B4, "M", "y"), + (0x1D4B5, "M", "z"), + (0x1D4B6, "M", "a"), + (0x1D4B7, "M", "b"), + (0x1D4B8, "M", "c"), + (0x1D4B9, "M", "d"), + (0x1D4BA, "X"), + (0x1D4BB, "M", "f"), + (0x1D4BC, "X"), + (0x1D4BD, "M", "h"), + (0x1D4BE, "M", "i"), + (0x1D4BF, "M", "j"), + (0x1D4C0, "M", "k"), + (0x1D4C1, "M", "l"), + (0x1D4C2, "M", "m"), + (0x1D4C3, "M", "n"), + (0x1D4C4, "X"), + (0x1D4C5, "M", "p"), + (0x1D4C6, "M", "q"), + (0x1D4C7, "M", "r"), + (0x1D4C8, "M", "s"), + (0x1D4C9, "M", "t"), + (0x1D4CA, "M", "u"), + (0x1D4CB, "M", "v"), + (0x1D4CC, "M", "w"), + (0x1D4CD, "M", "x"), + (0x1D4CE, "M", "y"), + (0x1D4CF, "M", "z"), + (0x1D4D0, "M", "a"), + (0x1D4D1, "M", "b"), + (0x1D4D2, "M", "c"), + (0x1D4D3, "M", "d"), + (0x1D4D4, "M", "e"), + (0x1D4D5, "M", "f"), + (0x1D4D6, "M", "g"), + (0x1D4D7, "M", "h"), + (0x1D4D8, "M", "i"), + (0x1D4D9, "M", "j"), + (0x1D4DA, "M", "k"), + (0x1D4DB, "M", "l"), + (0x1D4DC, "M", "m"), + (0x1D4DD, "M", "n"), + (0x1D4DE, "M", "o"), + (0x1D4DF, "M", "p"), + (0x1D4E0, "M", "q"), + (0x1D4E1, "M", "r"), + (0x1D4E2, "M", "s"), + (0x1D4E3, "M", "t"), + (0x1D4E4, "M", "u"), + (0x1D4E5, "M", "v"), + (0x1D4E6, "M", "w"), + (0x1D4E7, "M", "x"), + (0x1D4E8, "M", "y"), + (0x1D4E9, "M", "z"), + (0x1D4EA, "M", "a"), + (0x1D4EB, "M", "b"), + (0x1D4EC, "M", "c"), + (0x1D4ED, "M", "d"), + (0x1D4EE, "M", "e"), + (0x1D4EF, "M", "f"), + ] + + +def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D4F0, "M", "g"), + (0x1D4F1, "M", "h"), + (0x1D4F2, "M", "i"), + (0x1D4F3, "M", "j"), + (0x1D4F4, "M", "k"), + (0x1D4F5, "M", "l"), + (0x1D4F6, "M", "m"), + (0x1D4F7, "M", "n"), + (0x1D4F8, "M", "o"), + (0x1D4F9, "M", "p"), + (0x1D4FA, "M", "q"), + (0x1D4FB, "M", "r"), + (0x1D4FC, "M", "s"), + (0x1D4FD, "M", "t"), + (0x1D4FE, "M", "u"), + (0x1D4FF, "M", "v"), + (0x1D500, "M", "w"), + (0x1D501, "M", "x"), + (0x1D502, "M", "y"), + (0x1D503, "M", "z"), + (0x1D504, "M", "a"), + (0x1D505, "M", "b"), + (0x1D506, "X"), + (0x1D507, "M", "d"), + (0x1D508, "M", "e"), + (0x1D509, "M", "f"), + (0x1D50A, "M", "g"), + (0x1D50B, "X"), + (0x1D50D, "M", "j"), + (0x1D50E, "M", "k"), + (0x1D50F, "M", "l"), + (0x1D510, "M", "m"), + (0x1D511, "M", "n"), + (0x1D512, "M", "o"), + (0x1D513, "M", "p"), + (0x1D514, "M", "q"), + (0x1D515, "X"), + (0x1D516, "M", "s"), + (0x1D517, "M", "t"), + (0x1D518, "M", "u"), + (0x1D519, "M", "v"), + (0x1D51A, "M", "w"), + (0x1D51B, "M", "x"), + (0x1D51C, "M", "y"), + (0x1D51D, "X"), + (0x1D51E, "M", "a"), + (0x1D51F, "M", "b"), + (0x1D520, "M", "c"), + (0x1D521, "M", "d"), + (0x1D522, "M", "e"), + (0x1D523, "M", "f"), + (0x1D524, "M", "g"), + (0x1D525, "M", "h"), + (0x1D526, "M", "i"), + (0x1D527, "M", "j"), + (0x1D528, "M", "k"), + (0x1D529, "M", "l"), + (0x1D52A, "M", "m"), + (0x1D52B, "M", "n"), + (0x1D52C, "M", "o"), + (0x1D52D, "M", "p"), + (0x1D52E, "M", "q"), + (0x1D52F, "M", "r"), + (0x1D530, "M", "s"), + (0x1D531, "M", "t"), + (0x1D532, "M", "u"), + (0x1D533, "M", "v"), + (0x1D534, "M", "w"), + (0x1D535, "M", "x"), + (0x1D536, "M", "y"), + (0x1D537, "M", "z"), + (0x1D538, "M", "a"), + (0x1D539, "M", "b"), + (0x1D53A, "X"), + (0x1D53B, "M", "d"), + (0x1D53C, "M", "e"), + (0x1D53D, "M", "f"), + (0x1D53E, "M", "g"), + (0x1D53F, "X"), + (0x1D540, "M", "i"), + (0x1D541, "M", "j"), + (0x1D542, "M", "k"), + (0x1D543, "M", "l"), + (0x1D544, "M", "m"), + (0x1D545, "X"), + (0x1D546, "M", "o"), + (0x1D547, "X"), + (0x1D54A, "M", "s"), + (0x1D54B, "M", "t"), + (0x1D54C, "M", "u"), + (0x1D54D, "M", "v"), + (0x1D54E, "M", "w"), + (0x1D54F, "M", "x"), + (0x1D550, "M", "y"), + (0x1D551, "X"), + (0x1D552, "M", "a"), + (0x1D553, "M", "b"), + (0x1D554, "M", "c"), + (0x1D555, "M", "d"), + (0x1D556, "M", "e"), + ] + + +def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D557, "M", "f"), + (0x1D558, "M", "g"), + (0x1D559, "M", "h"), + (0x1D55A, "M", "i"), + (0x1D55B, "M", "j"), + (0x1D55C, "M", "k"), + (0x1D55D, "M", "l"), + (0x1D55E, "M", "m"), + (0x1D55F, "M", "n"), + (0x1D560, "M", "o"), + (0x1D561, "M", "p"), + (0x1D562, "M", "q"), + (0x1D563, "M", "r"), + (0x1D564, "M", "s"), + (0x1D565, "M", "t"), + (0x1D566, "M", "u"), + (0x1D567, "M", "v"), + (0x1D568, "M", "w"), + (0x1D569, "M", "x"), + (0x1D56A, "M", "y"), + (0x1D56B, "M", "z"), + (0x1D56C, "M", "a"), + (0x1D56D, "M", "b"), + (0x1D56E, "M", "c"), + (0x1D56F, "M", "d"), + (0x1D570, "M", "e"), + (0x1D571, "M", "f"), + (0x1D572, "M", "g"), + (0x1D573, "M", "h"), + (0x1D574, "M", "i"), + (0x1D575, "M", "j"), + (0x1D576, "M", "k"), + (0x1D577, "M", "l"), + (0x1D578, "M", "m"), + (0x1D579, "M", "n"), + (0x1D57A, "M", "o"), + (0x1D57B, "M", "p"), + (0x1D57C, "M", "q"), + (0x1D57D, "M", "r"), + (0x1D57E, "M", "s"), + (0x1D57F, "M", "t"), + (0x1D580, "M", "u"), + (0x1D581, "M", "v"), + (0x1D582, "M", "w"), + (0x1D583, "M", "x"), + (0x1D584, "M", "y"), + (0x1D585, "M", "z"), + (0x1D586, "M", "a"), + (0x1D587, "M", "b"), + (0x1D588, "M", "c"), + (0x1D589, "M", "d"), + (0x1D58A, "M", "e"), + (0x1D58B, "M", "f"), + (0x1D58C, "M", "g"), + (0x1D58D, "M", "h"), + (0x1D58E, "M", "i"), + (0x1D58F, "M", "j"), + (0x1D590, "M", "k"), + (0x1D591, "M", "l"), + (0x1D592, "M", "m"), + (0x1D593, "M", "n"), + (0x1D594, "M", "o"), + (0x1D595, "M", "p"), + (0x1D596, "M", "q"), + (0x1D597, "M", "r"), + (0x1D598, "M", "s"), + (0x1D599, "M", "t"), + (0x1D59A, "M", "u"), + (0x1D59B, "M", "v"), + (0x1D59C, "M", "w"), + (0x1D59D, "M", "x"), + (0x1D59E, "M", "y"), + (0x1D59F, "M", "z"), + (0x1D5A0, "M", "a"), + (0x1D5A1, "M", "b"), + (0x1D5A2, "M", "c"), + (0x1D5A3, "M", "d"), + (0x1D5A4, "M", "e"), + (0x1D5A5, "M", "f"), + (0x1D5A6, "M", "g"), + (0x1D5A7, "M", "h"), + (0x1D5A8, "M", "i"), + (0x1D5A9, "M", "j"), + (0x1D5AA, "M", "k"), + (0x1D5AB, "M", "l"), + (0x1D5AC, "M", "m"), + (0x1D5AD, "M", "n"), + (0x1D5AE, "M", "o"), + (0x1D5AF, "M", "p"), + (0x1D5B0, "M", "q"), + (0x1D5B1, "M", "r"), + (0x1D5B2, "M", "s"), + (0x1D5B3, "M", "t"), + (0x1D5B4, "M", "u"), + (0x1D5B5, "M", "v"), + (0x1D5B6, "M", "w"), + (0x1D5B7, "M", "x"), + (0x1D5B8, "M", "y"), + (0x1D5B9, "M", "z"), + (0x1D5BA, "M", "a"), + ] + + +def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D5BB, "M", "b"), + (0x1D5BC, "M", "c"), + (0x1D5BD, "M", "d"), + (0x1D5BE, "M", "e"), + (0x1D5BF, "M", "f"), + (0x1D5C0, "M", "g"), + (0x1D5C1, "M", "h"), + (0x1D5C2, "M", "i"), + (0x1D5C3, "M", "j"), + (0x1D5C4, "M", "k"), + (0x1D5C5, "M", "l"), + (0x1D5C6, "M", "m"), + (0x1D5C7, "M", "n"), + (0x1D5C8, "M", "o"), + (0x1D5C9, "M", "p"), + (0x1D5CA, "M", "q"), + (0x1D5CB, "M", "r"), + (0x1D5CC, "M", "s"), + (0x1D5CD, "M", "t"), + (0x1D5CE, "M", "u"), + (0x1D5CF, "M", "v"), + (0x1D5D0, "M", "w"), + (0x1D5D1, "M", "x"), + (0x1D5D2, "M", "y"), + (0x1D5D3, "M", "z"), + (0x1D5D4, "M", "a"), + (0x1D5D5, "M", "b"), + (0x1D5D6, "M", "c"), + (0x1D5D7, "M", "d"), + (0x1D5D8, "M", "e"), + (0x1D5D9, "M", "f"), + (0x1D5DA, "M", "g"), + (0x1D5DB, "M", "h"), + (0x1D5DC, "M", "i"), + (0x1D5DD, "M", "j"), + (0x1D5DE, "M", "k"), + (0x1D5DF, "M", "l"), + (0x1D5E0, "M", "m"), + (0x1D5E1, "M", "n"), + (0x1D5E2, "M", "o"), + (0x1D5E3, "M", "p"), + (0x1D5E4, "M", "q"), + (0x1D5E5, "M", "r"), + (0x1D5E6, "M", "s"), + (0x1D5E7, "M", "t"), + (0x1D5E8, "M", "u"), + (0x1D5E9, "M", "v"), + (0x1D5EA, "M", "w"), + (0x1D5EB, "M", "x"), + (0x1D5EC, "M", "y"), + (0x1D5ED, "M", "z"), + (0x1D5EE, "M", "a"), + (0x1D5EF, "M", "b"), + (0x1D5F0, "M", "c"), + (0x1D5F1, "M", "d"), + (0x1D5F2, "M", "e"), + (0x1D5F3, "M", "f"), + (0x1D5F4, "M", "g"), + (0x1D5F5, "M", "h"), + (0x1D5F6, "M", "i"), + (0x1D5F7, "M", "j"), + (0x1D5F8, "M", "k"), + (0x1D5F9, "M", "l"), + (0x1D5FA, "M", "m"), + (0x1D5FB, "M", "n"), + (0x1D5FC, "M", "o"), + (0x1D5FD, "M", "p"), + (0x1D5FE, "M", "q"), + (0x1D5FF, "M", "r"), + (0x1D600, "M", "s"), + (0x1D601, "M", "t"), + (0x1D602, "M", "u"), + (0x1D603, "M", "v"), + (0x1D604, "M", "w"), + (0x1D605, "M", "x"), + (0x1D606, "M", "y"), + (0x1D607, "M", "z"), + (0x1D608, "M", "a"), + (0x1D609, "M", "b"), + (0x1D60A, "M", "c"), + (0x1D60B, "M", "d"), + (0x1D60C, "M", "e"), + (0x1D60D, "M", "f"), + (0x1D60E, "M", "g"), + (0x1D60F, "M", "h"), + (0x1D610, "M", "i"), + (0x1D611, "M", "j"), + (0x1D612, "M", "k"), + (0x1D613, "M", "l"), + (0x1D614, "M", "m"), + (0x1D615, "M", "n"), + (0x1D616, "M", "o"), + (0x1D617, "M", "p"), + (0x1D618, "M", "q"), + (0x1D619, "M", "r"), + (0x1D61A, "M", "s"), + (0x1D61B, "M", "t"), + (0x1D61C, "M", "u"), + (0x1D61D, "M", "v"), + (0x1D61E, "M", "w"), + ] + + +def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D61F, "M", "x"), + (0x1D620, "M", "y"), + (0x1D621, "M", "z"), + (0x1D622, "M", "a"), + (0x1D623, "M", "b"), + (0x1D624, "M", "c"), + (0x1D625, "M", "d"), + (0x1D626, "M", "e"), + (0x1D627, "M", "f"), + (0x1D628, "M", "g"), + (0x1D629, "M", "h"), + (0x1D62A, "M", "i"), + (0x1D62B, "M", "j"), + (0x1D62C, "M", "k"), + (0x1D62D, "M", "l"), + (0x1D62E, "M", "m"), + (0x1D62F, "M", "n"), + (0x1D630, "M", "o"), + (0x1D631, "M", "p"), + (0x1D632, "M", "q"), + (0x1D633, "M", "r"), + (0x1D634, "M", "s"), + (0x1D635, "M", "t"), + (0x1D636, "M", "u"), + (0x1D637, "M", "v"), + (0x1D638, "M", "w"), + (0x1D639, "M", "x"), + (0x1D63A, "M", "y"), + (0x1D63B, "M", "z"), + (0x1D63C, "M", "a"), + (0x1D63D, "M", "b"), + (0x1D63E, "M", "c"), + (0x1D63F, "M", "d"), + (0x1D640, "M", "e"), + (0x1D641, "M", "f"), + (0x1D642, "M", "g"), + (0x1D643, "M", "h"), + (0x1D644, "M", "i"), + (0x1D645, "M", "j"), + (0x1D646, "M", "k"), + (0x1D647, "M", "l"), + (0x1D648, "M", "m"), + (0x1D649, "M", "n"), + (0x1D64A, "M", "o"), + (0x1D64B, "M", "p"), + (0x1D64C, "M", "q"), + (0x1D64D, "M", "r"), + (0x1D64E, "M", "s"), + (0x1D64F, "M", "t"), + (0x1D650, "M", "u"), + (0x1D651, "M", "v"), + (0x1D652, "M", "w"), + (0x1D653, "M", "x"), + (0x1D654, "M", "y"), + (0x1D655, "M", "z"), + (0x1D656, "M", "a"), + (0x1D657, "M", "b"), + (0x1D658, "M", "c"), + (0x1D659, "M", "d"), + (0x1D65A, "M", "e"), + (0x1D65B, "M", "f"), + (0x1D65C, "M", "g"), + (0x1D65D, "M", "h"), + (0x1D65E, "M", "i"), + (0x1D65F, "M", "j"), + (0x1D660, "M", "k"), + (0x1D661, "M", "l"), + (0x1D662, "M", "m"), + (0x1D663, "M", "n"), + (0x1D664, "M", "o"), + (0x1D665, "M", "p"), + (0x1D666, "M", "q"), + (0x1D667, "M", "r"), + (0x1D668, "M", "s"), + (0x1D669, "M", "t"), + (0x1D66A, "M", "u"), + (0x1D66B, "M", "v"), + (0x1D66C, "M", "w"), + (0x1D66D, "M", "x"), + (0x1D66E, "M", "y"), + (0x1D66F, "M", "z"), + (0x1D670, "M", "a"), + (0x1D671, "M", "b"), + (0x1D672, "M", "c"), + (0x1D673, "M", "d"), + (0x1D674, "M", "e"), + (0x1D675, "M", "f"), + (0x1D676, "M", "g"), + (0x1D677, "M", "h"), + (0x1D678, "M", "i"), + (0x1D679, "M", "j"), + (0x1D67A, "M", "k"), + (0x1D67B, "M", "l"), + (0x1D67C, "M", "m"), + (0x1D67D, "M", "n"), + (0x1D67E, "M", "o"), + (0x1D67F, "M", "p"), + (0x1D680, "M", "q"), + (0x1D681, "M", "r"), + (0x1D682, "M", "s"), + ] + + +def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D683, "M", "t"), + (0x1D684, "M", "u"), + (0x1D685, "M", "v"), + (0x1D686, "M", "w"), + (0x1D687, "M", "x"), + (0x1D688, "M", "y"), + (0x1D689, "M", "z"), + (0x1D68A, "M", "a"), + (0x1D68B, "M", "b"), + (0x1D68C, "M", "c"), + (0x1D68D, "M", "d"), + (0x1D68E, "M", "e"), + (0x1D68F, "M", "f"), + (0x1D690, "M", "g"), + (0x1D691, "M", "h"), + (0x1D692, "M", "i"), + (0x1D693, "M", "j"), + (0x1D694, "M", "k"), + (0x1D695, "M", "l"), + (0x1D696, "M", "m"), + (0x1D697, "M", "n"), + (0x1D698, "M", "o"), + (0x1D699, "M", "p"), + (0x1D69A, "M", "q"), + (0x1D69B, "M", "r"), + (0x1D69C, "M", "s"), + (0x1D69D, "M", "t"), + (0x1D69E, "M", "u"), + (0x1D69F, "M", "v"), + (0x1D6A0, "M", "w"), + (0x1D6A1, "M", "x"), + (0x1D6A2, "M", "y"), + (0x1D6A3, "M", "z"), + (0x1D6A4, "M", "ı"), + (0x1D6A5, "M", "ȷ"), + (0x1D6A6, "X"), + (0x1D6A8, "M", "α"), + (0x1D6A9, "M", "β"), + (0x1D6AA, "M", "γ"), + (0x1D6AB, "M", "δ"), + (0x1D6AC, "M", "ε"), + (0x1D6AD, "M", "ζ"), + (0x1D6AE, "M", "η"), + (0x1D6AF, "M", "θ"), + (0x1D6B0, "M", "ι"), + (0x1D6B1, "M", "κ"), + (0x1D6B2, "M", "λ"), + (0x1D6B3, "M", "μ"), + (0x1D6B4, "M", "ν"), + (0x1D6B5, "M", "ξ"), + (0x1D6B6, "M", "ο"), + (0x1D6B7, "M", "π"), + (0x1D6B8, "M", "ρ"), + (0x1D6B9, "M", "θ"), + (0x1D6BA, "M", "σ"), + (0x1D6BB, "M", "τ"), + (0x1D6BC, "M", "υ"), + (0x1D6BD, "M", "φ"), + (0x1D6BE, "M", "χ"), + (0x1D6BF, "M", "ψ"), + (0x1D6C0, "M", "ω"), + (0x1D6C1, "M", "∇"), + (0x1D6C2, "M", "α"), + (0x1D6C3, "M", "β"), + (0x1D6C4, "M", "γ"), + (0x1D6C5, "M", "δ"), + (0x1D6C6, "M", "ε"), + (0x1D6C7, "M", "ζ"), + (0x1D6C8, "M", "η"), + (0x1D6C9, "M", "θ"), + (0x1D6CA, "M", "ι"), + (0x1D6CB, "M", "κ"), + (0x1D6CC, "M", "λ"), + (0x1D6CD, "M", "μ"), + (0x1D6CE, "M", "ν"), + (0x1D6CF, "M", "ξ"), + (0x1D6D0, "M", "ο"), + (0x1D6D1, "M", "π"), + (0x1D6D2, "M", "ρ"), + (0x1D6D3, "M", "σ"), + (0x1D6D5, "M", "τ"), + (0x1D6D6, "M", "υ"), + (0x1D6D7, "M", "φ"), + (0x1D6D8, "M", "χ"), + (0x1D6D9, "M", "ψ"), + (0x1D6DA, "M", "ω"), + (0x1D6DB, "M", "∂"), + (0x1D6DC, "M", "ε"), + (0x1D6DD, "M", "θ"), + (0x1D6DE, "M", "κ"), + (0x1D6DF, "M", "φ"), + (0x1D6E0, "M", "ρ"), + (0x1D6E1, "M", "π"), + (0x1D6E2, "M", "α"), + (0x1D6E3, "M", "β"), + (0x1D6E4, "M", "γ"), + (0x1D6E5, "M", "δ"), + (0x1D6E6, "M", "ε"), + (0x1D6E7, "M", "ζ"), + (0x1D6E8, "M", "η"), + ] + + +def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D6E9, "M", "θ"), + (0x1D6EA, "M", "ι"), + (0x1D6EB, "M", "κ"), + (0x1D6EC, "M", "λ"), + (0x1D6ED, "M", "μ"), + (0x1D6EE, "M", "ν"), + (0x1D6EF, "M", "ξ"), + (0x1D6F0, "M", "ο"), + (0x1D6F1, "M", "π"), + (0x1D6F2, "M", "ρ"), + (0x1D6F3, "M", "θ"), + (0x1D6F4, "M", "σ"), + (0x1D6F5, "M", "τ"), + (0x1D6F6, "M", "υ"), + (0x1D6F7, "M", "φ"), + (0x1D6F8, "M", "χ"), + (0x1D6F9, "M", "ψ"), + (0x1D6FA, "M", "ω"), + (0x1D6FB, "M", "∇"), + (0x1D6FC, "M", "α"), + (0x1D6FD, "M", "β"), + (0x1D6FE, "M", "γ"), + (0x1D6FF, "M", "δ"), + (0x1D700, "M", "ε"), + (0x1D701, "M", "ζ"), + (0x1D702, "M", "η"), + (0x1D703, "M", "θ"), + (0x1D704, "M", "ι"), + (0x1D705, "M", "κ"), + (0x1D706, "M", "λ"), + (0x1D707, "M", "μ"), + (0x1D708, "M", "ν"), + (0x1D709, "M", "ξ"), + (0x1D70A, "M", "ο"), + (0x1D70B, "M", "π"), + (0x1D70C, "M", "ρ"), + (0x1D70D, "M", "σ"), + (0x1D70F, "M", "τ"), + (0x1D710, "M", "υ"), + (0x1D711, "M", "φ"), + (0x1D712, "M", "χ"), + (0x1D713, "M", "ψ"), + (0x1D714, "M", "ω"), + (0x1D715, "M", "∂"), + (0x1D716, "M", "ε"), + (0x1D717, "M", "θ"), + (0x1D718, "M", "κ"), + (0x1D719, "M", "φ"), + (0x1D71A, "M", "ρ"), + (0x1D71B, "M", "π"), + (0x1D71C, "M", "α"), + (0x1D71D, "M", "β"), + (0x1D71E, "M", "γ"), + (0x1D71F, "M", "δ"), + (0x1D720, "M", "ε"), + (0x1D721, "M", "ζ"), + (0x1D722, "M", "η"), + (0x1D723, "M", "θ"), + (0x1D724, "M", "ι"), + (0x1D725, "M", "κ"), + (0x1D726, "M", "λ"), + (0x1D727, "M", "μ"), + (0x1D728, "M", "ν"), + (0x1D729, "M", "ξ"), + (0x1D72A, "M", "ο"), + (0x1D72B, "M", "π"), + (0x1D72C, "M", "ρ"), + (0x1D72D, "M", "θ"), + (0x1D72E, "M", "σ"), + (0x1D72F, "M", "τ"), + (0x1D730, "M", "υ"), + (0x1D731, "M", "φ"), + (0x1D732, "M", "χ"), + (0x1D733, "M", "ψ"), + (0x1D734, "M", "ω"), + (0x1D735, "M", "∇"), + (0x1D736, "M", "α"), + (0x1D737, "M", "β"), + (0x1D738, "M", "γ"), + (0x1D739, "M", "δ"), + (0x1D73A, "M", "ε"), + (0x1D73B, "M", "ζ"), + (0x1D73C, "M", "η"), + (0x1D73D, "M", "θ"), + (0x1D73E, "M", "ι"), + (0x1D73F, "M", "κ"), + (0x1D740, "M", "λ"), + (0x1D741, "M", "μ"), + (0x1D742, "M", "ν"), + (0x1D743, "M", "ξ"), + (0x1D744, "M", "ο"), + (0x1D745, "M", "π"), + (0x1D746, "M", "ρ"), + (0x1D747, "M", "σ"), + (0x1D749, "M", "τ"), + (0x1D74A, "M", "υ"), + (0x1D74B, "M", "φ"), + (0x1D74C, "M", "χ"), + (0x1D74D, "M", "ψ"), + (0x1D74E, "M", "ω"), + ] + + +def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D74F, "M", "∂"), + (0x1D750, "M", "ε"), + (0x1D751, "M", "θ"), + (0x1D752, "M", "κ"), + (0x1D753, "M", "φ"), + (0x1D754, "M", "ρ"), + (0x1D755, "M", "π"), + (0x1D756, "M", "α"), + (0x1D757, "M", "β"), + (0x1D758, "M", "γ"), + (0x1D759, "M", "δ"), + (0x1D75A, "M", "ε"), + (0x1D75B, "M", "ζ"), + (0x1D75C, "M", "η"), + (0x1D75D, "M", "θ"), + (0x1D75E, "M", "ι"), + (0x1D75F, "M", "κ"), + (0x1D760, "M", "λ"), + (0x1D761, "M", "μ"), + (0x1D762, "M", "ν"), + (0x1D763, "M", "ξ"), + (0x1D764, "M", "ο"), + (0x1D765, "M", "π"), + (0x1D766, "M", "ρ"), + (0x1D767, "M", "θ"), + (0x1D768, "M", "σ"), + (0x1D769, "M", "τ"), + (0x1D76A, "M", "υ"), + (0x1D76B, "M", "φ"), + (0x1D76C, "M", "χ"), + (0x1D76D, "M", "ψ"), + (0x1D76E, "M", "ω"), + (0x1D76F, "M", "∇"), + (0x1D770, "M", "α"), + (0x1D771, "M", "β"), + (0x1D772, "M", "γ"), + (0x1D773, "M", "δ"), + (0x1D774, "M", "ε"), + (0x1D775, "M", "ζ"), + (0x1D776, "M", "η"), + (0x1D777, "M", "θ"), + (0x1D778, "M", "ι"), + (0x1D779, "M", "κ"), + (0x1D77A, "M", "λ"), + (0x1D77B, "M", "μ"), + (0x1D77C, "M", "ν"), + (0x1D77D, "M", "ξ"), + (0x1D77E, "M", "ο"), + (0x1D77F, "M", "π"), + (0x1D780, "M", "ρ"), + (0x1D781, "M", "σ"), + (0x1D783, "M", "τ"), + (0x1D784, "M", "υ"), + (0x1D785, "M", "φ"), + (0x1D786, "M", "χ"), + (0x1D787, "M", "ψ"), + (0x1D788, "M", "ω"), + (0x1D789, "M", "∂"), + (0x1D78A, "M", "ε"), + (0x1D78B, "M", "θ"), + (0x1D78C, "M", "κ"), + (0x1D78D, "M", "φ"), + (0x1D78E, "M", "ρ"), + (0x1D78F, "M", "π"), + (0x1D790, "M", "α"), + (0x1D791, "M", "β"), + (0x1D792, "M", "γ"), + (0x1D793, "M", "δ"), + (0x1D794, "M", "ε"), + (0x1D795, "M", "ζ"), + (0x1D796, "M", "η"), + (0x1D797, "M", "θ"), + (0x1D798, "M", "ι"), + (0x1D799, "M", "κ"), + (0x1D79A, "M", "λ"), + (0x1D79B, "M", "μ"), + (0x1D79C, "M", "ν"), + (0x1D79D, "M", "ξ"), + (0x1D79E, "M", "ο"), + (0x1D79F, "M", "π"), + (0x1D7A0, "M", "ρ"), + (0x1D7A1, "M", "θ"), + (0x1D7A2, "M", "σ"), + (0x1D7A3, "M", "τ"), + (0x1D7A4, "M", "υ"), + (0x1D7A5, "M", "φ"), + (0x1D7A6, "M", "χ"), + (0x1D7A7, "M", "ψ"), + (0x1D7A8, "M", "ω"), + (0x1D7A9, "M", "∇"), + (0x1D7AA, "M", "α"), + (0x1D7AB, "M", "β"), + (0x1D7AC, "M", "γ"), + (0x1D7AD, "M", "δ"), + (0x1D7AE, "M", "ε"), + (0x1D7AF, "M", "ζ"), + (0x1D7B0, "M", "η"), + (0x1D7B1, "M", "θ"), + (0x1D7B2, "M", "ι"), + (0x1D7B3, "M", "κ"), + ] + + +def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D7B4, "M", "λ"), + (0x1D7B5, "M", "μ"), + (0x1D7B6, "M", "ν"), + (0x1D7B7, "M", "ξ"), + (0x1D7B8, "M", "ο"), + (0x1D7B9, "M", "π"), + (0x1D7BA, "M", "ρ"), + (0x1D7BB, "M", "σ"), + (0x1D7BD, "M", "τ"), + (0x1D7BE, "M", "υ"), + (0x1D7BF, "M", "φ"), + (0x1D7C0, "M", "χ"), + (0x1D7C1, "M", "ψ"), + (0x1D7C2, "M", "ω"), + (0x1D7C3, "M", "∂"), + (0x1D7C4, "M", "ε"), + (0x1D7C5, "M", "θ"), + (0x1D7C6, "M", "κ"), + (0x1D7C7, "M", "φ"), + (0x1D7C8, "M", "ρ"), + (0x1D7C9, "M", "π"), + (0x1D7CA, "M", "ϝ"), + (0x1D7CC, "X"), + (0x1D7CE, "M", "0"), + (0x1D7CF, "M", "1"), + (0x1D7D0, "M", "2"), + (0x1D7D1, "M", "3"), + (0x1D7D2, "M", "4"), + (0x1D7D3, "M", "5"), + (0x1D7D4, "M", "6"), + (0x1D7D5, "M", "7"), + (0x1D7D6, "M", "8"), + (0x1D7D7, "M", "9"), + (0x1D7D8, "M", "0"), + (0x1D7D9, "M", "1"), + (0x1D7DA, "M", "2"), + (0x1D7DB, "M", "3"), + (0x1D7DC, "M", "4"), + (0x1D7DD, "M", "5"), + (0x1D7DE, "M", "6"), + (0x1D7DF, "M", "7"), + (0x1D7E0, "M", "8"), + (0x1D7E1, "M", "9"), + (0x1D7E2, "M", "0"), + (0x1D7E3, "M", "1"), + (0x1D7E4, "M", "2"), + (0x1D7E5, "M", "3"), + (0x1D7E6, "M", "4"), + (0x1D7E7, "M", "5"), + (0x1D7E8, "M", "6"), + (0x1D7E9, "M", "7"), + (0x1D7EA, "M", "8"), + (0x1D7EB, "M", "9"), + (0x1D7EC, "M", "0"), + (0x1D7ED, "M", "1"), + (0x1D7EE, "M", "2"), + (0x1D7EF, "M", "3"), + (0x1D7F0, "M", "4"), + (0x1D7F1, "M", "5"), + (0x1D7F2, "M", "6"), + (0x1D7F3, "M", "7"), + (0x1D7F4, "M", "8"), + (0x1D7F5, "M", "9"), + (0x1D7F6, "M", "0"), + (0x1D7F7, "M", "1"), + (0x1D7F8, "M", "2"), + (0x1D7F9, "M", "3"), + (0x1D7FA, "M", "4"), + (0x1D7FB, "M", "5"), + (0x1D7FC, "M", "6"), + (0x1D7FD, "M", "7"), + (0x1D7FE, "M", "8"), + (0x1D7FF, "M", "9"), + (0x1D800, "V"), + (0x1DA8C, "X"), + (0x1DA9B, "V"), + (0x1DAA0, "X"), + (0x1DAA1, "V"), + (0x1DAB0, "X"), + (0x1DF00, "V"), + (0x1DF1F, "X"), + (0x1DF25, "V"), + (0x1DF2B, "X"), + (0x1E000, "V"), + (0x1E007, "X"), + (0x1E008, "V"), + (0x1E019, "X"), + (0x1E01B, "V"), + (0x1E022, "X"), + (0x1E023, "V"), + (0x1E025, "X"), + (0x1E026, "V"), + (0x1E02B, "X"), + (0x1E030, "M", "а"), + (0x1E031, "M", "б"), + (0x1E032, "M", "в"), + (0x1E033, "M", "г"), + (0x1E034, "M", "д"), + (0x1E035, "M", "е"), + (0x1E036, "M", "ж"), + ] + + +def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E037, "M", "з"), + (0x1E038, "M", "и"), + (0x1E039, "M", "к"), + (0x1E03A, "M", "л"), + (0x1E03B, "M", "м"), + (0x1E03C, "M", "о"), + (0x1E03D, "M", "п"), + (0x1E03E, "M", "р"), + (0x1E03F, "M", "с"), + (0x1E040, "M", "т"), + (0x1E041, "M", "у"), + (0x1E042, "M", "ф"), + (0x1E043, "M", "х"), + (0x1E044, "M", "ц"), + (0x1E045, "M", "ч"), + (0x1E046, "M", "ш"), + (0x1E047, "M", "ы"), + (0x1E048, "M", "э"), + (0x1E049, "M", "ю"), + (0x1E04A, "M", "ꚉ"), + (0x1E04B, "M", "ә"), + (0x1E04C, "M", "і"), + (0x1E04D, "M", "ј"), + (0x1E04E, "M", "ө"), + (0x1E04F, "M", "ү"), + (0x1E050, "M", "ӏ"), + (0x1E051, "M", "а"), + (0x1E052, "M", "б"), + (0x1E053, "M", "в"), + (0x1E054, "M", "г"), + (0x1E055, "M", "д"), + (0x1E056, "M", "е"), + (0x1E057, "M", "ж"), + (0x1E058, "M", "з"), + (0x1E059, "M", "и"), + (0x1E05A, "M", "к"), + (0x1E05B, "M", "л"), + (0x1E05C, "M", "о"), + (0x1E05D, "M", "п"), + (0x1E05E, "M", "с"), + (0x1E05F, "M", "у"), + (0x1E060, "M", "ф"), + (0x1E061, "M", "х"), + (0x1E062, "M", "ц"), + (0x1E063, "M", "ч"), + (0x1E064, "M", "ш"), + (0x1E065, "M", "ъ"), + (0x1E066, "M", "ы"), + (0x1E067, "M", "ґ"), + (0x1E068, "M", "і"), + (0x1E069, "M", "ѕ"), + (0x1E06A, "M", "џ"), + (0x1E06B, "M", "ҫ"), + (0x1E06C, "M", "ꙑ"), + (0x1E06D, "M", "ұ"), + (0x1E06E, "X"), + (0x1E08F, "V"), + (0x1E090, "X"), + (0x1E100, "V"), + (0x1E12D, "X"), + (0x1E130, "V"), + (0x1E13E, "X"), + (0x1E140, "V"), + (0x1E14A, "X"), + (0x1E14E, "V"), + (0x1E150, "X"), + (0x1E290, "V"), + (0x1E2AF, "X"), + (0x1E2C0, "V"), + (0x1E2FA, "X"), + (0x1E2FF, "V"), + (0x1E300, "X"), + (0x1E4D0, "V"), + (0x1E4FA, "X"), + (0x1E7E0, "V"), + (0x1E7E7, "X"), + (0x1E7E8, "V"), + (0x1E7EC, "X"), + (0x1E7ED, "V"), + (0x1E7EF, "X"), + (0x1E7F0, "V"), + (0x1E7FF, "X"), + (0x1E800, "V"), + (0x1E8C5, "X"), + (0x1E8C7, "V"), + (0x1E8D7, "X"), + (0x1E900, "M", "𞤢"), + (0x1E901, "M", "𞤣"), + (0x1E902, "M", "𞤤"), + (0x1E903, "M", "𞤥"), + (0x1E904, "M", "𞤦"), + (0x1E905, "M", "𞤧"), + (0x1E906, "M", "𞤨"), + (0x1E907, "M", "𞤩"), + (0x1E908, "M", "𞤪"), + (0x1E909, "M", "𞤫"), + (0x1E90A, "M", "𞤬"), + (0x1E90B, "M", "𞤭"), + (0x1E90C, "M", "𞤮"), + (0x1E90D, "M", "𞤯"), + ] + + +def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E90E, "M", "𞤰"), + (0x1E90F, "M", "𞤱"), + (0x1E910, "M", "𞤲"), + (0x1E911, "M", "𞤳"), + (0x1E912, "M", "𞤴"), + (0x1E913, "M", "𞤵"), + (0x1E914, "M", "𞤶"), + (0x1E915, "M", "𞤷"), + (0x1E916, "M", "𞤸"), + (0x1E917, "M", "𞤹"), + (0x1E918, "M", "𞤺"), + (0x1E919, "M", "𞤻"), + (0x1E91A, "M", "𞤼"), + (0x1E91B, "M", "𞤽"), + (0x1E91C, "M", "𞤾"), + (0x1E91D, "M", "𞤿"), + (0x1E91E, "M", "𞥀"), + (0x1E91F, "M", "𞥁"), + (0x1E920, "M", "𞥂"), + (0x1E921, "M", "𞥃"), + (0x1E922, "V"), + (0x1E94C, "X"), + (0x1E950, "V"), + (0x1E95A, "X"), + (0x1E95E, "V"), + (0x1E960, "X"), + (0x1EC71, "V"), + (0x1ECB5, "X"), + (0x1ED01, "V"), + (0x1ED3E, "X"), + (0x1EE00, "M", "ا"), + (0x1EE01, "M", "ب"), + (0x1EE02, "M", "ج"), + (0x1EE03, "M", "د"), + (0x1EE04, "X"), + (0x1EE05, "M", "و"), + (0x1EE06, "M", "ز"), + (0x1EE07, "M", "ح"), + (0x1EE08, "M", "ط"), + (0x1EE09, "M", "ي"), + (0x1EE0A, "M", "ك"), + (0x1EE0B, "M", "ل"), + (0x1EE0C, "M", "م"), + (0x1EE0D, "M", "ن"), + (0x1EE0E, "M", "س"), + (0x1EE0F, "M", "ع"), + (0x1EE10, "M", "ف"), + (0x1EE11, "M", "ص"), + (0x1EE12, "M", "ق"), + (0x1EE13, "M", "ر"), + (0x1EE14, "M", "ش"), + (0x1EE15, "M", "ت"), + (0x1EE16, "M", "ث"), + (0x1EE17, "M", "خ"), + (0x1EE18, "M", "ذ"), + (0x1EE19, "M", "ض"), + (0x1EE1A, "M", "ظ"), + (0x1EE1B, "M", "غ"), + (0x1EE1C, "M", "ٮ"), + (0x1EE1D, "M", "ں"), + (0x1EE1E, "M", "ڡ"), + (0x1EE1F, "M", "ٯ"), + (0x1EE20, "X"), + (0x1EE21, "M", "ب"), + (0x1EE22, "M", "ج"), + (0x1EE23, "X"), + (0x1EE24, "M", "ه"), + (0x1EE25, "X"), + (0x1EE27, "M", "ح"), + (0x1EE28, "X"), + (0x1EE29, "M", "ي"), + (0x1EE2A, "M", "ك"), + (0x1EE2B, "M", "ل"), + (0x1EE2C, "M", "م"), + (0x1EE2D, "M", "ن"), + (0x1EE2E, "M", "س"), + (0x1EE2F, "M", "ع"), + (0x1EE30, "M", "ف"), + (0x1EE31, "M", "ص"), + (0x1EE32, "M", "ق"), + (0x1EE33, "X"), + (0x1EE34, "M", "ش"), + (0x1EE35, "M", "ت"), + (0x1EE36, "M", "ث"), + (0x1EE37, "M", "خ"), + (0x1EE38, "X"), + (0x1EE39, "M", "ض"), + (0x1EE3A, "X"), + (0x1EE3B, "M", "غ"), + (0x1EE3C, "X"), + (0x1EE42, "M", "ج"), + (0x1EE43, "X"), + (0x1EE47, "M", "ح"), + (0x1EE48, "X"), + (0x1EE49, "M", "ي"), + (0x1EE4A, "X"), + (0x1EE4B, "M", "ل"), + (0x1EE4C, "X"), + (0x1EE4D, "M", "ن"), + (0x1EE4E, "M", "س"), + ] + + +def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EE4F, "M", "ع"), + (0x1EE50, "X"), + (0x1EE51, "M", "ص"), + (0x1EE52, "M", "ق"), + (0x1EE53, "X"), + (0x1EE54, "M", "ش"), + (0x1EE55, "X"), + (0x1EE57, "M", "خ"), + (0x1EE58, "X"), + (0x1EE59, "M", "ض"), + (0x1EE5A, "X"), + (0x1EE5B, "M", "غ"), + (0x1EE5C, "X"), + (0x1EE5D, "M", "ں"), + (0x1EE5E, "X"), + (0x1EE5F, "M", "ٯ"), + (0x1EE60, "X"), + (0x1EE61, "M", "ب"), + (0x1EE62, "M", "ج"), + (0x1EE63, "X"), + (0x1EE64, "M", "ه"), + (0x1EE65, "X"), + (0x1EE67, "M", "ح"), + (0x1EE68, "M", "ط"), + (0x1EE69, "M", "ي"), + (0x1EE6A, "M", "ك"), + (0x1EE6B, "X"), + (0x1EE6C, "M", "م"), + (0x1EE6D, "M", "ن"), + (0x1EE6E, "M", "س"), + (0x1EE6F, "M", "ع"), + (0x1EE70, "M", "ف"), + (0x1EE71, "M", "ص"), + (0x1EE72, "M", "ق"), + (0x1EE73, "X"), + (0x1EE74, "M", "ش"), + (0x1EE75, "M", "ت"), + (0x1EE76, "M", "ث"), + (0x1EE77, "M", "خ"), + (0x1EE78, "X"), + (0x1EE79, "M", "ض"), + (0x1EE7A, "M", "ظ"), + (0x1EE7B, "M", "غ"), + (0x1EE7C, "M", "ٮ"), + (0x1EE7D, "X"), + (0x1EE7E, "M", "ڡ"), + (0x1EE7F, "X"), + (0x1EE80, "M", "ا"), + (0x1EE81, "M", "ب"), + (0x1EE82, "M", "ج"), + (0x1EE83, "M", "د"), + (0x1EE84, "M", "ه"), + (0x1EE85, "M", "و"), + (0x1EE86, "M", "ز"), + (0x1EE87, "M", "ح"), + (0x1EE88, "M", "ط"), + (0x1EE89, "M", "ي"), + (0x1EE8A, "X"), + (0x1EE8B, "M", "ل"), + (0x1EE8C, "M", "م"), + (0x1EE8D, "M", "ن"), + (0x1EE8E, "M", "س"), + (0x1EE8F, "M", "ع"), + (0x1EE90, "M", "ف"), + (0x1EE91, "M", "ص"), + (0x1EE92, "M", "ق"), + (0x1EE93, "M", "ر"), + (0x1EE94, "M", "ش"), + (0x1EE95, "M", "ت"), + (0x1EE96, "M", "ث"), + (0x1EE97, "M", "خ"), + (0x1EE98, "M", "ذ"), + (0x1EE99, "M", "ض"), + (0x1EE9A, "M", "ظ"), + (0x1EE9B, "M", "غ"), + (0x1EE9C, "X"), + (0x1EEA1, "M", "ب"), + (0x1EEA2, "M", "ج"), + (0x1EEA3, "M", "د"), + (0x1EEA4, "X"), + (0x1EEA5, "M", "و"), + (0x1EEA6, "M", "ز"), + (0x1EEA7, "M", "ح"), + (0x1EEA8, "M", "ط"), + (0x1EEA9, "M", "ي"), + (0x1EEAA, "X"), + (0x1EEAB, "M", "ل"), + (0x1EEAC, "M", "م"), + (0x1EEAD, "M", "ن"), + (0x1EEAE, "M", "س"), + (0x1EEAF, "M", "ع"), + (0x1EEB0, "M", "ف"), + (0x1EEB1, "M", "ص"), + (0x1EEB2, "M", "ق"), + (0x1EEB3, "M", "ر"), + (0x1EEB4, "M", "ش"), + (0x1EEB5, "M", "ت"), + (0x1EEB6, "M", "ث"), + (0x1EEB7, "M", "خ"), + (0x1EEB8, "M", "ذ"), + ] + + +def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EEB9, "M", "ض"), + (0x1EEBA, "M", "ظ"), + (0x1EEBB, "M", "غ"), + (0x1EEBC, "X"), + (0x1EEF0, "V"), + (0x1EEF2, "X"), + (0x1F000, "V"), + (0x1F02C, "X"), + (0x1F030, "V"), + (0x1F094, "X"), + (0x1F0A0, "V"), + (0x1F0AF, "X"), + (0x1F0B1, "V"), + (0x1F0C0, "X"), + (0x1F0C1, "V"), + (0x1F0D0, "X"), + (0x1F0D1, "V"), + (0x1F0F6, "X"), + (0x1F101, "3", "0,"), + (0x1F102, "3", "1,"), + (0x1F103, "3", "2,"), + (0x1F104, "3", "3,"), + (0x1F105, "3", "4,"), + (0x1F106, "3", "5,"), + (0x1F107, "3", "6,"), + (0x1F108, "3", "7,"), + (0x1F109, "3", "8,"), + (0x1F10A, "3", "9,"), + (0x1F10B, "V"), + (0x1F110, "3", "(a)"), + (0x1F111, "3", "(b)"), + (0x1F112, "3", "(c)"), + (0x1F113, "3", "(d)"), + (0x1F114, "3", "(e)"), + (0x1F115, "3", "(f)"), + (0x1F116, "3", "(g)"), + (0x1F117, "3", "(h)"), + (0x1F118, "3", "(i)"), + (0x1F119, "3", "(j)"), + (0x1F11A, "3", "(k)"), + (0x1F11B, "3", "(l)"), + (0x1F11C, "3", "(m)"), + (0x1F11D, "3", "(n)"), + (0x1F11E, "3", "(o)"), + (0x1F11F, "3", "(p)"), + (0x1F120, "3", "(q)"), + (0x1F121, "3", "(r)"), + (0x1F122, "3", "(s)"), + (0x1F123, "3", "(t)"), + (0x1F124, "3", "(u)"), + (0x1F125, "3", "(v)"), + (0x1F126, "3", "(w)"), + (0x1F127, "3", "(x)"), + (0x1F128, "3", "(y)"), + (0x1F129, "3", "(z)"), + (0x1F12A, "M", "〔s〕"), + (0x1F12B, "M", "c"), + (0x1F12C, "M", "r"), + (0x1F12D, "M", "cd"), + (0x1F12E, "M", "wz"), + (0x1F12F, "V"), + (0x1F130, "M", "a"), + (0x1F131, "M", "b"), + (0x1F132, "M", "c"), + (0x1F133, "M", "d"), + (0x1F134, "M", "e"), + (0x1F135, "M", "f"), + (0x1F136, "M", "g"), + (0x1F137, "M", "h"), + (0x1F138, "M", "i"), + (0x1F139, "M", "j"), + (0x1F13A, "M", "k"), + (0x1F13B, "M", "l"), + (0x1F13C, "M", "m"), + (0x1F13D, "M", "n"), + (0x1F13E, "M", "o"), + (0x1F13F, "M", "p"), + (0x1F140, "M", "q"), + (0x1F141, "M", "r"), + (0x1F142, "M", "s"), + (0x1F143, "M", "t"), + (0x1F144, "M", "u"), + (0x1F145, "M", "v"), + (0x1F146, "M", "w"), + (0x1F147, "M", "x"), + (0x1F148, "M", "y"), + (0x1F149, "M", "z"), + (0x1F14A, "M", "hv"), + (0x1F14B, "M", "mv"), + (0x1F14C, "M", "sd"), + (0x1F14D, "M", "ss"), + (0x1F14E, "M", "ppv"), + (0x1F14F, "M", "wc"), + (0x1F150, "V"), + (0x1F16A, "M", "mc"), + (0x1F16B, "M", "md"), + (0x1F16C, "M", "mr"), + (0x1F16D, "V"), + (0x1F190, "M", "dj"), + (0x1F191, "V"), + ] + + +def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1F1AE, "X"), + (0x1F1E6, "V"), + (0x1F200, "M", "ほか"), + (0x1F201, "M", "ココ"), + (0x1F202, "M", "サ"), + (0x1F203, "X"), + (0x1F210, "M", "手"), + (0x1F211, "M", "字"), + (0x1F212, "M", "双"), + (0x1F213, "M", "デ"), + (0x1F214, "M", "二"), + (0x1F215, "M", "多"), + (0x1F216, "M", "解"), + (0x1F217, "M", "天"), + (0x1F218, "M", "交"), + (0x1F219, "M", "映"), + (0x1F21A, "M", "無"), + (0x1F21B, "M", "料"), + (0x1F21C, "M", "前"), + (0x1F21D, "M", "後"), + (0x1F21E, "M", "再"), + (0x1F21F, "M", "新"), + (0x1F220, "M", "初"), + (0x1F221, "M", "終"), + (0x1F222, "M", "生"), + (0x1F223, "M", "販"), + (0x1F224, "M", "声"), + (0x1F225, "M", "吹"), + (0x1F226, "M", "演"), + (0x1F227, "M", "投"), + (0x1F228, "M", "捕"), + (0x1F229, "M", "一"), + (0x1F22A, "M", "三"), + (0x1F22B, "M", "遊"), + (0x1F22C, "M", "左"), + (0x1F22D, "M", "中"), + (0x1F22E, "M", "右"), + (0x1F22F, "M", "指"), + (0x1F230, "M", "走"), + (0x1F231, "M", "打"), + (0x1F232, "M", "禁"), + (0x1F233, "M", "空"), + (0x1F234, "M", "合"), + (0x1F235, "M", "満"), + (0x1F236, "M", "有"), + (0x1F237, "M", "月"), + (0x1F238, "M", "申"), + (0x1F239, "M", "割"), + (0x1F23A, "M", "営"), + (0x1F23B, "M", "配"), + (0x1F23C, "X"), + (0x1F240, "M", "〔本〕"), + (0x1F241, "M", "〔三〕"), + (0x1F242, "M", "〔二〕"), + (0x1F243, "M", "〔安〕"), + (0x1F244, "M", "〔点〕"), + (0x1F245, "M", "〔打〕"), + (0x1F246, "M", "〔盗〕"), + (0x1F247, "M", "〔勝〕"), + (0x1F248, "M", "〔敗〕"), + (0x1F249, "X"), + (0x1F250, "M", "得"), + (0x1F251, "M", "可"), + (0x1F252, "X"), + (0x1F260, "V"), + (0x1F266, "X"), + (0x1F300, "V"), + (0x1F6D8, "X"), + (0x1F6DC, "V"), + (0x1F6ED, "X"), + (0x1F6F0, "V"), + (0x1F6FD, "X"), + (0x1F700, "V"), + (0x1F777, "X"), + (0x1F77B, "V"), + (0x1F7DA, "X"), + (0x1F7E0, "V"), + (0x1F7EC, "X"), + (0x1F7F0, "V"), + (0x1F7F1, "X"), + (0x1F800, "V"), + (0x1F80C, "X"), + (0x1F810, "V"), + (0x1F848, "X"), + (0x1F850, "V"), + (0x1F85A, "X"), + (0x1F860, "V"), + (0x1F888, "X"), + (0x1F890, "V"), + (0x1F8AE, "X"), + (0x1F8B0, "V"), + (0x1F8B2, "X"), + (0x1F900, "V"), + (0x1FA54, "X"), + (0x1FA60, "V"), + (0x1FA6E, "X"), + (0x1FA70, "V"), + (0x1FA7D, "X"), + (0x1FA80, "V"), + (0x1FA89, "X"), + ] + + +def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1FA90, "V"), + (0x1FABE, "X"), + (0x1FABF, "V"), + (0x1FAC6, "X"), + (0x1FACE, "V"), + (0x1FADC, "X"), + (0x1FAE0, "V"), + (0x1FAE9, "X"), + (0x1FAF0, "V"), + (0x1FAF9, "X"), + (0x1FB00, "V"), + (0x1FB93, "X"), + (0x1FB94, "V"), + (0x1FBCB, "X"), + (0x1FBF0, "M", "0"), + (0x1FBF1, "M", "1"), + (0x1FBF2, "M", "2"), + (0x1FBF3, "M", "3"), + (0x1FBF4, "M", "4"), + (0x1FBF5, "M", "5"), + (0x1FBF6, "M", "6"), + (0x1FBF7, "M", "7"), + (0x1FBF8, "M", "8"), + (0x1FBF9, "M", "9"), + (0x1FBFA, "X"), + (0x20000, "V"), + (0x2A6E0, "X"), + (0x2A700, "V"), + (0x2B73A, "X"), + (0x2B740, "V"), + (0x2B81E, "X"), + (0x2B820, "V"), + (0x2CEA2, "X"), + (0x2CEB0, "V"), + (0x2EBE1, "X"), + (0x2EBF0, "V"), + (0x2EE5E, "X"), + (0x2F800, "M", "丽"), + (0x2F801, "M", "丸"), + (0x2F802, "M", "乁"), + (0x2F803, "M", "𠄢"), + (0x2F804, "M", "你"), + (0x2F805, "M", "侮"), + (0x2F806, "M", "侻"), + (0x2F807, "M", "倂"), + (0x2F808, "M", "偺"), + (0x2F809, "M", "備"), + (0x2F80A, "M", "僧"), + (0x2F80B, "M", "像"), + (0x2F80C, "M", "㒞"), + (0x2F80D, "M", "𠘺"), + (0x2F80E, "M", "免"), + (0x2F80F, "M", "兔"), + (0x2F810, "M", "兤"), + (0x2F811, "M", "具"), + (0x2F812, "M", "𠔜"), + (0x2F813, "M", "㒹"), + (0x2F814, "M", "內"), + (0x2F815, "M", "再"), + (0x2F816, "M", "𠕋"), + (0x2F817, "M", "冗"), + (0x2F818, "M", "冤"), + (0x2F819, "M", "仌"), + (0x2F81A, "M", "冬"), + (0x2F81B, "M", "况"), + (0x2F81C, "M", "𩇟"), + (0x2F81D, "M", "凵"), + (0x2F81E, "M", "刃"), + (0x2F81F, "M", "㓟"), + (0x2F820, "M", "刻"), + (0x2F821, "M", "剆"), + (0x2F822, "M", "割"), + (0x2F823, "M", "剷"), + (0x2F824, "M", "㔕"), + (0x2F825, "M", "勇"), + (0x2F826, "M", "勉"), + (0x2F827, "M", "勤"), + (0x2F828, "M", "勺"), + (0x2F829, "M", "包"), + (0x2F82A, "M", "匆"), + (0x2F82B, "M", "北"), + (0x2F82C, "M", "卉"), + (0x2F82D, "M", "卑"), + (0x2F82E, "M", "博"), + (0x2F82F, "M", "即"), + (0x2F830, "M", "卽"), + (0x2F831, "M", "卿"), + (0x2F834, "M", "𠨬"), + (0x2F835, "M", "灰"), + (0x2F836, "M", "及"), + (0x2F837, "M", "叟"), + (0x2F838, "M", "𠭣"), + (0x2F839, "M", "叫"), + (0x2F83A, "M", "叱"), + (0x2F83B, "M", "吆"), + (0x2F83C, "M", "咞"), + (0x2F83D, "M", "吸"), + (0x2F83E, "M", "呈"), + (0x2F83F, "M", "周"), + (0x2F840, "M", "咢"), + ] + + +def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F841, "M", "哶"), + (0x2F842, "M", "唐"), + (0x2F843, "M", "啓"), + (0x2F844, "M", "啣"), + (0x2F845, "M", "善"), + (0x2F847, "M", "喙"), + (0x2F848, "M", "喫"), + (0x2F849, "M", "喳"), + (0x2F84A, "M", "嗂"), + (0x2F84B, "M", "圖"), + (0x2F84C, "M", "嘆"), + (0x2F84D, "M", "圗"), + (0x2F84E, "M", "噑"), + (0x2F84F, "M", "噴"), + (0x2F850, "M", "切"), + (0x2F851, "M", "壮"), + (0x2F852, "M", "城"), + (0x2F853, "M", "埴"), + (0x2F854, "M", "堍"), + (0x2F855, "M", "型"), + (0x2F856, "M", "堲"), + (0x2F857, "M", "報"), + (0x2F858, "M", "墬"), + (0x2F859, "M", "𡓤"), + (0x2F85A, "M", "売"), + (0x2F85B, "M", "壷"), + (0x2F85C, "M", "夆"), + (0x2F85D, "M", "多"), + (0x2F85E, "M", "夢"), + (0x2F85F, "M", "奢"), + (0x2F860, "M", "𡚨"), + (0x2F861, "M", "𡛪"), + (0x2F862, "M", "姬"), + (0x2F863, "M", "娛"), + (0x2F864, "M", "娧"), + (0x2F865, "M", "姘"), + (0x2F866, "M", "婦"), + (0x2F867, "M", "㛮"), + (0x2F868, "X"), + (0x2F869, "M", "嬈"), + (0x2F86A, "M", "嬾"), + (0x2F86C, "M", "𡧈"), + (0x2F86D, "M", "寃"), + (0x2F86E, "M", "寘"), + (0x2F86F, "M", "寧"), + (0x2F870, "M", "寳"), + (0x2F871, "M", "𡬘"), + (0x2F872, "M", "寿"), + (0x2F873, "M", "将"), + (0x2F874, "X"), + (0x2F875, "M", "尢"), + (0x2F876, "M", "㞁"), + (0x2F877, "M", "屠"), + (0x2F878, "M", "屮"), + (0x2F879, "M", "峀"), + (0x2F87A, "M", "岍"), + (0x2F87B, "M", "𡷤"), + (0x2F87C, "M", "嵃"), + (0x2F87D, "M", "𡷦"), + (0x2F87E, "M", "嵮"), + (0x2F87F, "M", "嵫"), + (0x2F880, "M", "嵼"), + (0x2F881, "M", "巡"), + (0x2F882, "M", "巢"), + (0x2F883, "M", "㠯"), + (0x2F884, "M", "巽"), + (0x2F885, "M", "帨"), + (0x2F886, "M", "帽"), + (0x2F887, "M", "幩"), + (0x2F888, "M", "㡢"), + (0x2F889, "M", "𢆃"), + (0x2F88A, "M", "㡼"), + (0x2F88B, "M", "庰"), + (0x2F88C, "M", "庳"), + (0x2F88D, "M", "庶"), + (0x2F88E, "M", "廊"), + (0x2F88F, "M", "𪎒"), + (0x2F890, "M", "廾"), + (0x2F891, "M", "𢌱"), + (0x2F893, "M", "舁"), + (0x2F894, "M", "弢"), + (0x2F896, "M", "㣇"), + (0x2F897, "M", "𣊸"), + (0x2F898, "M", "𦇚"), + (0x2F899, "M", "形"), + (0x2F89A, "M", "彫"), + (0x2F89B, "M", "㣣"), + (0x2F89C, "M", "徚"), + (0x2F89D, "M", "忍"), + (0x2F89E, "M", "志"), + (0x2F89F, "M", "忹"), + (0x2F8A0, "M", "悁"), + (0x2F8A1, "M", "㤺"), + (0x2F8A2, "M", "㤜"), + (0x2F8A3, "M", "悔"), + (0x2F8A4, "M", "𢛔"), + (0x2F8A5, "M", "惇"), + (0x2F8A6, "M", "慈"), + (0x2F8A7, "M", "慌"), + (0x2F8A8, "M", "慎"), + ] + + +def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F8A9, "M", "慌"), + (0x2F8AA, "M", "慺"), + (0x2F8AB, "M", "憎"), + (0x2F8AC, "M", "憲"), + (0x2F8AD, "M", "憤"), + (0x2F8AE, "M", "憯"), + (0x2F8AF, "M", "懞"), + (0x2F8B0, "M", "懲"), + (0x2F8B1, "M", "懶"), + (0x2F8B2, "M", "成"), + (0x2F8B3, "M", "戛"), + (0x2F8B4, "M", "扝"), + (0x2F8B5, "M", "抱"), + (0x2F8B6, "M", "拔"), + (0x2F8B7, "M", "捐"), + (0x2F8B8, "M", "𢬌"), + (0x2F8B9, "M", "挽"), + (0x2F8BA, "M", "拼"), + (0x2F8BB, "M", "捨"), + (0x2F8BC, "M", "掃"), + (0x2F8BD, "M", "揤"), + (0x2F8BE, "M", "𢯱"), + (0x2F8BF, "M", "搢"), + (0x2F8C0, "M", "揅"), + (0x2F8C1, "M", "掩"), + (0x2F8C2, "M", "㨮"), + (0x2F8C3, "M", "摩"), + (0x2F8C4, "M", "摾"), + (0x2F8C5, "M", "撝"), + (0x2F8C6, "M", "摷"), + (0x2F8C7, "M", "㩬"), + (0x2F8C8, "M", "敏"), + (0x2F8C9, "M", "敬"), + (0x2F8CA, "M", "𣀊"), + (0x2F8CB, "M", "旣"), + (0x2F8CC, "M", "書"), + (0x2F8CD, "M", "晉"), + (0x2F8CE, "M", "㬙"), + (0x2F8CF, "M", "暑"), + (0x2F8D0, "M", "㬈"), + (0x2F8D1, "M", "㫤"), + (0x2F8D2, "M", "冒"), + (0x2F8D3, "M", "冕"), + (0x2F8D4, "M", "最"), + (0x2F8D5, "M", "暜"), + (0x2F8D6, "M", "肭"), + (0x2F8D7, "M", "䏙"), + (0x2F8D8, "M", "朗"), + (0x2F8D9, "M", "望"), + (0x2F8DA, "M", "朡"), + (0x2F8DB, "M", "杞"), + (0x2F8DC, "M", "杓"), + (0x2F8DD, "M", "𣏃"), + (0x2F8DE, "M", "㭉"), + (0x2F8DF, "M", "柺"), + (0x2F8E0, "M", "枅"), + (0x2F8E1, "M", "桒"), + (0x2F8E2, "M", "梅"), + (0x2F8E3, "M", "𣑭"), + (0x2F8E4, "M", "梎"), + (0x2F8E5, "M", "栟"), + (0x2F8E6, "M", "椔"), + (0x2F8E7, "M", "㮝"), + (0x2F8E8, "M", "楂"), + (0x2F8E9, "M", "榣"), + (0x2F8EA, "M", "槪"), + (0x2F8EB, "M", "檨"), + (0x2F8EC, "M", "𣚣"), + (0x2F8ED, "M", "櫛"), + (0x2F8EE, "M", "㰘"), + (0x2F8EF, "M", "次"), + (0x2F8F0, "M", "𣢧"), + (0x2F8F1, "M", "歔"), + (0x2F8F2, "M", "㱎"), + (0x2F8F3, "M", "歲"), + (0x2F8F4, "M", "殟"), + (0x2F8F5, "M", "殺"), + (0x2F8F6, "M", "殻"), + (0x2F8F7, "M", "𣪍"), + (0x2F8F8, "M", "𡴋"), + (0x2F8F9, "M", "𣫺"), + (0x2F8FA, "M", "汎"), + (0x2F8FB, "M", "𣲼"), + (0x2F8FC, "M", "沿"), + (0x2F8FD, "M", "泍"), + (0x2F8FE, "M", "汧"), + (0x2F8FF, "M", "洖"), + (0x2F900, "M", "派"), + (0x2F901, "M", "海"), + (0x2F902, "M", "流"), + (0x2F903, "M", "浩"), + (0x2F904, "M", "浸"), + (0x2F905, "M", "涅"), + (0x2F906, "M", "𣴞"), + (0x2F907, "M", "洴"), + (0x2F908, "M", "港"), + (0x2F909, "M", "湮"), + (0x2F90A, "M", "㴳"), + (0x2F90B, "M", "滋"), + (0x2F90C, "M", "滇"), + ] + + +def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F90D, "M", "𣻑"), + (0x2F90E, "M", "淹"), + (0x2F90F, "M", "潮"), + (0x2F910, "M", "𣽞"), + (0x2F911, "M", "𣾎"), + (0x2F912, "M", "濆"), + (0x2F913, "M", "瀹"), + (0x2F914, "M", "瀞"), + (0x2F915, "M", "瀛"), + (0x2F916, "M", "㶖"), + (0x2F917, "M", "灊"), + (0x2F918, "M", "災"), + (0x2F919, "M", "灷"), + (0x2F91A, "M", "炭"), + (0x2F91B, "M", "𠔥"), + (0x2F91C, "M", "煅"), + (0x2F91D, "M", "𤉣"), + (0x2F91E, "M", "熜"), + (0x2F91F, "X"), + (0x2F920, "M", "爨"), + (0x2F921, "M", "爵"), + (0x2F922, "M", "牐"), + (0x2F923, "M", "𤘈"), + (0x2F924, "M", "犀"), + (0x2F925, "M", "犕"), + (0x2F926, "M", "𤜵"), + (0x2F927, "M", "𤠔"), + (0x2F928, "M", "獺"), + (0x2F929, "M", "王"), + (0x2F92A, "M", "㺬"), + (0x2F92B, "M", "玥"), + (0x2F92C, "M", "㺸"), + (0x2F92E, "M", "瑇"), + (0x2F92F, "M", "瑜"), + (0x2F930, "M", "瑱"), + (0x2F931, "M", "璅"), + (0x2F932, "M", "瓊"), + (0x2F933, "M", "㼛"), + (0x2F934, "M", "甤"), + (0x2F935, "M", "𤰶"), + (0x2F936, "M", "甾"), + (0x2F937, "M", "𤲒"), + (0x2F938, "M", "異"), + (0x2F939, "M", "𢆟"), + (0x2F93A, "M", "瘐"), + (0x2F93B, "M", "𤾡"), + (0x2F93C, "M", "𤾸"), + (0x2F93D, "M", "𥁄"), + (0x2F93E, "M", "㿼"), + (0x2F93F, "M", "䀈"), + (0x2F940, "M", "直"), + (0x2F941, "M", "𥃳"), + (0x2F942, "M", "𥃲"), + (0x2F943, "M", "𥄙"), + (0x2F944, "M", "𥄳"), + (0x2F945, "M", "眞"), + (0x2F946, "M", "真"), + (0x2F948, "M", "睊"), + (0x2F949, "M", "䀹"), + (0x2F94A, "M", "瞋"), + (0x2F94B, "M", "䁆"), + (0x2F94C, "M", "䂖"), + (0x2F94D, "M", "𥐝"), + (0x2F94E, "M", "硎"), + (0x2F94F, "M", "碌"), + (0x2F950, "M", "磌"), + (0x2F951, "M", "䃣"), + (0x2F952, "M", "𥘦"), + (0x2F953, "M", "祖"), + (0x2F954, "M", "𥚚"), + (0x2F955, "M", "𥛅"), + (0x2F956, "M", "福"), + (0x2F957, "M", "秫"), + (0x2F958, "M", "䄯"), + (0x2F959, "M", "穀"), + (0x2F95A, "M", "穊"), + (0x2F95B, "M", "穏"), + (0x2F95C, "M", "𥥼"), + (0x2F95D, "M", "𥪧"), + (0x2F95F, "X"), + (0x2F960, "M", "䈂"), + (0x2F961, "M", "𥮫"), + (0x2F962, "M", "篆"), + (0x2F963, "M", "築"), + (0x2F964, "M", "䈧"), + (0x2F965, "M", "𥲀"), + (0x2F966, "M", "糒"), + (0x2F967, "M", "䊠"), + (0x2F968, "M", "糨"), + (0x2F969, "M", "糣"), + (0x2F96A, "M", "紀"), + (0x2F96B, "M", "𥾆"), + (0x2F96C, "M", "絣"), + (0x2F96D, "M", "䌁"), + (0x2F96E, "M", "緇"), + (0x2F96F, "M", "縂"), + (0x2F970, "M", "繅"), + (0x2F971, "M", "䌴"), + (0x2F972, "M", "𦈨"), + (0x2F973, "M", "𦉇"), + ] + + +def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F974, "M", "䍙"), + (0x2F975, "M", "𦋙"), + (0x2F976, "M", "罺"), + (0x2F977, "M", "𦌾"), + (0x2F978, "M", "羕"), + (0x2F979, "M", "翺"), + (0x2F97A, "M", "者"), + (0x2F97B, "M", "𦓚"), + (0x2F97C, "M", "𦔣"), + (0x2F97D, "M", "聠"), + (0x2F97E, "M", "𦖨"), + (0x2F97F, "M", "聰"), + (0x2F980, "M", "𣍟"), + (0x2F981, "M", "䏕"), + (0x2F982, "M", "育"), + (0x2F983, "M", "脃"), + (0x2F984, "M", "䐋"), + (0x2F985, "M", "脾"), + (0x2F986, "M", "媵"), + (0x2F987, "M", "𦞧"), + (0x2F988, "M", "𦞵"), + (0x2F989, "M", "𣎓"), + (0x2F98A, "M", "𣎜"), + (0x2F98B, "M", "舁"), + (0x2F98C, "M", "舄"), + (0x2F98D, "M", "辞"), + (0x2F98E, "M", "䑫"), + (0x2F98F, "M", "芑"), + (0x2F990, "M", "芋"), + (0x2F991, "M", "芝"), + (0x2F992, "M", "劳"), + (0x2F993, "M", "花"), + (0x2F994, "M", "芳"), + (0x2F995, "M", "芽"), + (0x2F996, "M", "苦"), + (0x2F997, "M", "𦬼"), + (0x2F998, "M", "若"), + (0x2F999, "M", "茝"), + (0x2F99A, "M", "荣"), + (0x2F99B, "M", "莭"), + (0x2F99C, "M", "茣"), + (0x2F99D, "M", "莽"), + (0x2F99E, "M", "菧"), + (0x2F99F, "M", "著"), + (0x2F9A0, "M", "荓"), + (0x2F9A1, "M", "菊"), + (0x2F9A2, "M", "菌"), + (0x2F9A3, "M", "菜"), + (0x2F9A4, "M", "𦰶"), + (0x2F9A5, "M", "𦵫"), + (0x2F9A6, "M", "𦳕"), + (0x2F9A7, "M", "䔫"), + (0x2F9A8, "M", "蓱"), + (0x2F9A9, "M", "蓳"), + (0x2F9AA, "M", "蔖"), + (0x2F9AB, "M", "𧏊"), + (0x2F9AC, "M", "蕤"), + (0x2F9AD, "M", "𦼬"), + (0x2F9AE, "M", "䕝"), + (0x2F9AF, "M", "䕡"), + (0x2F9B0, "M", "𦾱"), + (0x2F9B1, "M", "𧃒"), + (0x2F9B2, "M", "䕫"), + (0x2F9B3, "M", "虐"), + (0x2F9B4, "M", "虜"), + (0x2F9B5, "M", "虧"), + (0x2F9B6, "M", "虩"), + (0x2F9B7, "M", "蚩"), + (0x2F9B8, "M", "蚈"), + (0x2F9B9, "M", "蜎"), + (0x2F9BA, "M", "蛢"), + (0x2F9BB, "M", "蝹"), + (0x2F9BC, "M", "蜨"), + (0x2F9BD, "M", "蝫"), + (0x2F9BE, "M", "螆"), + (0x2F9BF, "X"), + (0x2F9C0, "M", "蟡"), + (0x2F9C1, "M", "蠁"), + (0x2F9C2, "M", "䗹"), + (0x2F9C3, "M", "衠"), + (0x2F9C4, "M", "衣"), + (0x2F9C5, "M", "𧙧"), + (0x2F9C6, "M", "裗"), + (0x2F9C7, "M", "裞"), + (0x2F9C8, "M", "䘵"), + (0x2F9C9, "M", "裺"), + (0x2F9CA, "M", "㒻"), + (0x2F9CB, "M", "𧢮"), + (0x2F9CC, "M", "𧥦"), + (0x2F9CD, "M", "䚾"), + (0x2F9CE, "M", "䛇"), + (0x2F9CF, "M", "誠"), + (0x2F9D0, "M", "諭"), + (0x2F9D1, "M", "變"), + (0x2F9D2, "M", "豕"), + (0x2F9D3, "M", "𧲨"), + (0x2F9D4, "M", "貫"), + (0x2F9D5, "M", "賁"), + (0x2F9D6, "M", "贛"), + (0x2F9D7, "M", "起"), + ] + + +def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F9D8, "M", "𧼯"), + (0x2F9D9, "M", "𠠄"), + (0x2F9DA, "M", "跋"), + (0x2F9DB, "M", "趼"), + (0x2F9DC, "M", "跰"), + (0x2F9DD, "M", "𠣞"), + (0x2F9DE, "M", "軔"), + (0x2F9DF, "M", "輸"), + (0x2F9E0, "M", "𨗒"), + (0x2F9E1, "M", "𨗭"), + (0x2F9E2, "M", "邔"), + (0x2F9E3, "M", "郱"), + (0x2F9E4, "M", "鄑"), + (0x2F9E5, "M", "𨜮"), + (0x2F9E6, "M", "鄛"), + (0x2F9E7, "M", "鈸"), + (0x2F9E8, "M", "鋗"), + (0x2F9E9, "M", "鋘"), + (0x2F9EA, "M", "鉼"), + (0x2F9EB, "M", "鏹"), + (0x2F9EC, "M", "鐕"), + (0x2F9ED, "M", "𨯺"), + (0x2F9EE, "M", "開"), + (0x2F9EF, "M", "䦕"), + (0x2F9F0, "M", "閷"), + (0x2F9F1, "M", "𨵷"), + (0x2F9F2, "M", "䧦"), + (0x2F9F3, "M", "雃"), + (0x2F9F4, "M", "嶲"), + (0x2F9F5, "M", "霣"), + (0x2F9F6, "M", "𩅅"), + (0x2F9F7, "M", "𩈚"), + (0x2F9F8, "M", "䩮"), + (0x2F9F9, "M", "䩶"), + (0x2F9FA, "M", "韠"), + (0x2F9FB, "M", "𩐊"), + (0x2F9FC, "M", "䪲"), + (0x2F9FD, "M", "𩒖"), + (0x2F9FE, "M", "頋"), + (0x2FA00, "M", "頩"), + (0x2FA01, "M", "𩖶"), + (0x2FA02, "M", "飢"), + (0x2FA03, "M", "䬳"), + (0x2FA04, "M", "餩"), + (0x2FA05, "M", "馧"), + (0x2FA06, "M", "駂"), + (0x2FA07, "M", "駾"), + (0x2FA08, "M", "䯎"), + (0x2FA09, "M", "𩬰"), + (0x2FA0A, "M", "鬒"), + (0x2FA0B, "M", "鱀"), + (0x2FA0C, "M", "鳽"), + (0x2FA0D, "M", "䳎"), + (0x2FA0E, "M", "䳭"), + (0x2FA0F, "M", "鵧"), + (0x2FA10, "M", "𪃎"), + (0x2FA11, "M", "䳸"), + (0x2FA12, "M", "𪄅"), + (0x2FA13, "M", "𪈎"), + (0x2FA14, "M", "𪊑"), + (0x2FA15, "M", "麻"), + (0x2FA16, "M", "䵖"), + (0x2FA17, "M", "黹"), + (0x2FA18, "M", "黾"), + (0x2FA19, "M", "鼅"), + (0x2FA1A, "M", "鼏"), + (0x2FA1B, "M", "鼖"), + (0x2FA1C, "M", "鼻"), + (0x2FA1D, "M", "𪘀"), + (0x2FA1E, "X"), + (0x30000, "V"), + (0x3134B, "X"), + (0x31350, "V"), + (0x323B0, "X"), + (0xE0100, "I"), + (0xE01F0, "X"), + ] + + +uts46data = tuple( + _seg_0() + + _seg_1() + + _seg_2() + + _seg_3() + + _seg_4() + + _seg_5() + + _seg_6() + + _seg_7() + + _seg_8() + + _seg_9() + + _seg_10() + + _seg_11() + + _seg_12() + + _seg_13() + + _seg_14() + + _seg_15() + + _seg_16() + + _seg_17() + + _seg_18() + + _seg_19() + + _seg_20() + + _seg_21() + + _seg_22() + + _seg_23() + + _seg_24() + + _seg_25() + + _seg_26() + + _seg_27() + + _seg_28() + + _seg_29() + + _seg_30() + + _seg_31() + + _seg_32() + + _seg_33() + + _seg_34() + + _seg_35() + + _seg_36() + + _seg_37() + + _seg_38() + + _seg_39() + + _seg_40() + + _seg_41() + + _seg_42() + + _seg_43() + + _seg_44() + + _seg_45() + + _seg_46() + + _seg_47() + + _seg_48() + + _seg_49() + + _seg_50() + + _seg_51() + + _seg_52() + + _seg_53() + + _seg_54() + + _seg_55() + + _seg_56() + + _seg_57() + + _seg_58() + + _seg_59() + + _seg_60() + + _seg_61() + + _seg_62() + + _seg_63() + + _seg_64() + + _seg_65() + + _seg_66() + + _seg_67() + + _seg_68() + + _seg_69() + + _seg_70() + + _seg_71() + + _seg_72() + + _seg_73() + + _seg_74() + + _seg_75() + + _seg_76() + + _seg_77() + + _seg_78() + + _seg_79() + + _seg_80() + + _seg_81() +) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] diff --git a/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt new file mode 100644 index 0000000..7b190ca --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2011 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/METADATA b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/METADATA new file mode 100644 index 0000000..ddf5464 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: itsdangerous +Version: 2.2.0 +Summary: Safely pass data to untrusted environments and back. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/itsdangerous/ + +# ItsDangerous + +... so better sign this + +Various helpers to pass data to untrusted environments and to get it +back safe and sound. Data is cryptographically signed to ensure that a +token has not been tampered with. + +It's possible to customize how data is serialized. Data is compressed as +needed. A timestamp can be added and verified automatically while +loading a token. + + +## A Simple Example + +Here's how you could generate a token for transmitting a user's id and +name between web requests. + +```python +from itsdangerous import URLSafeSerializer +auth_s = URLSafeSerializer("secret key", "auth") +token = auth_s.dumps({"id": 5, "name": "itsdangerous"}) + +print(token) +# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg + +data = auth_s.loads(token) +print(data["name"]) +# itsdangerous +``` + + +## Donate + +The Pallets organization develops and supports ItsDangerous and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +[please donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/RECORD b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/RECORD new file mode 100644 index 0000000..245f43e --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/RECORD @@ -0,0 +1,22 @@ +itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475 +itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924 +itsdangerous-2.2.0.dist-info/RECORD,, +itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427 +itsdangerous/__pycache__/__init__.cpython-312.pyc,, +itsdangerous/__pycache__/_json.cpython-312.pyc,, +itsdangerous/__pycache__/encoding.cpython-312.pyc,, +itsdangerous/__pycache__/exc.cpython-312.pyc,, +itsdangerous/__pycache__/serializer.cpython-312.pyc,, +itsdangerous/__pycache__/signer.cpython-312.pyc,, +itsdangerous/__pycache__/timed.cpython-312.pyc,, +itsdangerous/__pycache__/url_safe.cpython-312.pyc,, +itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473 +itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409 +itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201 +itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601 +itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647 +itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083 +itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505 diff --git a/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/WHEEL b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous-2.2.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__init__.py b/venv/lib/python3.12/site-packages/itsdangerous/__init__.py new file mode 100644 index 0000000..ea55256 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/__init__.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import typing as t + +from .encoding import base64_decode as base64_decode +from .encoding import base64_encode as base64_encode +from .encoding import want_bytes as want_bytes +from .exc import BadData as BadData +from .exc import BadHeader as BadHeader +from .exc import BadPayload as BadPayload +from .exc import BadSignature as BadSignature +from .exc import BadTimeSignature as BadTimeSignature +from .exc import SignatureExpired as SignatureExpired +from .serializer import Serializer as Serializer +from .signer import HMACAlgorithm as HMACAlgorithm +from .signer import NoneAlgorithm as NoneAlgorithm +from .signer import Signer as Signer +from .timed import TimedSerializer as TimedSerializer +from .timed import TimestampSigner as TimestampSigner +from .url_safe import URLSafeSerializer as URLSafeSerializer +from .url_safe import URLSafeTimedSerializer as URLSafeTimedSerializer + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " ItsDangerous 2.3. Use feature detection or" + " 'importlib.metadata.version(\"itsdangerous\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("itsdangerous") + + raise AttributeError(name) diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a447c645cc91a4b88f7468e73702fb0ad99df9c5 GIT binary patch literal 1640 zcmZXU&ube;6vt=vW3^goC0YKRnq=*!RkjeRwbMdqD7bN27a9}lgu-5yv1Tl3!@f zSO?CzImNla2=i`Uu>owlrs6zs!7V5@fs1ZYaRJzJEyYFPl3P-21?8~fRuq?lv9Rh^ z6_-EqYg;0bp^@mMe!PPtQxtH9IlwBqq#CY*I=6;A+Pa4!H)k;(5e?pxiIGkqkN z?r2E?M^P-W@Z*TD9cg{h+Q6KCbj>5Q850V#h60TSg1Lty;cavU9`IHIG1E@P;q~X}9;fyuRn>*} z1#QZvvSVh~{IDG}5%?SRkP1woQ|g0!t}OV1lVO|%rv{<9fc~i;$vkECp;*nGfbP;D zDUMEda!K|7ffHj7v&fHHJjqB(sw;z~Kr&zVA0@^xjU+e7BPlHpmw$_~m^tYr6XB31 z`Lj>3IY@}h8rin}+Hb&e8E*)>jd>f+PtaJ2o1KtGf;ZNv*o)Z?_f{cwEVkmPu}h=f z2JAqi-Ie}Q{e#5@_XWM$mQz}kH%8ai@H{{Ah3D1VU0J;rY#ZbU)q4lNKO+-a2lEYj zo-2HR_-AhJg)#ran0{$gezbnDj#DY?bL~_|)}`muGsgv#pE^Z)-aIa$%Ivf9{FCzh zv$FG~?EF%HTE70+xc-+p^Kjy+dGT@P;t7OBPKGVOElG315}i>vu+e^2)R&{KGnbg2 zx7m?r7}Am3k?5k^h8<5dkr?U^0S=Q5&t!kIoC-znH<@f|mX}8UlbP&iR+L6|E>!yL zoU@V?bgm9EE6XVrX~v|S74lTGsuaehV02jEaX7(jLTZ!J$bI@1v3Dh32J_mu5yqqw z&`;PBxbo2On_!O9nx^&8!Yfq$8(r(ktKLIz_fV~eoF2N`Lm#T^{T^CW*X5ydqlZ2_ L)l1qX^^yMoi3Q0s literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc b/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b78548fc1541dc6799d239d9f1ada00e75282860 GIT binary patch literal 1194 zcmZ`&y-yTD6rb5IRz4&k8YxURpeBoWt6(%S#KdUSSeykhCf96+n>pCyZg-uTg&a^& z(Aa1RrG*8C|HH-xB8jqULV}Hj2|{6Vm2Y+43a#@_v? z>|uls)SLM&f;7knE*FdC`0L;r80sK zACCiAN3wHQZI#xs1h9g(TKCgXXVKMC(^mmgvlbC5p!BYoG%~F0oMy#)Di{}@WK{ye zWl;0(N9Cl>LMgl=lZz3b7yctso+olH3cUpuE_k(I#)}*3JXyFt;R#6mDkMHnW|{B; zDJThN8B{C0EO;Sqa2uj64gN_?AwRY3-|7`S=!N5qidX7-FHDc|z)V_i$IDmKF;FlOUHH&F4 z3q``2PeeHg9;DrZ#e@?Xap7uBJl@2&U0rD@2-yAs7uzB%VN7mq>LWdThBTYBQGTl#w@^_Rsqy`C95~v1}#jD5JG87TiU1~FoL#xTotqNOj4W8+RTib z#v~}99?FRzDm4fpdO->*5=dMsPH^GE#g>s$Ek&wSap(alB0ZpT;mxc!sap<=y)$p# zdo%C<=9gG3ieT*e`OnD@!U)}xn_%cZfY%OTgf1h32zJmkPGcLsmG@?6A(~)!pqh>@}n_=Ggkv0;(5KcFfI595h=_ssCu$olM_Xff@*3S{(w`}YK z=yOCOUugNhV85}F=BuEw9OShas0ts_3qBc2q3eb!d80S(k%d+m~lBYOjJSk}2=0z~WNggd^OViX9Jei_m zroi6end5f$9b23&xXE+WJ(qNH6UpMN-0vNJVo#Fi1RW|$mMO}UIl+nTPEl4U@nj%( zxH#)YXKYtwCT0cYtQEwY@bLkd7SJ67MLHI@Upnz?)8^|fv5${`bbRrRrE|5Gofq*< zvt{A<8nB`4y2oH64N%^E8-PY{2B|QQgyd2qUr+yFFV{H~aORut#rrV90Tp~4D!+Ba z=5%z#^4)6L7C0FkY856eWs+53mZ0awuyyh*wHW0kM@YI)v>Av; z$d3=P2=s_lqR9`s=1`Y)0DD8&eMP#Qc)(FO2ttC8dEU{eZHQIz_30Vt2w304Ls+?G9V%&3VvVm3@4~A%`HveTUssm z^0A$8@e}ZIX~Y7$VfHR{*37;Yb4S(Oapm=zIaJYy9;_pogNEyUT;M&3kI*-tP`q&C!ZJs;q*B7%qv)p)tP;Wkn*wWLe%d!GG4A-}U@bP)e$L zkP!4QDoV`t!b&_eJeehISWZbfJq{CKAA!Zwz=#Iy?tsI`$_OMjd(lj0vILjXOoqwO zt0MAiLiWf~R(OV(Ez0K)3s0lxv#M@X)u|q-io=VkO3pY`2zU`agXE^*Eo046lX#}y zS#76y)}Ekn;|c#}l|Z8-nYtidzJqK)p3$>52fmW4PzkA+OdI9uuaR=2>e_cB`=<+} z?UmxD?uTPGt^=3G_ z76$rSM;Jf77LVfnt6Nb|-%9tcYWJ>6*Y4%!KMSR)##HjR)T^m~2m#Xed)#5KN#MTUq Mhwnr%eo7hjFQ9W`+W-In literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc b/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d27054490ae1739d2f98815ce053b745d720a4c7 GIT binary patch literal 3954 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/signer.cpython-312.pyc b/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/signer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f33d450374c85a643393ef2fb5a3d5115fd395f9 GIT binary patch literal 11299 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 DJA7&{ literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/url_safe.cpython-312.pyc b/venv/lib/python3.12/site-packages/itsdangerous/__pycache__/url_safe.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0d866b210c582e795a9d4969e0c157d6e356e61 GIT binary patch literal 3544 zcmbtWU2Ggz6~41Gv;RN-$*%1rCbw~_W<#<|lQak?K%Io9t%zIUMuDxuc)W9Mk3BoH z+?lQ8)tW{qh>Z}ac|dVRD_Io}sRB}vc;E>&NFX8l;M7Q1Lm~yWJoEu+Q@bKcUpVK^ zuI-po1YEE0oO{l>XYQPHzH`qXQ>i$Cap3oVpZr6NkoR%X8IgdH*4_o;8Zn3=S)?MB zBnjz|6)MT%sgx8$HWW*(giB$N$%bl0D$!C@&|#osrI?^2R=koZB?KL{l9f~`CFmH? z=~7zIaVt~lDs@RDM9vT+ahVuNmS)`paE2RlaH3L=kflJDW<48Hr7i6h(hNwuK-$&b z+mY^=59PZ*MAf|HCv@9(Jl!)L+a3K-3YballvAndW$*d17e+xTHKDug*ip@3WyfG! z7|d=n;wN?EMSb3KbOXd)+KZ=kPak94)Gf2lIPl_+tTHc|6=rO*%E8HlxqVP+?VGUv z0XUwKl4Oul=o|!~Br~O?8X*=o740JQ=M`)RkL(X-Hi{TrUydHqPpj? zO4XyDL+h3~5vMT9;5^P;mwMBTx*j*}DU?_AS%&-EX@`4^Q*)BqtPFZOpD)noItDG* z5mo}9)4;`BO}P%NbPr9Hb(^~I1=c*BV61^pg-80z@uvK(p$1+zkh{|q70+Fn@wL;^5K3u;4}LD{xpgl@FCJkpQ=3}h!+kPKx( zjS;V%z=SlUj@ClBq4FHa0Di%k5s>Vxf@dSVsqdvavMbRB`O$8$7M_wC@>|j`!X{}b zKa+kejgcYZwKIv3eT4TeM7%bjA#2n||&W!5ttB` zw8PCQ)7CAGaqjT?$fh|=JBr4(B;BULNry8bHAEIdLbhf3D8$;+x#wb%^Dvy!kA1E4 zN*=|vg0}tmrg2|&YgNYmBm!OQSc>_I%dAO1(q?c-6xgiuDc29r&f$~i1Z&21Y+qu2 zOw-Di?z)=hV$cyZI4(Uji{~H#-J-{4bhip+$ts?9%C!o!J-0Z@yg7%@y4tgPc~{TpuYsdAR7B9yygrtu)E)YR2y+dj6akyqy?aH2#zrTFnhE>WdSv%{I@h4h%M* zZzRai}H&5SBlVq+H3a19{^zFL#>eW}5yp_I#uPN(k(v`h3cRMq*bb2{6 zeEsNqncdUmgNon75S*HyVU-3pT(*;YhOWj|@jApK;$ zhwK;xMX;Wut2@rG4($WQz8+BQ9{|Pf0aQ#4Jah~232!DwddZFK$YFA;H#Sm~Z|zQx z9FT7vP?0_yJDHYm9Z#Q($-j-MKyOq4*hw&t0lm`NuYkY`;2~FxD`7w(RERB@4ncj8 zJ**mH%wT?P8;y-Rv7l^XzoB$+zJ<4;X@u%f8)gBwTxlo^Aw!0@Bszw-SX3J_R}H11 z)rhUAK`cb`?51J!v~Q{ znXcB+V}>8!LPr9K8+;Eay0~4WH@(Cu(0ngU|2Ffsp5}|7=zbd}$hBgWu@owX5_Dl{?**h#q(F~=9zn$Tr<4}Z-D!d?}Uf1PRx7E<-34>sCtDFdtSh~ zo)k1~&{4-`97-KZdIrC3FcAVrE}nBe2$Mlp*=A^eh`U6 zKnOcP7l01>jnTIieh9sR<%Sn=`T|UElfXw58Am(Qvp}pNJ}#4wFf@S t.Any: + return _json.loads(payload) + + @staticmethod + def dumps(obj: t.Any, **kwargs: t.Any) -> str: + kwargs.setdefault("ensure_ascii", False) + kwargs.setdefault("separators", (",", ":")) + return _json.dumps(obj, **kwargs) diff --git a/venv/lib/python3.12/site-packages/itsdangerous/encoding.py b/venv/lib/python3.12/site-packages/itsdangerous/encoding.py new file mode 100644 index 0000000..f5ca80f --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/encoding.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +import base64 +import string +import struct +import typing as t + +from .exc import BadData + + +def want_bytes( + s: str | bytes, encoding: str = "utf-8", errors: str = "strict" +) -> bytes: + if isinstance(s, str): + s = s.encode(encoding, errors) + + return s + + +def base64_encode(string: str | bytes) -> bytes: + """Base64 encode a string of bytes or text. The resulting bytes are + safe to use in URLs. + """ + string = want_bytes(string) + return base64.urlsafe_b64encode(string).rstrip(b"=") + + +def base64_decode(string: str | bytes) -> bytes: + """Base64 decode a URL-safe string of bytes or text. The result is + bytes. + """ + string = want_bytes(string, encoding="ascii", errors="ignore") + string += b"=" * (-len(string) % 4) + + try: + return base64.urlsafe_b64decode(string) + except (TypeError, ValueError) as e: + raise BadData("Invalid base64-encoded data") from e + + +# The alphabet used by base64.urlsafe_* +_base64_alphabet = f"{string.ascii_letters}{string.digits}-_=".encode("ascii") + +_int64_struct = struct.Struct(">Q") +_int_to_bytes = _int64_struct.pack +_bytes_to_int = t.cast("t.Callable[[bytes], tuple[int]]", _int64_struct.unpack) + + +def int_to_bytes(num: int) -> bytes: + return _int_to_bytes(num).lstrip(b"\x00") + + +def bytes_to_int(bytestr: bytes) -> int: + return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/venv/lib/python3.12/site-packages/itsdangerous/exc.py b/venv/lib/python3.12/site-packages/itsdangerous/exc.py new file mode 100644 index 0000000..a75adcd --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/exc.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime + + +class BadData(Exception): + """Raised if bad data of any sort was encountered. This is the base + for all exceptions that ItsDangerous defines. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str): + super().__init__(message) + self.message = message + + def __str__(self) -> str: + return self.message + + +class BadSignature(BadData): + """Raised if a signature does not match.""" + + def __init__(self, message: str, payload: t.Any | None = None): + super().__init__(message) + + #: The payload that failed the signature test. In some + #: situations you might still want to inspect this, even if + #: you know it was tampered with. + #: + #: .. versionadded:: 0.14 + self.payload: t.Any | None = payload + + +class BadTimeSignature(BadSignature): + """Raised if a time-based signature is invalid. This is a subclass + of :class:`BadSignature`. + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + date_signed: datetime | None = None, + ): + super().__init__(message, payload) + + #: If the signature expired this exposes the date of when the + #: signature was created. This can be helpful in order to + #: tell the user how long a link has been gone stale. + #: + #: .. versionchanged:: 2.0 + #: The datetime value is timezone-aware rather than naive. + #: + #: .. versionadded:: 0.14 + self.date_signed = date_signed + + +class SignatureExpired(BadTimeSignature): + """Raised if a signature timestamp is older than ``max_age``. This + is a subclass of :exc:`BadTimeSignature`. + """ + + +class BadHeader(BadSignature): + """Raised if a signed header is invalid in some form. This only + happens for serializers that have a header that goes with the + signature. + + .. versionadded:: 0.24 + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + header: t.Any | None = None, + original_error: Exception | None = None, + ): + super().__init__(message, payload) + + #: If the header is actually available but just malformed it + #: might be stored here. + self.header: t.Any | None = header + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error + + +class BadPayload(BadData): + """Raised if a payload is invalid. This could happen if the payload + is loaded despite an invalid signature, or if there is a mismatch + between the serializer and deserializer. The original exception + that occurred during loading is stored on as :attr:`original_error`. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str, original_error: Exception | None = None): + super().__init__(message) + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error diff --git a/venv/lib/python3.12/site-packages/itsdangerous/py.typed b/venv/lib/python3.12/site-packages/itsdangerous/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.12/site-packages/itsdangerous/serializer.py b/venv/lib/python3.12/site-packages/itsdangerous/serializer.py new file mode 100644 index 0000000..5ddf387 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/serializer.py @@ -0,0 +1,406 @@ +from __future__ import annotations + +import collections.abc as cabc +import json +import typing as t + +from .encoding import want_bytes +from .exc import BadPayload +from .exc import BadSignature +from .signer import _make_keys_list +from .signer import Signer + +if t.TYPE_CHECKING: + import typing_extensions as te + + # This should be either be str or bytes. To avoid having to specify the + # bound type, it falls back to a union if structural matching fails. + _TSerialized = te.TypeVar( + "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] + ) +else: + # Still available at runtime on Python < 3.13, but without the default. + _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) + + +class _PDataSerializer(t.Protocol[_TSerialized]): + def loads(self, payload: _TSerialized, /) -> t.Any: ... + # A signature with additional arguments is not handled correctly by type + # checkers right now, so an overload is used below for serializers that + # don't match this strict protocol. + def dumps(self, obj: t.Any, /) -> _TSerialized: ... + + +# Use TypeIs once it's available in typing_extensions or 3.13. +def is_text_serializer( + serializer: _PDataSerializer[t.Any], +) -> te.TypeGuard[_PDataSerializer[str]]: + """Checks whether a serializer generates text or binary.""" + return isinstance(serializer.dumps({}), str) + + +class Serializer(t.Generic[_TSerialized]): + """A serializer wraps a :class:`~itsdangerous.signer.Signer` to + enable serializing and securely signing data other than bytes. It + can unsign to verify that the data hasn't been changed. + + The serializer provides :meth:`dumps` and :meth:`loads`, similar to + :mod:`json`, and by default uses :mod:`json` internally to serialize + the data to bytes. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param serializer: An object that provides ``dumps`` and ``loads`` + methods for serializing data to a string. Defaults to + :attr:`default_serializer`, which defaults to :mod:`json`. + :param serializer_kwargs: Keyword arguments to pass when calling + ``serializer.dumps``. + :param signer: A ``Signer`` class to instantiate when signing data. + Defaults to :attr:`default_signer`, which defaults to + :class:`~itsdangerous.signer.Signer`. + :param signer_kwargs: Keyword arguments to pass when instantiating + the ``Signer`` class. + :param fallback_signers: List of signer parameters to try when + unsigning with the default signer fails. Each item can be a dict + of ``signer_kwargs``, a ``Signer`` class, or a tuple of + ``(signer, signer_kwargs)``. Defaults to + :attr:`default_fallback_signers`. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 2.0 + Removed the default SHA-512 fallback signer from + ``default_fallback_signers``. + + .. versionchanged:: 1.1 + Added support for ``fallback_signers`` and configured a default + SHA-512 fallback. This fallback is for users who used the yanked + 1.0.0 release which defaulted to SHA-512. + + .. versionchanged:: 0.14 + The ``signer`` and ``signer_kwargs`` parameters were added to + the constructor. + """ + + #: The default serialization module to use to serialize data to a + #: string internally. The default is :mod:`json`, but can be changed + #: to any object that provides ``dumps`` and ``loads`` methods. + default_serializer: _PDataSerializer[t.Any] = json + + #: The default ``Signer`` class to instantiate when signing data. + #: The default is :class:`itsdangerous.signer.Signer`. + default_signer: type[Signer] = Signer + + #: The default fallback signers to try when unsigning fails. + default_fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = [] + + # Serializer[str] if no data serializer is provided, or if it returns str. + @t.overload + def __init__( + self: Serializer[str], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: None | _PDataSerializer[str] = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer positional argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer keyword argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a positional argument. If the strict signature of + # _PDataSerializer doesn't match, fall back to a union, requiring the user + # to specify the type. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a keyword argument. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: t.Any | None = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + + if salt is not None: + salt = want_bytes(salt) + # if salt is None then the signer's default is used + + self.salt = salt + + if serializer is None: + serializer = self.default_serializer + + self.serializer: _PDataSerializer[_TSerialized] = serializer + self.is_text_serializer: bool = is_text_serializer(serializer) + + if signer is None: + signer = self.default_signer + + self.signer: type[Signer] = signer + self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} + + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers) + + self.fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = fallback_signers + self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def load_payload( + self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None + ) -> t.Any: + """Loads the encoded object. This function raises + :class:`.BadPayload` if the payload is not valid. The + ``serializer`` parameter can be used to override the serializer + stored on the class. The encoded ``payload`` should always be + bytes. + """ + if serializer is None: + use_serializer = self.serializer + is_text = self.is_text_serializer + else: + use_serializer = serializer + is_text = is_text_serializer(serializer) + + try: + if is_text: + return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] + + return use_serializer.loads(payload) # type: ignore[arg-type] + except Exception as e: + raise BadPayload( + "Could not load the payload because an exception" + " occurred on unserializing the data.", + original_error=e, + ) from e + + def dump_payload(self, obj: t.Any) -> bytes: + """Dumps the encoded object. The return value is always bytes. + If the internal serializer returns text, the value will be + encoded as UTF-8. + """ + return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) + + def make_signer(self, salt: str | bytes | None = None) -> Signer: + """Creates a new instance of the signer to be used. The default + implementation uses the :class:`.Signer` base class. + """ + if salt is None: + salt = self.salt + + return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) + + def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: + """Iterates over all signers to be tried for unsigning. Starts + with the configured signer, then constructs each signer + specified in ``fallback_signers``. + """ + if salt is None: + salt = self.salt + + yield self.make_signer(salt) + + for fallback in self.fallback_signers: + if isinstance(fallback, dict): + kwargs = fallback + fallback = self.signer + elif isinstance(fallback, tuple): + fallback, kwargs = fallback + else: + kwargs = self.signer_kwargs + + for secret_key in self.secret_keys: + yield fallback(secret_key, salt=salt, **kwargs) + + def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: + """Returns a signed string serialized with the internal + serializer. The return value can be either a byte or unicode + string depending on the format of the internal serializer. + """ + payload = want_bytes(self.dump_payload(obj)) + rv = self.make_signer(salt).sign(payload) + + if self.is_text_serializer: + return rv.decode("utf-8") # type: ignore[return-value] + + return rv # type: ignore[return-value] + + def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: + """Like :meth:`dumps` but dumps into a file. The file handle has + to be compatible with what the internal serializer expects. + """ + f.write(self.dumps(obj, salt)) + + def loads( + self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any + ) -> t.Any: + """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the + signature validation fails. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + return self.load_payload(signer.unsign(s)) + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: + """Like :meth:`loads` but loads from a file.""" + return self.loads(f.read(), salt) + + def loads_unsafe( + self, s: str | bytes, salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads` but without verifying the signature. This + is potentially very dangerous to use depending on how your + serializer works. The return value is ``(signature_valid, + payload)`` instead of just the payload. The first item will be a + boolean that indicates if the signature is valid. This function + never fails. + + Use it for debugging only and if you know that your serializer + module is not exploitable (for example, do not use it with a + pickle serializer). + + .. versionadded:: 0.15 + """ + return self._loads_unsafe_impl(s, salt) + + def _loads_unsafe_impl( + self, + s: str | bytes, + salt: str | bytes | None, + load_kwargs: dict[str, t.Any] | None = None, + load_payload_kwargs: dict[str, t.Any] | None = None, + ) -> tuple[bool, t.Any]: + """Low level helper function to implement :meth:`loads_unsafe` + in serializer subclasses. + """ + if load_kwargs is None: + load_kwargs = {} + + try: + return True, self.loads(s, salt=salt, **load_kwargs) + except BadSignature as e: + if e.payload is None: + return False, None + + if load_payload_kwargs is None: + load_payload_kwargs = {} + + try: + return ( + False, + self.load_payload(e.payload, **load_payload_kwargs), + ) + except BadPayload: + return False, None + + def load_unsafe( + self, f: t.IO[t.Any], salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads_unsafe` but loads from a file. + + .. versionadded:: 0.15 + """ + return self.loads_unsafe(f.read(), salt=salt) diff --git a/venv/lib/python3.12/site-packages/itsdangerous/signer.py b/venv/lib/python3.12/site-packages/itsdangerous/signer.py new file mode 100644 index 0000000..e324dc0 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/signer.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +import collections.abc as cabc +import hashlib +import hmac +import typing as t + +from .encoding import _base64_alphabet +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import want_bytes +from .exc import BadSignature + + +class SigningAlgorithm: + """Subclasses must implement :meth:`get_signature` to provide + signature generation functionality. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + """Returns the signature for the given key and value.""" + raise NotImplementedError() + + def verify_signature(self, key: bytes, value: bytes, sig: bytes) -> bool: + """Verifies the given signature matches the expected + signature. + """ + return hmac.compare_digest(sig, self.get_signature(key, value)) + + +class NoneAlgorithm(SigningAlgorithm): + """Provides an algorithm that does not perform any signing and + returns an empty signature. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + return b"" + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class HMACAlgorithm(SigningAlgorithm): + """Provides signature generation using HMACs.""" + + #: The digest method to use with the MAC algorithm. This defaults to + #: SHA1, but can be changed to any other function in the hashlib + #: module. + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + def __init__(self, digest_method: t.Any = None): + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + def get_signature(self, key: bytes, value: bytes) -> bytes: + mac = hmac.new(key, msg=value, digestmod=self.digest_method) + return mac.digest() + + +def _make_keys_list( + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], +) -> list[bytes]: + if isinstance(secret_key, (str, bytes)): + return [want_bytes(secret_key)] + + return [want_bytes(s) for s in secret_key] # pyright: ignore + + +class Signer: + """A signer securely signs bytes, then unsigns them to verify that + the value hasn't been changed. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param sep: Separator between the signature and value. + :param key_derivation: How to derive the signing key from the secret + key and salt. Possible values are ``concat``, ``django-concat``, + or ``hmac``. Defaults to :attr:`default_key_derivation`, which + defaults to ``django-concat``. + :param digest_method: Hash function to use when generating the HMAC + signature. Defaults to :attr:`default_digest_method`, which + defaults to :func:`hashlib.sha1`. Note that the security of the + hash alone doesn't apply when used intermediately in HMAC. + :param algorithm: A :class:`SigningAlgorithm` instance to use + instead of building a default :class:`HMACAlgorithm` with the + ``digest_method``. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 0.18 + ``algorithm`` was added as an argument to the class constructor. + + .. versionchanged:: 0.14 + ``key_derivation`` and ``digest_method`` were added as arguments + to the class constructor. + """ + + #: The default digest method to use for the signer. The default is + #: :func:`hashlib.sha1`, but can be changed to any :mod:`hashlib` or + #: compatible object. Note that the security of the hash alone + #: doesn't apply when used intermediately in HMAC. + #: + #: .. versionadded:: 0.14 + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + #: The default scheme to use to derive the signing key from the + #: secret key and salt. The default is ``django-concat``. Possible + #: values are ``concat``, ``django-concat``, and ``hmac``. + #: + #: .. versionadded:: 0.14 + default_key_derivation: str = "django-concat" + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous.Signer", + sep: str | bytes = b".", + key_derivation: str | None = None, + digest_method: t.Any | None = None, + algorithm: SigningAlgorithm | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + self.sep: bytes = want_bytes(sep) + + if self.sep in _base64_alphabet: + raise ValueError( + "The given separator cannot be used because it may be" + " contained in the signature itself. ASCII letters," + " digits, and '-_=' must not be used." + ) + + if salt is not None: + salt = want_bytes(salt) + else: + salt = b"itsdangerous.Signer" + + self.salt = salt + + if key_derivation is None: + key_derivation = self.default_key_derivation + + self.key_derivation: str = key_derivation + + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + if algorithm is None: + algorithm = HMACAlgorithm(self.digest_method) + + self.algorithm: SigningAlgorithm = algorithm + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def derive_key(self, secret_key: str | bytes | None = None) -> bytes: + """This method is called to derive the key. The default key + derivation choices can be overridden here. Key derivation is not + intended to be used as a security method to make a complex key + out of a short password. Instead you should use large random + secret keys. + + :param secret_key: A specific secret key to derive from. + Defaults to the last item in :attr:`secret_keys`. + + .. versionchanged:: 2.0 + Added the ``secret_key`` parameter. + """ + if secret_key is None: + secret_key = self.secret_keys[-1] + else: + secret_key = want_bytes(secret_key) + + if self.key_derivation == "concat": + return t.cast(bytes, self.digest_method(self.salt + secret_key).digest()) + elif self.key_derivation == "django-concat": + return t.cast( + bytes, self.digest_method(self.salt + b"signer" + secret_key).digest() + ) + elif self.key_derivation == "hmac": + mac = hmac.new(secret_key, digestmod=self.digest_method) + mac.update(self.salt) + return mac.digest() + elif self.key_derivation == "none": + return secret_key + else: + raise TypeError("Unknown key derivation method") + + def get_signature(self, value: str | bytes) -> bytes: + """Returns the signature for the given value.""" + value = want_bytes(value) + key = self.derive_key() + sig = self.algorithm.get_signature(key, value) + return base64_encode(sig) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string.""" + value = want_bytes(value) + return value + self.sep + self.get_signature(value) + + def verify_signature(self, value: str | bytes, sig: str | bytes) -> bool: + """Verifies the signature for the given value.""" + try: + sig = base64_decode(sig) + except Exception: + return False + + value = want_bytes(value) + + for secret_key in reversed(self.secret_keys): + key = self.derive_key(secret_key) + + if self.algorithm.verify_signature(key, value, sig): + return True + + return False + + def unsign(self, signed_value: str | bytes) -> bytes: + """Unsigns the given string.""" + signed_value = want_bytes(signed_value) + + if self.sep not in signed_value: + raise BadSignature(f"No {self.sep!r} found in value") + + value, sig = signed_value.rsplit(self.sep, 1) + + if self.verify_signature(value, sig): + return value + + raise BadSignature(f"Signature {sig!r} does not match", payload=value) + + def validate(self, signed_value: str | bytes) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid. + """ + try: + self.unsign(signed_value) + return True + except BadSignature: + return False diff --git a/venv/lib/python3.12/site-packages/itsdangerous/timed.py b/venv/lib/python3.12/site-packages/itsdangerous/timed.py new file mode 100644 index 0000000..7384375 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/timed.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import collections.abc as cabc +import time +import typing as t +from datetime import datetime +from datetime import timezone + +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import bytes_to_int +from .encoding import int_to_bytes +from .encoding import want_bytes +from .exc import BadSignature +from .exc import BadTimeSignature +from .exc import SignatureExpired +from .serializer import _TSerialized +from .serializer import Serializer +from .signer import Signer + + +class TimestampSigner(Signer): + """Works like the regular :class:`.Signer` but also records the time + of the signing and can be used to expire signatures. The + :meth:`unsign` method can raise :exc:`.SignatureExpired` if the + unsigning failed because the signature is expired. + """ + + def get_timestamp(self) -> int: + """Returns the current timestamp. The function must return an + integer. + """ + return int(time.time()) + + def timestamp_to_datetime(self, ts: int) -> datetime: + """Convert the timestamp from :meth:`get_timestamp` into an + aware :class`datetime.datetime` in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + return datetime.fromtimestamp(ts, tz=timezone.utc) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string and also attaches time information.""" + value = want_bytes(value) + timestamp = base64_encode(int_to_bytes(self.get_timestamp())) + sep = want_bytes(self.sep) + value = value + sep + timestamp + return value + sep + self.get_signature(value) + + # Ignore overlapping signatures check, return_timestamp is the only + # parameter that affects the return type. + + @t.overload + def unsign( # type: ignore[overload-overlap] + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[False] = False, + ) -> bytes: ... + + @t.overload + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[True] = True, + ) -> tuple[bytes, datetime]: ... + + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + ) -> tuple[bytes, datetime] | bytes: + """Works like the regular :meth:`.Signer.unsign` but can also + validate the time. See the base docstring of the class for + the general behavior. If ``return_timestamp`` is ``True`` the + timestamp of the signature will be returned as an aware + :class:`datetime.datetime` object in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + try: + result = super().unsign(signed_value) + sig_error = None + except BadSignature as e: + sig_error = e + result = e.payload or b"" + + sep = want_bytes(self.sep) + + # If there is no timestamp in the result there is something + # seriously wrong. In case there was a signature error, we raise + # that one directly, otherwise we have a weird situation in + # which we shouldn't have come except someone uses a time-based + # serializer on non-timestamp data, so catch that. + if sep not in result: + if sig_error: + raise sig_error + + raise BadTimeSignature("timestamp missing", payload=result) + + value, ts_bytes = result.rsplit(sep, 1) + ts_int: int | None = None + ts_dt: datetime | None = None + + try: + ts_int = bytes_to_int(base64_decode(ts_bytes)) + except Exception: + pass + + # Signature is *not* okay. Raise a proper error now that we have + # split the value and the timestamp. + if sig_error is not None: + if ts_int is not None: + try: + ts_dt = self.timestamp_to_datetime(ts_int) + except (ValueError, OSError, OverflowError) as exc: + # Windows raises OSError + # 32-bit raises OverflowError + raise BadTimeSignature( + "Malformed timestamp", payload=value + ) from exc + + raise BadTimeSignature(str(sig_error), payload=value, date_signed=ts_dt) + + # Signature was okay but the timestamp is actually not there or + # malformed. Should not happen, but we handle it anyway. + if ts_int is None: + raise BadTimeSignature("Malformed timestamp", payload=value) + + # Check timestamp is not older than max_age + if max_age is not None: + age = self.get_timestamp() - ts_int + + if age > max_age: + raise SignatureExpired( + f"Signature age {age} > {max_age} seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if age < 0: + raise SignatureExpired( + f"Signature age {age} < 0 seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if return_timestamp: + return value, self.timestamp_to_datetime(ts_int) + + return value + + def validate(self, signed_value: str | bytes, max_age: int | None = None) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid.""" + try: + self.unsign(signed_value, max_age=max_age) + return True + except BadSignature: + return False + + +class TimedSerializer(Serializer[_TSerialized]): + """Uses :class:`TimestampSigner` instead of the default + :class:`.Signer`. + """ + + default_signer: type[TimestampSigner] = TimestampSigner + + def iter_unsigners( + self, salt: str | bytes | None = None + ) -> cabc.Iterator[TimestampSigner]: + return t.cast("cabc.Iterator[TimestampSigner]", super().iter_unsigners(salt)) + + # TODO: Signature is incompatible because parameters were added + # before salt. + + def loads( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + salt: str | bytes | None = None, + ) -> t.Any: + """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the + signature validation fails. If a ``max_age`` is provided it will + ensure the signature is not older than that time in seconds. In + case the signature is outdated, :exc:`.SignatureExpired` is + raised. All arguments are forwarded to the signer's + :meth:`~TimestampSigner.unsign` method. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + base64d, timestamp = signer.unsign( + s, max_age=max_age, return_timestamp=True + ) + payload = self.load_payload(base64d) + + if return_timestamp: + return payload, timestamp + + return payload + except SignatureExpired: + # The signature was unsigned successfully but was + # expired. Do not try the next signer. + raise + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def loads_unsafe( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + salt: str | bytes | None = None, + ) -> tuple[bool, t.Any]: + return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/venv/lib/python3.12/site-packages/itsdangerous/url_safe.py b/venv/lib/python3.12/site-packages/itsdangerous/url_safe.py new file mode 100644 index 0000000..56a0793 --- /dev/null +++ b/venv/lib/python3.12/site-packages/itsdangerous/url_safe.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import typing as t +import zlib + +from ._json import _CompactJSON +from .encoding import base64_decode +from .encoding import base64_encode +from .exc import BadPayload +from .serializer import _PDataSerializer +from .serializer import Serializer +from .timed import TimedSerializer + + +class URLSafeSerializerMixin(Serializer[str]): + """Mixed in with a regular serializer it will attempt to zlib + compress the string to make it shorter if necessary. It will also + base64 encode the string so that it can safely be placed in a URL. + """ + + default_serializer: _PDataSerializer[str] = _CompactJSON + + def load_payload( + self, + payload: bytes, + *args: t.Any, + serializer: t.Any | None = None, + **kwargs: t.Any, + ) -> t.Any: + decompress = False + + if payload.startswith(b"."): + payload = payload[1:] + decompress = True + + try: + json = base64_decode(payload) + except Exception as e: + raise BadPayload( + "Could not base64 decode the payload because of an exception", + original_error=e, + ) from e + + if decompress: + try: + json = zlib.decompress(json) + except Exception as e: + raise BadPayload( + "Could not zlib decompress the payload before decoding the payload", + original_error=e, + ) from e + + return super().load_payload(json, *args, **kwargs) + + def dump_payload(self, obj: t.Any) -> bytes: + json = super().dump_payload(obj) + is_compressed = False + compressed = zlib.compress(json) + + if len(compressed) < (len(json) - 1): + json = compressed + is_compressed = True + + base64d = base64_encode(json) + + if is_compressed: + base64d = b"." + base64d + + return base64d + + +class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]): + """Works like :class:`.Serializer` but dumps and loads into a URL + safe string consisting of the upper and lowercase character of the + alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ + + +class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]): + """Works like :class:`.TimedSerializer` but dumps and loads into a + URL safe string consisting of the upper and lowercase character of + the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt new file mode 100644 index 0000000..c37cae4 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/METADATA b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/METADATA new file mode 100644 index 0000000..265cc32 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/METADATA @@ -0,0 +1,76 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 3.1.4 +Summary: A very fast and expressive template engine. +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Typing :: Typed +Requires-Dist: MarkupSafe>=2.0 +Requires-Dist: Babel>=2.7 ; extra == "i18n" +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/jinja/ +Provides-Extra: i18n + +# Jinja + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +## In A Nutshell + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} +

+ {% endblock %} + + +## Donate + +The Pallets organization develops and supports Jinja and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/RECORD b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/RECORD new file mode 100644 index 0000000..df3acaf --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/RECORD @@ -0,0 +1,57 @@ +jinja2-3.1.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2-3.1.4.dist-info/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +jinja2-3.1.4.dist-info/METADATA,sha256=R_brzpPQVBvpGcsm-WbrtgotO7suQ1D0F-qkhTzeEfY,2640 +jinja2-3.1.4.dist-info/RECORD,, +jinja2-3.1.4.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +jinja2-3.1.4.dist-info/entry_points.txt,sha256=OL85gYU1eD8cuPlikifFngXpeBjaxl6rIJ8KkC_3r-I,58 +jinja2/__init__.py,sha256=wIl45IM20KGw-kfr7jJhaBxxX5g4-kihlBYjxopX7Pw,1928 +jinja2/__pycache__/__init__.cpython-312.pyc,, +jinja2/__pycache__/_identifier.cpython-312.pyc,, +jinja2/__pycache__/async_utils.cpython-312.pyc,, +jinja2/__pycache__/bccache.cpython-312.pyc,, +jinja2/__pycache__/compiler.cpython-312.pyc,, +jinja2/__pycache__/constants.cpython-312.pyc,, +jinja2/__pycache__/debug.cpython-312.pyc,, +jinja2/__pycache__/defaults.cpython-312.pyc,, +jinja2/__pycache__/environment.cpython-312.pyc,, +jinja2/__pycache__/exceptions.cpython-312.pyc,, +jinja2/__pycache__/ext.cpython-312.pyc,, +jinja2/__pycache__/filters.cpython-312.pyc,, +jinja2/__pycache__/idtracking.cpython-312.pyc,, +jinja2/__pycache__/lexer.cpython-312.pyc,, +jinja2/__pycache__/loaders.cpython-312.pyc,, +jinja2/__pycache__/meta.cpython-312.pyc,, +jinja2/__pycache__/nativetypes.cpython-312.pyc,, +jinja2/__pycache__/nodes.cpython-312.pyc,, +jinja2/__pycache__/optimizer.cpython-312.pyc,, +jinja2/__pycache__/parser.cpython-312.pyc,, +jinja2/__pycache__/runtime.cpython-312.pyc,, +jinja2/__pycache__/sandbox.cpython-312.pyc,, +jinja2/__pycache__/tests.cpython-312.pyc,, +jinja2/__pycache__/utils.cpython-312.pyc,, +jinja2/__pycache__/visitor.cpython-312.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=JXKWCAXmTx0iZB4-hAsF50vgjxw_RJTjiLOlGGTBso0,2477 +jinja2/bccache.py,sha256=gh0qs9rulnXo0PhX5jTJy2UHzI8wFnQ63o_vw7nhzRg,14061 +jinja2/compiler.py,sha256=dpV-n6_iQUP4uSwlXwGUavJmwjvXdyxKzJ-AonFjPBk,72271 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=iWJ432RadxJNnaMOPrjIDInz50UEgni3_HKuFXi2vuQ,6299 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=xhFkmxO0CESA76Ki5tz4XWq9yzGu-t0p93JCCVBVNps,61538 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=igsBH7c6C0byHaOtMbE-ugpt4GjLGgR-ywskyXtKgq8,31877 +jinja2/filters.py,sha256=bKeqjFjjz88TkHVLSyyMIEB75CzAN6b3Airgx0phJDg,54611 +jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704 +jinja2/lexer.py,sha256=xnWWXhPndHFsoqzpc5VTjheDE9JuKk9MUo9DZkrM8Os,29754 +jinja2/loaders.py,sha256=ru0GIWHo5KiHJi7_MoI_LvGDoBBvP6rd0hiC1ReaTwk,23167 +jinja2/meta.py,sha256=OTDPkaFvU2Hgvx-6akz7154F8BIWaRmvJcBFvwopHww,4397 +jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 +jinja2/nodes.py,sha256=m1Duzcr6qhZI8JQ6VyJgUNinjAf5bQzijSmDnMsvUx8,34579 +jinja2/optimizer.py,sha256=rJnCRlQ7pZsEEmMhsQDgC_pKyDHxP5TPS6zVPGsgcu8,1651 +jinja2/parser.py,sha256=DV1iF1FR2Rsaj_5zl8rmx7j6Bj4S8iLHoYsvJ0bfEis,39890 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=POXT3tKNKJRENx2CymwUsOOXH2JwGPjW702njB5__cQ,33435 +jinja2/sandbox.py,sha256=TJjBNS9qRJ2ZgBMWdAgRBpyDLOHea2kT-2mk4PrjYx0,14616 +jinja2/tests.py,sha256=VLsBhVFnWg-PxSBz1MhRnNWgP1ovXk3neO1FLQMeC9Q,5926 +jinja2/utils.py,sha256=nV7IpWLvRCMyHW1irBAK8CIPAnOFfkb2ukggDBjbBEY,23952 +jinja2/visitor.py,sha256=EcnL1PIwf_4RVCOMxsRNuR8AXHbS1qfAdMOE2ngKJz4,3557 diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/WHEEL b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/entry_points.txt b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/entry_points.txt new file mode 100644 index 0000000..abc3eae --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2-3.1.4.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2=jinja2.ext:babel_extract[i18n] + diff --git a/venv/lib/python3.12/site-packages/jinja2/__init__.py b/venv/lib/python3.12/site-packages/jinja2/__init__.py new file mode 100644 index 0000000..2f0b5b2 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/__init__.py @@ -0,0 +1,38 @@ +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" + +from .bccache import BytecodeCache as BytecodeCache +from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache +from .environment import Environment as Environment +from .environment import Template as Template +from .exceptions import TemplateAssertionError as TemplateAssertionError +from .exceptions import TemplateError as TemplateError +from .exceptions import TemplateNotFound as TemplateNotFound +from .exceptions import TemplateRuntimeError as TemplateRuntimeError +from .exceptions import TemplatesNotFound as TemplatesNotFound +from .exceptions import TemplateSyntaxError as TemplateSyntaxError +from .exceptions import UndefinedError as UndefinedError +from .loaders import BaseLoader as BaseLoader +from .loaders import ChoiceLoader as ChoiceLoader +from .loaders import DictLoader as DictLoader +from .loaders import FileSystemLoader as FileSystemLoader +from .loaders import FunctionLoader as FunctionLoader +from .loaders import ModuleLoader as ModuleLoader +from .loaders import PackageLoader as PackageLoader +from .loaders import PrefixLoader as PrefixLoader +from .runtime import ChainableUndefined as ChainableUndefined +from .runtime import DebugUndefined as DebugUndefined +from .runtime import make_logging_undefined as make_logging_undefined +from .runtime import StrictUndefined as StrictUndefined +from .runtime import Undefined as Undefined +from .utils import clear_caches as clear_caches +from .utils import is_undefined as is_undefined +from .utils import pass_context as pass_context +from .utils import pass_environment as pass_environment +from .utils import pass_eval_context as pass_eval_context +from .utils import select_autoescape as select_autoescape + +__version__ = "3.1.4" diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f4e42481bab60d3d4cc17e182d2994b83288f5a GIT binary patch literal 1665 zcmZ9MNpIUm6vs!4Es0tz*;>4twv!faU=dlm1V{taThk&ojJg4exe#M=BGD#ih?$Wi z<<#E#4cf2JFVaiDfdB#pdg`G-i=daB`eqzTY6$6%-}}#-m2dc4wQ3=FKKk{qmp>K| z`a=illYIwozRw`^6Y>#8e#Xy+nJA018O=H19L^ce1Ltwx@LV_-&Et8)^S}jMFkA?W zQ3;m}7lAEo87={raoMm1T)`E?W#B5V8m<7>aLsTPcmXdMu7&lefg6SwfEV$i;X3dV zUNYPOZsMllMc@{08D0WzYAcpa}BUIE^~ z8-`bbH}R(7wQwu4v2A!AcpGmU-T>agJBBxbck!;_E#N!&j$s@4F1`!AjXxOe?Crk( z`RjmP5j&7Ju@#NtkSJT#bQ60c9e=$r&0y%}r!A>bPmMFKPWXWNkkm}QZw5>S5lwR&sV`@ems0b>99EiJd%=AA z5)R5w9qWKd`kWJ=>V;Ge`#kWbv2_%9YSLPt9>~P2oeY?#_cC!Rr`#We(=n>&#JeWF zsZlu>u!iBJ!{T9|1dLpUbh0{FO6`bV4tldrJ0jQA4S5f0rsu+;-0lQ&7cP{5h0Z3I zW`l|sQX*XQ#-!e6Aph6D5)&z1k26Jw3fk)?o~aV>8n@mJ31<=;l7`e%E*U6JrAK1= zdhTKOe)rMY-iPCY>-yYt-Era4GgFHkRGP?ZnFAS@XJ!!d+J=u98e4SeQB$;16t!E@ zqQ7*atfiu*s-*@pE`;XoNwJ`~+92bCxGf;j(blq-6)me;)Z2$&2@i4Z@@xtJ?90KwsaJ|A~Gg0igU!hfxc+c zIiuTI52pMNSrhBT literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/_identifier.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/_identifier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..322e03246f08df44b27161ae58160c42619effe6 GIT binary patch literal 2146 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/bccache.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/bccache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99741951e7e08f98d839d4a70aaca282702354cb GIT binary patch literal 19337 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 CV4@iS literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbdd774119804f85089739ab1443a4fafea60762 GIT binary patch literal 102270 zcmdSC33yvqb|#3G1PPD;_nicHf(x|oyF_ZSB+8a3FSJ!O#0N^GxcLE;M3}T?my;r0 zs+dYuBC5-dsEN~t#?F{dDxc}3CZ(E5C!U_98z89y3sFz2lIotMzsWSKl{58GESGM%<$Zatg zZW;tbr$I0Zrha3m3BTrk^MIw(Vx%xjzjYv`Gle}{`%?#Ooi_HI(w{bv-kHvxQ~T`$ zj?N7BZ0pY)aCSP`a~hsqoi0453-K`Rq9p&jpVq`1`?Cj1I!oAdPJih@S!Wr0&h0NBsOYR<&v|%u zce>eget+daRcDpa;5YRhmYYKT71LQ8)O6M&?SlTgf%?vRqrpVbPpVMzlTe88)AF18 zD-GTg`Z$(>eMIE;b+W;e~xyVnbaZr9%e_0u}uM&gTm`Zk8jUhkr_UK6w zb|BZ?Cc_bfu=5RruuB;udsx_Rgn5*(y)0}G!uI<2y>I4eb?#@O`w+U{U!{Z|V4(*P zdQcO3kcA#XXsiE_0^7<$+Ys8Ifo&T#d5(nE9~v4M?(O#n+=D{`?mgnrfIE26?;iGv z0l(<(9Sjb+pBxQd92#_Y1H${aRIGN7F`n5yG#K<>4G#DQeHZ*9g^UafzM#MBis&02 zW+ApSL9uu6!m(5MYVE%0>m9^HT5sTzfAq?bDBvZDA+qR*d~fYlwazZ(Sh?r{Q*2?K7HVH*NIaHTDuOMICkI+Lb8>R zCl8!HaI&qV?KDDNO6cjfGp9~G-If4(w!O9O@Uix`R)pHyF8lfq@hajq?bL9vcc3@K ztJU?SFAz8&UciSGG()#9NHN;cK2P@sdV{QV_O`*xz2eZ|fPXL;Hy-u^!g_vaWKam1 z_Us9nD)&4#?hTpt;%9frw0lq7)H@hT85|0t$vw8X$^TN^H0Y0;E(GJ23qgA8$5TI^ z#8R{nwNJ2jFmCLLr-=UGh&b3y4JTi;K+phsbPu<0&_aMkKrpLgyiY<__^e!lMX(Af zK`b2n>PwNI)L$WW?e9J56NVn6V0*(cZVaZ$@q$+QsgEsP@*DpRI^_2;qdXZV4f4|& zgD0&$ZVCANd*T^~(8NdlgMQJ6Mvhx(jKr-yqHh2{huKfcr7J%1LO`rVn%&YIV#!kx zO7Qn+3Af)c-ZYFEbkL6BwKHQTy~gQNnuVptZh<}eY4oM4F!IxwQ9oU|n&Xx+%b4-f zHiJRTMyh%#SjJ2;^ck#Plh!cBuj}tUziybJk4@eU8`mLU zf6Fj|T<{0h_4N++`8KZW<|s(?4v+HedqxJkLltr*Fu?*r@9zGgZeM?3ub0Y40A4B{ zEp7jB&9H1UI9zY-o!lF-*M|Kc4&EJ%dE4f_ZA%3uH($B&O01wMTF?}3ovr=Y`;m8{ z;K0Puht7iO&GXI*f(YFR%`}AD778{-TpNGlbWP<>1*gwOoh>sxxJ7I&kC2POlPcQr z6SuTo9TwxpVBCCQa8#sG5w~>v0zt8mfK05}#4UIZ&=h;oEp8@|jD*^VyAakwFi+z~ z6)>e+y-S&8%VzvOsBL_&^G+vwUfRBohaErhuebbfTiEkY)6(C{o6P%#6|kQb8XU!M zSKh9>RrhYz%+ZD7mhejp_6-rs25~FpYZ@9B8}J}D;g*0RXmTCVp_M0@mKfXG&#pL%ms zyfSHCWhUy(+RFy9OMiw5#!2&cO@iqi^ZODqH4>Ik&={*0yNwz35ScnZSv;LNESSDP z$_hHv-TUOv5;`Tbqz zdk2Sx8-NXn>S%U9HsR0M@YsmE$CDbjYa+zc0=_}v{Lodu5YGk);}^UA!$H5m(+I?^ zS41EpaU&WSYpTB|7`KYO7cK_xT9R?%Zh!=65D^OGQ#qBP&ml2X+BM+2ZVZZx}73>jH5M`_ei8gtamJLYr` z+BY@2=%`eo2n%jmL=rZ~Tj`VOQ=7i!WGKXAVc3czztn@hgM|MWI=O2Ssd>aFsH$3I zXV)~0coJXt5Cp-ZF&%39+?d(ISg{y zZE)mVYiFhT{|5>?`sGpB6JHXAZCqs{{Sr~w;QCeaFi)C8=uCCW0`8ZIBrR&nKnB+K zP=#i0b7U}*fD6QZD2}+FZU=D#X>*94TXBnLY3Dyh3y6p5BTarz{2aqm;v8o~I#j}k zF~wOiz0XpdG2Aes*PPyGq8rXco6acHd;47WT*}<}NWpC-o^ zE;`&v5I_KH&d;>7gFbOonW5qdDyDX7rmJ-lNyb5c0m4o`2wT}@|@^$TMuYX_LKr5$?qG8rwjfbzu46~ z*c((yRiRtET-p$y5hsgy0BNG|He-h1nq-MgAP4M0B|X6?kEho`lIV}rG1HhC1h{o9 z<$Z~)8BZNc?IVgW=^E3Hd&{+AK+jW+XpL+(Sq!TKOraK^3U%b+_b@x`2TZwJ$u4!Rz+vTv~4&(XC_=AGkd z9izj3#yH1wiI4BPAahY&-Th!@`E;OB9k*TZ2f;Lq_&qjFkDkFNv4d^|Bof^!K7(64 zO-U(0y@qv?U3{%XT8vpkcjKEMe}Nv{FxGMnj{GU%?Y7(Px7ru&O%E~)B858_GIvF6 zyB@kqVy^X3*ZL(}&Q!J?fAz;&vvk`-6 z95t#utU3Zz5;#a{vMZ=?xGG;8%v8R*l&5U@>0&BK($#Xvm7#+9$`f%K>qfZ3GWFG`O!Lp>K%R+JwJHgrAQajI4joVKzaYpke`K zM*pVqrqO7)o@FtN8h+P&#V8V6c-I)uxabRXQEpw7o5vJ4dDq8{ml-Z}bDr#R+HM-1 zpl0@lP(BT~itQDMUq!M3>Vdx@Oc}}EboXr7_?IZq#Btg=LWHTA5H+v70Jv7HMw9jh954UI9X#n1yT(iWl(m z`4ya`c=fnR6+H99bDwm~J#~*&av`UBK4<#}8MD5HhV2VE+kbdYs&Q?-@vtW=p4mPW zJO(M9pM(LRxovIz{k_A1-ayb&(GYQKa0DMfmiGq0V+Z_LBOsIv`3LFI3`QVs5qi6k5GeS8z+I#GB9)wmhE!hx zk0Ra1>BH-|T{ApPbzB>tw!T{)EnGLd<@-mYn_8EgIX_LcPqcmg`UNKxXKWDgN^cX|m zIdswAeaYS1!{;^C19D=BWd*lS#Psg&_OllVIsI5wM8Dv5yE}jaxP;QpFmXC954{1m z&y5as5B0dwr7S%)mYX$^DvJ*IUmEdaQ6p&S6A4niEGfvl^3Ez5wxdvz43@KZcImC{ zDyWTgH4m^gw782z!!dG?t#vXP$cIwg+0#2Hbg7ZV*8u%%_zTd|hgHmBaMsMUEo3%c zJF;xDSTp`Iw`ihu$&vHc$;p$`HTNAAKQkNhib*_`6SJ2^?PU>5**|<{H8=`>ZZKLi zmTZnCd$#gr*^02o0U{l~Rk+dcdua#K%s;dlaqmWua?x<1>(P1KZemsKG-96*`+I(K zpRx=w2zK*Z^#~M%DvOc|%XgMYRE!-H3-&H-qh^maZaeAg7KcvzdpJQrvYYmV5lo|* zjo{sQz=~=dGth$1FM-|^+|AyU(a+wLu{>(HYid7?uJIsd+$jyHKo{} z0&&?VlGqn4Dd8~Qmz0Tw1mm_YMsId?g|g(jc;%qq0$iXHw`+!_+`Kafv{>t=pSu0bt!HM=zW4l{=OM*h z_tCmY?SW|7!DRzJ-UCsNAD#{+(TzXlBBV;!qY2!!qovc#_WK-y*^j=~A0>i;?SWbK zzxq?z*A(nX+Jsc>!P$fii2f~|X+oxu=1&(=AQ!X<>G)#D7dyT<{AryTAb*`qf)J`Z zI@B)&6tWguEPm{NfchO^v;m`oM*`kAfbk{^2`M9D62wuA!0O@JO($o7RnZ%K4EVFn-tuqtPF? z1&6TEqa)*K;?Pi#Kc@E&4Gnkk9UVJ^lU~vTLp?$M4E(?*IgJUPJC!F9b+fq@%4B;& z%0v$n*ze#5p50+6s>D>!06$Ssh6npYd)CC>2PIYEyv34r6Rp=z0Bd`^6RnGmS^zh% zN6>KqH{sj2o&c*{T0OJ%y}ft#&H;WO!7nvcImBB zJU)R0ipp8G>4xG8JY*u55;q>4OZ2m7D_l-z0h07Bfu5vs$;S7e<3TI1*QEvwdSd(c zB|J>Rc|F=dmpeA-LCPsHQMWQ)P%!E0qal%W$y~#jQJqI@lfW3NJOtT5ka&ddq2W4|sf9uaBAyN3q-UdVV;hR*l-LHnfw|6&`cE1uTH*;hOQClg(Wrxd;qE#5@#*qcFe z(y|aYi3uEl_|E|mO6P-w;QkWtfkU`mGyF6o=dG_zer>vy7}SM~rU}!ME&VO~q&;RU zj@pW+H{afKYtN$1vy@kK^MxBP#PaH*d36hU4HKs8=}XS6i8O|eS#4M3OGOjuDI`oclo8F#yY_EWSuZS$gF(2$jf)3HvqX zQ2uGQq3rez0vCgQ2O);V&MQ(Ui@%8*CLpa%eEL%>GlYP>FE%ajB0$S$fl{YbLU!KH z?B%ZrW-D&j3_r2wJjf}W&b?iBt1K*h*nhV_=G`Cl?!UJo>TO-jX^S}89yoKSI&Pl3 zac-t{!Rd+EJgjXKrUuoDwdg@S5KG^u)ENQNB@e%GBghV;h9oiJO=%Z4AkDryBp^40 zn~;yx3~u)U&8vIBHwq3n=sxdvgAnNL=_O(~z$jB9bV(W``1&z^F`l6cfp6~KpgV98 zD;Z~x@yldB0r!>O;6*m-S$hLaN#zP+b+h>)U}iMC&yPS&AXraI8$rw%1%2`&qT@#0 z$P!u^-gG66j*B3=@qcKrf7CrfG&?jqdS#{!M12d&3YH4f4aE7NfO$A5^b&{e>sJyX zZW%N_0t1}-raB((@R-?D65mEci?`|a9&QPPz(P$Z&oz4f8-l394anGK$jpB0xyk3g z`8=jsK`G{tW2umSGSsQ$F}1g2h!O3{cOSrcW{TgW*Xwlq7H)(XgrV-PE|G*QoCLFx z<_1+l9HOu{=|=Nj9Hbi!3GsJvBm6-q0C8_n7!6L&KeM4uH(EIY6zdJck1gwgr|X-R zDr00CPUNJldmolFk+@>KC<&sg@qc;$gSaKnaF&xlA(I++~rX&SKWGaJEBxy?Opj{Z_lFCR> zN=K2Nt$-mi)ehz+Jzmi2ANGTR9PA!F40g{iN*rUzd%!Ji=Aq?$Bzy%I(v8^xi8gi* z*(3@21NZ=nKHz0Tvt1u6?Pt|h@h}ZLx

ovFdnny(608Z|J{7JBzG;>A;W8L*W} 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 HFqry(M2A%e literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/constants.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/constants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eaad64bdb447567547f963d6f38194fa978bf2c4 GIT binary patch literal 1568 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2383978577c16e0d0cfb03985728f9f5a575d535 GIT binary patch literal 1618 zcmah}%WoS+7@zeke#DNSc{u5tG?+HFS`Y%MrE;B3W8yez;_z6Cmc=tkH(BqR*>Q`v zs;IbdZB8jtrRK^%!i9@bFROt{NC=@EkW!UXPkgiWl5%2qJ>PGB^ZVxe=9?M+luX7E zJa7H@*Vc;=LcfcS|HOvi#TODn`)Ctkge3zh5)R;?5$FV!kc0q-jBqESjCeR~L_0Ah z=HUq7xDxm92;hX0@Ng9Hs4^-cBJC9YV8@n*yf`Uk49Ao-jw>0QP_lSb$>F4u$0?OUHd5Z3TvzPK#K5sWfvahMI>^ zYgCf>$YQ^UcJ?mjOx>P=bQXjNPCirj3eYwPl2{S%(^=-TSaYvkff zDejzPq}YR5P~;4`IE{c*OAX zjF(;=9r7v#n2W&+Njs+@EpjtMCi-q`@FCK0z4>Mvjn|jMk`h(t9^Kg&phD{^jM@K{x6^*!$JlXnmO;&45 za&5WZyumZC!l{rOF>T1)<^e`{_IhKrwk-B`y#?*MkfvX8a&y6F3LjP1>(%QG?+_dd zbN|w>Y4iSp_|KeKpFLJm@rS~rt6fn?&EP@UB|fIAnrT{06Qr%GG$BL@NNh#*(%Rt3 zhRAbm*riD!C@jnJn%Y{g*5O>;P>1J>reKVY2|>oMTeG?%Z>&{oGMx~7XhEE}VAbsZ zfL;KBUbZWnHta=(ksS@L1=P2)V6}T4VlunZBOX%!T1dSI5DC_1X1}N=L&J0k&6->^Z zm>!_KTbL4~rFq~VezouHIS1$VzIlq~-MI@OdU$hR*;5XJd+Jkk!A<2JB;0i2LDGHy zD$F*>zWWqibtg}N?@=73a_(r_O`Ua9dGTe6&yypCzyM{A#?kaCH#-Bd+?mtv#H0(| u;_Lw%OkD);=b6}>AWJ_yvwwc?{G;3>?FspwJSzU2edBKwlLGWIto0ws`qLT! literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/environment.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/environment.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae261dfb1a924648bc3d2176b3de7ed76ac00c4b GIT binary patch literal 76714 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 Vs*1Y#BqkAU^wQb=CB2Ai|35b@rIi2x literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/ext.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/ext.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57d7f543c3a9bf5245fc64c8b50511ee06dabc8c GIT binary patch literal 41880 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 S|Dt%#f~il_=bB4SMg9laTPgnl literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60f360561d2acbf1429687ddff267746e1f8d172 GIT binary patch literal 19161 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 Z_ytGquUAh)u-(Nhrv9qRezM!}{{taMyx9N% literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da911e7dda02dd629fa0d9de5b21779e53793e05 GIT binary patch literal 30975 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/meta.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/meta.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab85c7a156dd01813c1c303e53fee6957a153a57 GIT binary patch literal 5482 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37f153dc7e27f20ed167b87fdd62ec6408c4d0e4 GIT binary patch literal 7031 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Ν>F7x4w>!u~# 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/parser.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4efa99d07fbd13ff6a4abcd600fd1d9c26d86ed8 GIT binary patch literal 60823 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7cff0bc5ba7d08b8aef2c57df2d18078f26c1ca GIT binary patch literal 48504 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%0A|_Tk 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/sandbox.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/sandbox.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60bb9062ca1671cd4bf4507d468b56b910cbb90e GIT binary patch literal 17902 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 AUjP6A literal 0 HcmV?d00001 diff --git a/venv/lib/python3.12/site-packages/jinja2/__pycache__/utils.cpython-312.pyc b/venv/lib/python3.12/site-packages/jinja2/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db8b92e13bc0052e07c4974abce56b3593d03015 GIT binary patch literal 34483 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 bool: + return t.cast(bool, args[0].is_async) + + else: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].environment.is_async) + + # Take the doc and annotations from the sync function, but the + # name from the async function. Pallets-Sphinx-Themes + # build_function_directive expects __wrapped__ to point to the + # sync function. + async_func_attrs = ("__module__", "__name__", "__qualname__") + normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs)) + + @wraps(normal_func, assigned=normal_func_attrs) + @wraps(async_func, assigned=async_func_attrs, updated=()) + def wrapper(*args, **kwargs): # type: ignore + b = is_async(args) + + if need_eval_context: + args = args[1:] + + if b: + return async_func(*args, **kwargs) + + return normal_func(*args, **kwargs) + + if need_eval_context: + wrapper = pass_eval_context(wrapper) + + wrapper.jinja_async_variant = True # type: ignore[attr-defined] + return wrapper + + return decorator + + +_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)} + + +async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": + # Avoid a costly call to isawaitable + if type(value) in _common_primitives: + return t.cast("V", value) + + if inspect.isawaitable(value): + return await t.cast("t.Awaitable[V]", value) + + return t.cast("V", value) + + +async def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + async for item in t.cast("t.AsyncIterable[V]", iterable): + yield item + else: + for item in iterable: + yield item + + +async def auto_to_list( + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> t.List["V"]: + return [x async for x in auto_aiter(value)] diff --git a/venv/lib/python3.12/site-packages/jinja2/bccache.py b/venv/lib/python3.12/site-packages/jinja2/bccache.py new file mode 100644 index 0000000..ada8b09 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/bccache.py @@ -0,0 +1,408 @@ +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" + +import errno +import fnmatch +import marshal +import os +import pickle +import stat +import sys +import tempfile +import typing as t +from hashlib import sha1 +from io import BytesIO +from types import CodeType + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + + class _MemcachedClient(te.Protocol): + def get(self, key: str) -> bytes: ... + + def set( + self, key: str, value: bytes, timeout: t.Optional[int] = None + ) -> None: ... + + +bc_version = 5 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket: + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment: "Environment", key: str, checksum: str) -> None: + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self) -> None: + """Resets the bucket (unloads the bytecode).""" + self.code: t.Optional[CodeType] = None + + def load_bytecode(self, f: t.BinaryIO) -> None: + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal.load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f: t.IO[bytes]) -> None: + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal.dump(self.code, f) + + def bytecode_from_string(self, string: bytes) -> None: + """Load bytecode from bytes.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self) -> bytes: + """Return the bytecode as bytes.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache: + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self) -> None: + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key( + self, name: str, filename: t.Optional[t.Union[str]] = None + ) -> str: + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + + if filename is not None: + hash.update(f"|{filename}".encode()) + + return hash.hexdigest() + + def get_source_checksum(self, source: str) -> str: + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket( + self, + environment: "Environment", + name: str, + filename: t.Optional[str], + source: str, + ) -> Bucket: + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket: Bucket) -> None: + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__( + self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" + ) -> None: + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self) -> str: + def _unsafe_dir() -> "te.NoReturn": + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = f"_jinja2-cache-{os.getuid()}" + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket: Bucket) -> str: + return os.path.join(self.directory, self.pattern % (bucket.key,)) + + def load_bytecode(self, bucket: Bucket) -> None: + filename = self._get_cache_filename(bucket) + + # Don't test for existence before opening the file, since the + # file could disappear after the test before the open. + try: + f = open(filename, "rb") + except (FileNotFoundError, IsADirectoryError, PermissionError): + # PermissionError can occur on Windows when an operation is + # in progress, such as calling clear(). + return + + with f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket: Bucket) -> None: + # Write to a temporary file, then rename to the real name after + # writing. This avoids another process reading the file before + # it is fully written. + name = self._get_cache_filename(bucket) + f = tempfile.NamedTemporaryFile( + mode="wb", + dir=os.path.dirname(name), + prefix=os.path.basename(name), + suffix=".tmp", + delete=False, + ) + + def remove_silent() -> None: + try: + os.remove(f.name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + pass + + try: + with f: + bucket.write_bytecode(f) + except BaseException: + remove_silent() + raise + + try: + os.replace(f.name, name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + remove_silent() + except BaseException: + remove_silent() + raise + + def clear(self) -> None: + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) + for filename in files: + try: + remove(os.path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only text. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client: "_MemcachedClient", + prefix: str = "jinja2/bytecode/", + timeout: t.Optional[int] = None, + ignore_memcache_errors: bool = True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket: Bucket) -> None: + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + else: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket: Bucket) -> None: + key = self.prefix + bucket.key + value = bucket.bytecode_to_string() + + try: + if self.timeout is not None: + self.client.set(key, value, self.timeout) + else: + self.client.set(key, value) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/venv/lib/python3.12/site-packages/jinja2/compiler.py b/venv/lib/python3.12/site-packages/jinja2/compiler.py new file mode 100644 index 0000000..2740717 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/compiler.py @@ -0,0 +1,1960 @@ +"""Compiles nodes from the parser into Python code.""" + +import typing as t +from contextlib import contextmanager +from functools import update_wrapper +from io import StringIO +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import _PassArg +from .utils import concat +from .visitor import NodeVisitor + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + + +def optimizeconst(f: F) -> F: + def new_func( + self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any + ) -> t.Any: + # Only optimize if the frame is not volatile + if self.optimizer is not None and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + + if new_node != node: + return self.visit(new_node, frame) + + return f(self, node, frame, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor + + +def generate( + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + + if stream is None: + return generator.stream.getvalue() # type: ignore + + return None + + +def has_safe_repr(value: t.Any) -> bool: + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + + if type(value) in {bool, int, float, complex, range, str, Markup}: + return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: # noqa E721 + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + + return False + + +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame: + """Holds compile time information for us.""" + + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: + self.eval_ctx = eval_ctx + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False + + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False + + def copy(self) -> "Frame": + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated: bool = False) -> "Frame": + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self) -> "Frame": + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements and conditional + expressions. + """ + rv = self.copy() + rv.rootlevel = False + rv.soft_frame = True + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self) -> None: + self.filters: t.Set[str] = set() + self.tests: t.Set[str] = set() + + def visit_Filter(self, node: nodes.Filter) -> None: + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node: nodes.Test) -> None: + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names: t.Iterable[str]) -> None: + self.names = set(names) + self.undeclared: t.Set[str] = set() + + def visit_Name(self, node: nodes.Name) -> None: + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, + ) -> None: + if stream is None: + stream = StringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimizer: t.Optional[Optimizer] = None + + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases: t.Dict[str, str] = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks: t.Dict[str, nodes.Block] = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests: t.Dict[str, str] = {} + self.filters: t.Dict[str, str] = {} + + # the debug information + self.debug_info: t.List[t.Tuple[int, int]] = [] + self._write_debug_info: t.Optional[int] = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack: t.List[t.Set[str]] = [] + + # Tracks parameter definition blocks + self._param_def_block: t.List[t.Set[str]] = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + @property + def optimized(self) -> bool: + return self.optimizer is not None + + # -- Various compilation helpers + + def fail(self, msg: str, lineno: int) -> "te.NoReturn": + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self) -> str: + """Get a new unique identifier.""" + self._last_identifier += 1 + return f"t_{self._last_identifier}" + + def buffer(self, frame: Frame) -> None: + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline(f"{frame.buffer} = []") + + def return_buffer_contents( + self, frame: Frame, force_unescaped: bool = False + ) -> None: + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline(f"return Markup(concat({frame.buffer}))") + self.outdent() + self.writeline("else:") + self.indent() + self.writeline(f"return concat({frame.buffer})") + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline(f"return Markup(concat({frame.buffer}))") + return + self.writeline(f"return concat({frame.buffer})") + + def indent(self) -> None: + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step: int = 1) -> None: + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None: + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline(f"{frame.buffer}.append(", node) + + def end_write(self, frame: Frame) -> None: + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write( + self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None + ) -> None: + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x: str) -> None: + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline( + self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 + ) -> None: + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature( + self, + node: t.Union[nodes.Call, nodes.Filter, nodes.Test], + frame: Frame, + extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + ) -> None: + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = any( + is_python_keyword(t.cast(str, k)) + for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) + ) + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f", {key}={value}") + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write(f"{kwarg.key!r}: ") + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f"{key!r}: {value}, ") + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: + """Find all filter and test names used in the template and + assign them to variables in the compiled namespace. Checking + that the names are registered with the environment is done when + compiling the Filter and Test nodes. If the node is in an If or + CondExpr node, the check is done at runtime instead. + + .. versionchanged:: 3.0 + Filters and tests in If and CondExpr nodes are checked at + runtime instead of compile time. + """ + visitor = DependencyFinderVisitor() + + for node in nodes: + visitor.visit(node) + + for id_map, names, dependency in ( + (self.filters, visitor.filters, "filters"), + ( + self.tests, + visitor.tests, + "tests", + ), + ): + for name in sorted(names): + if name not in id_map: + id_map[name] = self.temporary_identifier() + + # add check during runtime that dependencies used inside of executed + # blocks are defined, as this step may be skipped during compile time + self.writeline("try:") + self.indent() + self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") + self.outdent() + self.writeline("except KeyError:") + self.indent() + self.writeline("@internalcode") + self.writeline(f"def {id_map[name]}(*unused):") + self.indent() + self.writeline( + f'raise TemplateRuntimeError("No {dependency[:-1]}' + f' named {name!r} found.")' + ) + self.outdent() + self.outdent() + + def enter_frame(self, frame: Frame) -> None: + undefs = [] + for target, (action, param) in frame.symbols.loads.items(): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") + elif action == VAR_LOAD_ALIAS: + self.writeline(f"{target} = {param}") + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: + if not with_python_scope: + undefs = [] + for target in frame.symbols.loads: + undefs.append(target) + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: + return async_value if self.environment.is_async else sync_value + + def func(self, name: str) -> str: + return f"{self.choose_async()}def {name}" + + def macro_body( + self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame + ) -> t.Tuple[Frame, MacroRef]: + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline(f"{self.func('macro')}({', '.join(args)}):", node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline(f"if {ref} is missing:") + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + f'{ref} = undefined("parameter {arg.name!r} was not provided",' + f" name={arg.name!r})" + ) + else: + self.writeline(f"{ref} = ") + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + f"Macro(environment, macro, {name!r}, ({arg_tuple})," + f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," + f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" + ) + + def position(self, node: nodes.Node) -> str: + """Return a human readable position for the node.""" + rv = f"line {node.lineno}" + if self.name is not None: + rv = f"{rv} in {self.name!r}" + return rv + + def dump_local_context(self, frame: Frame) -> str: + items_kv = ", ".join( + f"{name!r}: {target}" + for name, target in frame.symbols.dump_stores().items() + ) + return f"{{{items_kv}}}" + + def write_commons(self) -> None: + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + self.writeline("concat = environment.concat") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame: Frame) -> None: + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self) -> None: + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target: str) -> None: + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target: str) -> None: + self._context_reference_stack.append(target) + + def pop_context_reference(self) -> None: + self._context_reference_stack.pop() + + def get_context_ref(self) -> str: + return self._context_reference_stack[-1] + + def get_resolve_func(self) -> str: + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return f"{target}.resolve" + + def derive_context(self, frame: Frame) -> str: + return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" + + def parameter_is_undeclared(self, target: str) -> bool: + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self) -> None: + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame: Frame) -> None: + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if ( + not frame.block_frame + and not frame.loop_frame + and not frame.toplevel + or not vars + ): + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + if frame.loop_frame: + self.writeline(f"_loop_vars[{name!r}] = {ref}") + return + if frame.block_frame: + self.writeline(f"_block_vars[{name!r}] = {ref}") + return + self.writeline(f"context.vars[{name!r}] = {ref}") + else: + if frame.loop_frame: + self.writeline("_loop_vars.update({") + elif frame.block_frame: + self.writeline("_block_vars.update({") + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(vars): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write(f"{name!r}: {ref}") + self.write("})") + if not frame.block_frame and not frame.loop_frame and public_names: + if len(public_names) == 1: + self.writeline(f"context.exported_vars.add({public_names[0]!r})") + else: + names_str = ", ".join(map(repr, public_names)) + self.writeline(f"context.exported_vars.update(({names_str}))") + + # -- Statement Visitors + + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> None: + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import async_exported + from .runtime import exported + + if self.environment.is_async: + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = "" if self.defer_init else ", environment=environment" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail(f"block {block.name!r} defined twice", block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline(f"from {module} import {obj} as {alias}") + else: + self.writeline(f"import {imp} as {alias}") + + # add the load name + self.writeline(f"name = {self.name!r}") + + # generate the root render function. + self.writeline( + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline( + "async for event in parent_template.root_render_func(context):" + ) + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in self.blocks.items(): + self.writeline( + f"{self.func('block_' + name)}(context, missing=missing{envenv}):", + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + block_frame.block_frame = True + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline(f"{ref} = context.super({name!r}, block_{name})") + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.writeline("_block_vars = {}") + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) + self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) + debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) + self.writeline(f"debug_info = {debug_kv_str!r}") + + def visit_Block(self, node: nodes.Block, frame: Frame) -> None: + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if node.required: + self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) + self.indent() + self.writeline( + f'raise TemplateRuntimeError("Required block {node.name!r} not found")', + node, + ) + self.outdent() + + if not self.environment.is_async and frame.buffer is None: + self.writeline( + f"yield from context.blocks[{node.name!r}][0]({context})", node + ) + else: + self.writeline( + f"{self.choose_async()}for event in" + f" context.blocks[{node.name!r}][0]({context}):", + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + + self.outdent(level) + + def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline('raise TemplateRuntimeError("extended multiple times")') + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + self.writeline("for name, parent_block in parent_template.blocks.items():") + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node: nodes.Include, frame: Frame) -> None: + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, str): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline(f"template = environment.{func_name}(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + skip_event_yield = False + if node.with_context: + self.writeline( + f"{self.choose_async()}for event in template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)})):" + ) + elif self.environment.is_async: + self.writeline( + "for event in (await template._get_default_module_async())" + "._body_stream:" + ) + else: + self.writeline("yield from template._get_default_module()._body_stream") + skip_event_yield = True + + if not skip_event_yield: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.ignore_missing: + self.outdent() + + def _import_common( + self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame + ) -> None: + self.write(f"{self.choose_async('await ')}environment.get_template(") + self.visit(node.template, frame) + self.write(f", {self.name!r}).") + + if node.with_context: + f_name = f"make_module{self.choose_async('_async')}" + self.write( + f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})" + ) + else: + self.write(f"_get_default_module{self.choose_async('_async')}(context)") + + def visit_Import(self, node: nodes.Import, frame: Frame) -> None: + """Visit regular imports.""" + self.writeline(f"{frame.symbols.ref(node.target)} = ", node) + if frame.toplevel: + self.write(f"context.vars[{node.target!r}] = ") + + self._import_common(node, frame) + + if frame.toplevel and not node.target.startswith("_"): + self.writeline(f"context.exported_vars.discard({node.target!r})") + + def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: + """Visit named imports.""" + self.newline(node) + self.write("included_template = ") + self._import_common(node, frame) + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + f"{frame.symbols.ref(alias)} =" + f" getattr(included_template, {name!r}, missing)" + ) + self.writeline(f"if {frame.symbols.ref(alias)} is missing:") + self.indent() + message = ( + "the template {included_template.__name__!r}" + f" (imported on {self.position(node)})" + f" does not export the requested name {name!r}" + ) + self.writeline( + f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") + else: + names_kv = ", ".join( + f"{name!r}: {frame.symbols.ref(name)}" for name in var_names + ) + self.writeline(f"context.vars.update({{{names_kv}}})") + if discarded_names: + if len(discarded_names) == 1: + self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") + else: + names_str = ", ".join(map(repr, discarded_names)) + self.writeline( + f"context.exported_vars.difference_update(({names_str}))" + ) + + def visit_For(self, node: nodes.For, frame: Frame) -> None: + loop_frame = frame.inner() + loop_frame.loop_frame = True + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body if the body is a scoped block. + extended_loop = ( + node.recursive + or "loop" + in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) + or any(block.scoped for block in node.find_all(nodes.Block)) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.choose_async("async for ", "for ")) + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.choose_async("auto_aiter(fiter)", "fiter")) + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline(f"{loop_ref} = missing") + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline(f"{iteration_indicator} = 1") + + self.writeline(self.choose_async("async for ", "for "), node) + self.visit(node.target, loop_frame) + if extended_loop: + self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") + else: + self.write(" in ") + + if node.test: + self.write(f"{loop_filter_func}(") + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(", undefined):" if extended_loop else ":") + + self.indent() + self.enter_frame(loop_frame) + + self.writeline("_loop_vars = {}") + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline(f"{iteration_indicator} = 0") + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline(f"if {iteration_indicator}:") + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + self.write(f"{self.choose_async('await ')}loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + # at the end of the iteration, clear any assignments made in the + # loop from the top level + if self._assign_stack: + self._assign_stack[-1].difference_update(loop_frame.symbols.stores) + + def visit_If(self, node: nodes.If, frame: Frame) -> None: + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write(f"context.exported_vars.add({node.name!r})") + self.writeline(f"context.vars[{node.name!r}] = ") + self.write(f"{frame.symbols.ref(node.name)} = ") + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node: nodes.With, frame: Frame) -> None: + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in zip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: + self.newline(node) + self.visit(node.node, frame) + + class _FinalizeInfo(t.NamedTuple): + const: t.Optional[t.Callable[..., str]] + src: t.Optional[str] + + @staticmethod + def _default_finalize(value: t.Any) -> t.Any: + """The default finalize function if the environment isn't + configured with one. Or, if the environment has one, this is + called on that function's output for constants. + """ + return str(value) + + _finalize: t.Optional[_FinalizeInfo] = None + + def _make_finalize(self) -> _FinalizeInfo: + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize: t.Optional[t.Callable[..., t.Any]] + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(env_finalize) # type: ignore + ) + finalize = None + + if pass_arg is None: + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(value)) + + else: + src = f"{src}{pass_arg}, " + + if pass_arg == "environment": + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> str: + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return str(const) + + return finalize.const(const) # type: ignore + + def _output_child_pre( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else str)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("str(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node: nodes.Output, frame: Frame) -> None: + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline(f"{frame.buffer}.append(") + else: + self.writeline(f"{frame.buffer}.extend((") + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: + self.push_assign_tracking() + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write(f"concat({block_frame.buffer})") + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node: nodes.Name, frame: Frame) -> None: + if node.ctx == "store" and ( + frame.toplevel or frame.loop_frame or frame.block_frame + ): + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" + ) + return + + self.write(ref) + + def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: + # NSRefs can only be used to store values; since they use the normal + # `foo.bar` notation they will be parsed as a normal attribute access + # when used anywhere but in a `set` context + ref = frame.symbols.ref(node.name) + self.writeline(f"if not isinstance({ref}, Namespace):") + self.indent() + self.writeline( + "raise TemplateRuntimeError" + '("cannot assign attribute on non-namespace object")' + ) + self.outdent() + self.writeline(f"{ref}[{node.attr!r}]") + + def visit_Const(self, node: nodes.Const, frame: Frame) -> None: + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" + ) + + def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(",)" if idx == 0 else ")") + + def visit_List(self, node: nodes.List, frame: Frame) -> None: + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + visit_Add = _make_binop("+") + visit_Sub = _make_binop("-") + visit_Mul = _make_binop("*") + visit_Div = _make_binop("/") + visit_FloorDiv = _make_binop("//") + visit_Pow = _make_binop("**") + visit_Mod = _make_binop("%") + visit_And = _make_binop("and") + visit_Or = _make_binop("or") + visit_Pos = _make_unop("+") + visit_Neg = _make_unop("-") + visit_Not = _make_unop("not ") + + @optimizeconst + def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: + if frame.eval_ctx.volatile: + func_name = "(markup_join if context.eval_ctx.volatile else str_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "str_join" + self.write(f"{func_name}((") + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: + self.write(f" {operators[node.op]} ") + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(f", {node.attr!r})") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @contextmanager + def _filter_test_common( + self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool + ) -> t.Iterator[None]: + if self.environment.is_async: + self.write("(await auto_await(") + + if is_filter: + self.write(f"{self.filters[node.name]}(") + func = self.environment.filters.get(node.name) + else: + self.write(f"{self.tests[node.name]}(") + func = self.environment.tests.get(node.name) + + # When inside an If or CondExpr frame, allow the filter to be + # undefined at compile time and only raise an error if it's + # actually called at runtime. See pull_dependencies. + if func is None and not frame.soft_frame: + type_name = "filter" if is_filter else "test" + self.fail(f"No {type_name} named {node.name!r}.", node.lineno) + + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(func) # type: ignore + ) + + if pass_arg is not None: + self.write(f"{pass_arg}, ") + + # Back to the visitor function to handle visiting the target of + # the filter or test. + yield + + self.signature(node, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: + with self._filter_test_common(node, frame, True): + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + f"(Markup(concat({frame.buffer}))" + f" if context.eval_ctx.autoescape else concat({frame.buffer}))" + ) + elif frame.eval_ctx.autoescape: + self.write(f"Markup(concat({frame.buffer}))") + else: + self.write(f"concat({frame.buffer})") + + @optimizeconst + def visit_Test(self, node: nodes.Test, frame: Frame) -> None: + with self._filter_test_common(node, frame, False): + self.visit(node.node, frame) + + @optimizeconst + def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: + frame = frame.soft() + + def write_expr2() -> None: + if node.expr2 is not None: + self.visit(node.expr2, frame) + return + + self.write( + f'cond_expr_undefined("the inline if-expression on' + f" {self.position(node)} evaluated to false and no else" + f' section was defined.")' + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call( + self, node: nodes.Call, frame: Frame, forward_caller: bool = False + ) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = {"caller": "caller"} if forward_caller else None + loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} + block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} + if extra_kwargs: + extra_kwargs.update(loop_kwargs, **block_kwargs) + elif loop_kwargs or block_kwargs: + extra_kwargs = dict(loop_kwargs, **block_kwargs) + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write("))") + + def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape( + self, node: nodes.MarkSafeIfAutoescape, frame: Frame + ) -> None: + self.write("(Markup if context.eval_ctx.autoescape else identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute( + self, node: nodes.EnvironmentAttribute, frame: Frame + ) -> None: + self.write("environment." + node.name) + + def visit_ExtensionAttribute( + self, node: nodes.ExtensionAttribute, frame: Frame + ) -> None: + self.write(f"environment.extensions[{node.identifier!r}].{node.name}") + + def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: + self.write(node.name) + + def visit_ContextReference( + self, node: nodes.ContextReference, frame: Frame + ) -> None: + self.write("context") + + def visit_DerivedContextReference( + self, node: nodes.DerivedContextReference, frame: Frame + ) -> None: + self.write(self.derive_context(frame)) + + def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: + self.writeline("continue", node) + + def visit_Break(self, node: nodes.Break, frame: Frame) -> None: + self.writeline("break", node) + + def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: + ctx = self.temporary_identifier() + self.writeline(f"{ctx} = {self.derive_context(frame)}") + self.writeline(f"{ctx}.vars = ") + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier( + self, node: nodes.EvalContextModifier, frame: Frame + ) -> None: + for keyword in node.options: + self.writeline(f"context.eval_ctx.{keyword.key} = ") + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier( + self, node: nodes.ScopedEvalContextModifier, frame: Frame + ) -> None: + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/venv/lib/python3.12/site-packages/jinja2/constants.py b/venv/lib/python3.12/site-packages/jinja2/constants.py new file mode 100644 index 0000000..41a1c23 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/constants.py @@ -0,0 +1,20 @@ +#: list of lorem ipsum words used by the lipsum() helper function +LOREM_IPSUM_WORDS = """\ +a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at +auctor augue bibendum blandit class commodo condimentum congue consectetuer +consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus +diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend +elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames +faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac +hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum +justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem +luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie +mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non +nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque +penatibus per pharetra phasellus placerat platea porta porttitor posuere +potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus +ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit +sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor +tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices +ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus +viverra volutpat vulputate""" diff --git a/venv/lib/python3.12/site-packages/jinja2/debug.py b/venv/lib/python3.12/site-packages/jinja2/debug.py new file mode 100644 index 0000000..7ed7e92 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/debug.py @@ -0,0 +1,191 @@ +import sys +import typing as t +from types import CodeType +from types import TracebackType + +from .exceptions import TemplateSyntaxError +from .utils import internal_code +from .utils import missing + +if t.TYPE_CHECKING: + from .runtime import Context + + +def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException: + """Rewrite the current exception to replace any tracebacks from + within compiled template code with tracebacks that look like they + came from the template source. + + This must be called within an ``except`` block. + + :param source: For ``TemplateSyntaxError``, the original source if + known. + :return: The original exception with the rewritten traceback. + """ + _, exc_value, tb = sys.exc_info() + exc_value = t.cast(BaseException, exc_value) + tb = t.cast(TracebackType, tb) + + if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: + exc_value.translated = True + exc_value.source = source + # Remove the old traceback, otherwise the frames from the + # compiler still show up. + exc_value.with_traceback(None) + # Outside of runtime, so the frame isn't executing template + # code, but it still needs to point at the template. + tb = fake_traceback( + exc_value, None, exc_value.filename or "", exc_value.lineno + ) + else: + # Skip the frame for the render function. + tb = tb.tb_next + + stack = [] + + # Build the stack of traceback object, replacing any in template + # code with the source file and line information. + while tb is not None: + # Skip frames decorated with @internalcode. These are internal + # calls that aren't useful in template debugging output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + template = tb.tb_frame.f_globals.get("__jinja_template__") + + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) + stack.append(fake_tb) + else: + stack.append(tb) + + tb = tb.tb_next + + tb_next = None + + # Assign tb_next in reverse to avoid circular references. + for tb in reversed(stack): + tb.tb_next = tb_next + tb_next = tb + + return exc_value.with_traceback(tb_next) + + +def fake_traceback( # type: ignore + exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int +) -> TracebackType: + """Produce a new traceback object that looks like it came from the + template source instead of the compiled code. The filename, line + number, and location name will point to the template, and the local + variables will be the current template context. + + :param exc_value: The original exception to be re-raised to create + the new traceback. + :param tb: The original traceback to get the local variables and + code info from. + :param filename: The template filename. + :param lineno: The line number in the template source. + """ + if tb is not None: + # Replace the real locals with the context that would be + # available at that point in the template. + locals = get_template_locals(tb.tb_frame.f_locals) + locals.pop("__jinja_exception__", None) + else: + locals = {} + + globals = { + "__name__": filename, + "__file__": filename, + "__jinja_exception__": exc_value, + } + # Raise an exception at the correct line number. + code: CodeType = compile( + "\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec" + ) + + # Build a new code object that points to the template file and + # replaces the location with a block name. + location = "template" + + if tb is not None: + function = tb.tb_frame.f_code.co_name + + if function == "root": + location = "top-level template code" + elif function.startswith("block_"): + location = f"block {function[6:]!r}" + + if sys.version_info >= (3, 8): + code = code.replace(co_name=location) + else: + code = CodeType( + code.co_argcount, + code.co_kwonlyargcount, + code.co_nlocals, + code.co_stacksize, + code.co_flags, + code.co_code, + code.co_consts, + code.co_names, + code.co_varnames, + code.co_filename, + location, + code.co_firstlineno, + code.co_lnotab, + code.co_freevars, + code.co_cellvars, + ) + + # Execute the new code, which is guaranteed to raise, and return + # the new traceback without this frame. + try: + exec(code, globals, locals) + except BaseException: + return sys.exc_info()[2].tb_next # type: ignore + + +def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: + """Based on the runtime locals, get the context that would be + available at that point in the template. + """ + # Start with the current template context. + ctx: "t.Optional[Context]" = real_locals.get("context") + + if ctx is not None: + data: t.Dict[str, t.Any] = ctx.get_all().copy() + else: + data = {} + + # Might be in a derived context that only sets local variables + # rather than pushing a context. Local variables follow the scheme + # l_depth_name. Find the highest-depth local that has a value for + # each name. + local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} + + for name, value in real_locals.items(): + if not name.startswith("l_") or value is missing: + # Not a template variable, or no longer relevant. + continue + + try: + _, depth_str, name = name.split("_", 2) + depth = int(depth_str) + except ValueError: + continue + + cur_depth = local_overrides.get(name, (-1,))[0] + + if cur_depth < depth: + local_overrides[name] = (depth, value) + + # Modify the context with any derived context. + for name, (_, value) in local_overrides.items(): + if value is missing: + data.pop(name, None) + else: + data[name] = value + + return data diff --git a/venv/lib/python3.12/site-packages/jinja2/defaults.py b/venv/lib/python3.12/site-packages/jinja2/defaults.py new file mode 100644 index 0000000..638cad3 --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/defaults.py @@ -0,0 +1,48 @@ +import typing as t + +from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 +from .tests import TESTS as DEFAULT_TESTS # noqa: F401 +from .utils import Cycler +from .utils import generate_lorem_ipsum +from .utils import Joiner +from .utils import Namespace + +if t.TYPE_CHECKING: + import typing_extensions as te + +# defaults for the parser / lexer +BLOCK_START_STRING = "{%" +BLOCK_END_STRING = "%}" +VARIABLE_START_STRING = "{{" +VARIABLE_END_STRING = "}}" +COMMENT_START_STRING = "{#" +COMMENT_END_STRING = "#}" +LINE_STATEMENT_PREFIX: t.Optional[str] = None +LINE_COMMENT_PREFIX: t.Optional[str] = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n" +KEEP_TRAILING_NEWLINE = False + +# default filters, tests and namespace + +DEFAULT_NAMESPACE = { + "range": range, + "dict": dict, + "lipsum": generate_lorem_ipsum, + "cycler": Cycler, + "joiner": Joiner, + "namespace": Namespace, +} + +# default policies +DEFAULT_POLICIES: t.Dict[str, t.Any] = { + "compiler.ascii_str": True, + "urlize.rel": "noopener", + "urlize.target": None, + "urlize.extra_schemes": None, + "truncate.leeway": 5, + "json.dumps_function": None, + "json.dumps_kwargs": {"sort_keys": True}, + "ext.i18n.trimmed": False, +} diff --git a/venv/lib/python3.12/site-packages/jinja2/environment.py b/venv/lib/python3.12/site-packages/jinja2/environment.py new file mode 100644 index 0000000..1d3be0b --- /dev/null +++ b/venv/lib/python3.12/site-packages/jinja2/environment.py @@ -0,0 +1,1675 @@ +"""Classes for managing templates and their runtime and compile time +options. +""" + +import os +import typing +import typing as t +import weakref +from collections import ChainMap +from functools import lru_cache +from functools import partial +from functools import reduce +from types import CodeType + +from markupsafe import Markup + +from . import nodes +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import Lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import _PassArg +from .utils import concat +from .utils import consume +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + +# for direct template usage we have up to ten living environments +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + env = cls(*args) + env.shared = True + return env + + +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Return the cache class for the given size.""" + if size == 0: + return None + + if size < 0: + return {} + + return LRUCache(size) # type: ignore + + +def copy_cache( + cache: t.Optional[t.MutableMapping[t.Any, t.Any]], +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: # noqa E721 + return {} + + return LRUCache(cache.capacity) # type: ignore + + +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated extensions. + """ + result = {} + + for extension in extensions: + if isinstance(extension, str): + extension = t.cast(t.Type["Extension"], import_string(extension)) + + result[extension.identifier] = extension(environment) + + return result + + +def _environment_config_check(environment: "Environment") -> "Environment": + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "'undefined' must be a subclass of 'jinja2.Undefined'." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different." + assert environment.newline_sequence in { + "\r", + "\r\n", + "\n", + }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." + return environment + + +class Environment: + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which + allows using async functions and generators. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to: t.Optional["Environment"] = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class: t.Type["CodeGenerator"] = CodeGenerator + + concat = "".join + + #: the context class that is used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class: t.Type[Context] = Context + + template_class: t.Type["Template"] + + def __init__( + self, + block_start_string: str = BLOCK_START_STRING, + block_end_string: str = BLOCK_END_STRING, + variable_start_string: str = VARIABLE_START_STRING, + variable_end_string: str = VARIABLE_END_STRING, + comment_start_string: str = COMMENT_START_STRING, + comment_end_string: str = COMMENT_END_STRING, + line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, + line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, + trim_blocks: bool = TRIM_BLOCKS, + lstrip_blocks: bool = LSTRIP_BLOCKS, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, + keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), + optimized: bool = True, + undefined: t.Type[Undefined] = Undefined, + finalize: t.Optional[t.Callable[..., t.Any]] = None, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, + loader: t.Optional["BaseLoader"] = None, + cache_size: int = 400, + auto_reload: bool = True, + bytecode_cache: t.Optional["BytecodeCache"] = None, + enable_async: bool = False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined: t.Type[Undefined] = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.is_async = enable_async + _environment_config_check(self) + + def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes: t.Any) -> None: + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in attributes.items(): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string: str = missing, + block_end_string: str = missing, + variable_start_string: str = missing, + variable_end_string: str = missing, + comment_start_string: str = missing, + comment_end_string: str = missing, + line_statement_prefix: t.Optional[str] = missing, + line_comment_prefix: t.Optional[str] = missing, + trim_blocks: bool = missing, + lstrip_blocks: bool = missing, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, + keep_trailing_newline: bool = missing, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, + optimized: bool = missing, + undefined: t.Type[Undefined] = missing, + finalize: t.Optional[t.Callable[..., t.Any]] = missing, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, + loader: t.Optional["BaseLoader"] = missing, + cache_size: int = missing, + auto_reload: bool = missing, + bytecode_cache: t.Optional["BytecodeCache"] = missing, + enable_async: bool = False, + ) -> "Environment": + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + + .. versionchanged:: 3.1.2 + Added the ``newline_sequence``,, ``keep_trailing_newline``, + and ``enable_async`` parameters to match ``__init__``. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"], args["enable_async"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in args.items(): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in self.extensions.items(): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + if enable_async is not missing: + rv.is_async = enable_async + + return _environment_config_check(rv) + + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) + + def iter_extensions(self) -> t.Iterator["Extension"]: + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, str): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj: t.Any, attribute: str) -> t.Any: + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a string. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" + + func = env_map.get(name) # type: ignore + + if func is None: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: + if context is None: + raise TemplateRuntimeError( + f"Attempted to invoke a context {type_name} without context." + ) + + args.insert(0, context) + elif pass_arg is _PassArg.eval_context: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if the filter is running from an + environment in async mode and the filter supports async + execution. It's your responsibility to await this if needed. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) + + @internalcode + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, filename).parse() + + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = str(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + str(source), + ) + + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) # type: ignore + + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + + return stream + + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( # type: ignore + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source: str, filename: str) -> CodeType: + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @typing.overload + def compile( # type: ignore + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[False]" = False, + defer_init: bool = False, + ) -> CodeType: ... + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[True]" = ..., + defer_init: bool = False, + ) -> str: ... + + @internalcode + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: bool = False, + defer_init: bool = False, + ) -> t.Union[str, CodeType]: + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, str): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "