From d79d2aefee597d9cb282979b8e05d8d8ed2e8603 Mon Sep 17 00:00:00 2001 From: Markus Lehr Date: Tue, 19 Mar 2024 17:06:47 +0100 Subject: [PATCH] 1st Version --- .venv/bin/Activate.ps1 | 247 + .venv/bin/activate | 69 + .venv/bin/activate.csh | 26 + .venv/bin/activate.fish | 69 + .venv/bin/flask | 8 + .venv/bin/pip | 8 + .venv/bin/pip3 | 8 + .venv/bin/pip3.10 | 8 + .venv/bin/python | 1 + .venv/bin/python3 | 1 + .venv/bin/python3.10 | 1 + .../Jinja2-3.1.3.dist-info/INSTALLER | 1 + .../Jinja2-3.1.3.dist-info/LICENSE.rst | 28 + .../Jinja2-3.1.3.dist-info/METADATA | 105 + .../Jinja2-3.1.3.dist-info/RECORD | 58 + .../Jinja2-3.1.3.dist-info/WHEEL | 5 + .../Jinja2-3.1.3.dist-info/entry_points.txt | 2 + .../Jinja2-3.1.3.dist-info/top_level.txt | 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 | 6 + .../MarkupSafe-2.1.5.dist-info/top_level.txt | 1 + .../site-packages/_distutils_hack/__init__.py | 132 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 5109 bytes .../__pycache__/override.cpython-310.pyc | Bin 0 -> 234 bytes .../site-packages/_distutils_hack/override.py | 1 + .../blinker-1.7.0.dist-info/INSTALLER | 1 + .../blinker-1.7.0.dist-info/LICENSE.rst | 20 + .../blinker-1.7.0.dist-info/METADATA | 62 + .../blinker-1.7.0.dist-info/RECORD | 14 + .../blinker-1.7.0.dist-info/WHEEL | 4 + .../site-packages/blinker/__init__.py | 19 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 498 bytes .../__pycache__/_saferef.cpython-310.pyc | Bin 0 -> 7185 bytes .../__pycache__/_utilities.cpython-310.pyc | Bin 0 -> 3524 bytes .../blinker/__pycache__/base.cpython-310.pyc | Bin 0 -> 17498 bytes .../site-packages/blinker/_saferef.py | 230 + .../site-packages/blinker/_utilities.py | 105 + .../python3.10/site-packages/blinker/base.py | 558 + .../python3.10/site-packages/blinker/py.typed | 0 .../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-310.pyc | Bin 0 -> 2617 bytes .../click/__pycache__/_compat.cpython-310.pyc | Bin 0 -> 15675 bytes .../__pycache__/_termui_impl.cpython-310.pyc | Bin 0 -> 16315 bytes .../__pycache__/_textwrap.cpython-310.pyc | Bin 0 -> 1551 bytes .../__pycache__/_winconsole.cpython-310.pyc | Bin 0 -> 7667 bytes .../click/__pycache__/core.cpython-310.pyc | Bin 0 -> 91145 bytes .../__pycache__/decorators.cpython-310.pyc | Bin 0 -> 17215 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 10259 bytes .../__pycache__/formatting.cpython-310.pyc | Bin 0 -> 9464 bytes .../click/__pycache__/globals.cpython-310.pyc | Bin 0 -> 2436 bytes .../click/__pycache__/parser.cpython-310.pyc | Bin 0 -> 13677 bytes .../shell_completion.cpython-310.pyc | Bin 0 -> 16852 bytes .../click/__pycache__/termui.cpython-310.pyc | Bin 0 -> 26137 bytes .../click/__pycache__/testing.cpython-310.pyc | Bin 0 -> 15210 bytes .../click/__pycache__/types.cpython-310.pyc | Bin 0 -> 33694 bytes .../click/__pycache__/utils.cpython-310.pyc | Bin 0 -> 18850 bytes .../python3.10/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.10/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.10/site-packages/click/globals.py | 68 + .../python3.10/site-packages/click/parser.py | 529 + .../python3.10/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 596 + .../python3.10/site-packages/click/termui.py | 784 + .../python3.10/site-packages/click/testing.py | 479 + .../python3.10/site-packages/click/types.py | 1089 + .../python3.10/site-packages/click/utils.py | 624 + .../site-packages/distutils-precedence.pth | 1 + .../flask-3.0.2.dist-info/INSTALLER | 1 + .../flask-3.0.2.dist-info/LICENSE.rst | 28 + .../flask-3.0.2.dist-info/METADATA | 116 + .../flask-3.0.2.dist-info/RECORD | 58 + .../flask-3.0.2.dist-info/REQUESTED | 0 .../site-packages/flask-3.0.2.dist-info/WHEEL | 4 + .../flask-3.0.2.dist-info/entry_points.txt | 3 + .../site-packages/flask/__init__.py | 60 + .../site-packages/flask/__main__.py | 3 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2288 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 213 bytes .../flask/__pycache__/app.cpython-310.pyc | Bin 0 -> 49883 bytes .../__pycache__/blueprints.cpython-310.pyc | Bin 0 -> 3424 bytes .../flask/__pycache__/cli.cpython-310.pyc | Bin 0 -> 29087 bytes .../flask/__pycache__/config.cpython-310.pyc | Bin 0 -> 13422 bytes .../flask/__pycache__/ctx.cpython-310.pyc | Bin 0 -> 14854 bytes .../__pycache__/debughelpers.cpython-310.pyc | Bin 0 -> 6592 bytes .../flask/__pycache__/globals.cpython-310.pyc | Bin 0 -> 1581 bytes .../flask/__pycache__/helpers.cpython-310.pyc | Bin 0 -> 21608 bytes .../flask/__pycache__/logging.cpython-310.pyc | Bin 0 -> 2548 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 0 -> 13290 bytes .../flask/__pycache__/signals.cpython-310.pyc | Bin 0 -> 811 bytes .../__pycache__/templating.cpython-310.pyc | Bin 0 -> 7085 bytes .../flask/__pycache__/testing.cpython-310.pyc | Bin 0 -> 9848 bytes .../flask/__pycache__/typing.cpython-310.pyc | Bin 0 -> 1835 bytes .../flask/__pycache__/views.cpython-310.pyc | Bin 0 -> 5545 bytes .../__pycache__/wrappers.cpython-310.pyc | Bin 0 -> 5239 bytes .../lib/python3.10/site-packages/flask/app.py | 1488 + .../site-packages/flask/blueprints.py | 91 + .../lib/python3.10/site-packages/flask/cli.py | 1111 + .../python3.10/site-packages/flask/config.py | 372 + .../lib/python3.10/site-packages/flask/ctx.py | 449 + .../site-packages/flask/debughelpers.py | 178 + .../python3.10/site-packages/flask/globals.py | 51 + .../python3.10/site-packages/flask/helpers.py | 621 + .../site-packages/flask/json/__init__.py | 170 + .../json/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 5995 bytes .../json/__pycache__/provider.cpython-310.pyc | Bin 0 -> 7687 bytes .../json/__pycache__/tag.cpython-310.pyc | Bin 0 -> 11645 bytes .../site-packages/flask/json/provider.py | 215 + .../site-packages/flask/json/tag.py | 326 + .../python3.10/site-packages/flask/logging.py | 79 + .../python3.10/site-packages/flask/py.typed | 0 .../site-packages/flask/sansio/README.md | 6 + .../sansio/__pycache__/app.cpython-310.pyc | Bin 0 -> 28612 bytes .../__pycache__/blueprints.cpython-310.pyc | Bin 0 -> 22934 bytes .../__pycache__/scaffold.cpython-310.pyc | Bin 0 -> 24086 bytes .../site-packages/flask/sansio/app.py | 968 + .../site-packages/flask/sansio/blueprints.py | 632 + .../site-packages/flask/sansio/scaffold.py | 805 + .../site-packages/flask/sessions.py | 371 + .../python3.10/site-packages/flask/signals.py | 17 + .../site-packages/flask/templating.py | 219 + .../python3.10/site-packages/flask/testing.py | 298 + .../python3.10/site-packages/flask/typing.py | 90 + .../python3.10/site-packages/flask/views.py | 191 + .../site-packages/flask/wrappers.py | 174 + .../itsdangerous-2.1.2.dist-info/INSTALLER | 1 + .../itsdangerous-2.1.2.dist-info/LICENSE.rst | 28 + .../itsdangerous-2.1.2.dist-info/METADATA | 97 + .../itsdangerous-2.1.2.dist-info/RECORD | 23 + .../itsdangerous-2.1.2.dist-info/WHEEL | 5 + .../top_level.txt | 1 + .../site-packages/itsdangerous/__init__.py | 19 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 866 bytes .../__pycache__/_json.cpython-310.pyc | Bin 0 -> 921 bytes .../__pycache__/encoding.cpython-310.pyc | Bin 0 -> 1870 bytes .../__pycache__/exc.cpython-310.pyc | Bin 0 -> 3409 bytes .../__pycache__/serializer.cpython-310.pyc | Bin 0 -> 9693 bytes .../__pycache__/signer.cpython-310.pyc | Bin 0 -> 8461 bytes .../__pycache__/timed.cpython-310.pyc | Bin 0 -> 6475 bytes .../__pycache__/url_safe.cpython-310.pyc | Bin 0 -> 2694 bytes .../site-packages/itsdangerous/_json.py | 16 + .../site-packages/itsdangerous/encoding.py | 54 + .../site-packages/itsdangerous/exc.py | 107 + .../site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 295 + .../site-packages/itsdangerous/signer.py | 257 + .../site-packages/itsdangerous/timed.py | 234 + .../site-packages/itsdangerous/url_safe.py | 80 + .../site-packages/jinja2/__init__.py | 37 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1602 bytes .../__pycache__/_identifier.cpython-310.pyc | Bin 0 -> 2077 bytes .../__pycache__/async_utils.cpython-310.pyc | Bin 0 -> 2691 bytes .../__pycache__/bccache.cpython-310.pyc | Bin 0 -> 13948 bytes .../__pycache__/compiler.cpython-310.pyc | Bin 0 -> 54551 bytes .../__pycache__/constants.cpython-310.pyc | Bin 0 -> 1538 bytes .../jinja2/__pycache__/debug.cpython-310.pyc | Bin 0 -> 3994 bytes .../__pycache__/defaults.cpython-310.pyc | Bin 0 -> 1338 bytes .../__pycache__/environment.cpython-310.pyc | Bin 0 -> 53388 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 5537 bytes .../jinja2/__pycache__/ext.cpython-310.pyc | Bin 0 -> 25843 bytes .../__pycache__/filters.cpython-310.pyc | Bin 0 -> 51372 bytes .../__pycache__/idtracking.cpython-310.pyc | Bin 0 -> 11089 bytes .../jinja2/__pycache__/lexer.cpython-310.pyc | Bin 0 -> 20439 bytes .../__pycache__/loaders.cpython-310.pyc | Bin 0 -> 20495 bytes .../jinja2/__pycache__/meta.cpython-310.pyc | Bin 0 -> 3818 bytes .../__pycache__/nativetypes.cpython-310.pyc | Bin 0 -> 5013 bytes .../jinja2/__pycache__/nodes.cpython-310.pyc | Bin 0 -> 40304 bytes .../__pycache__/optimizer.cpython-310.pyc | Bin 0 -> 1958 bytes .../jinja2/__pycache__/parser.cpython-310.pyc | Bin 0 -> 27732 bytes .../__pycache__/runtime.cpython-310.pyc | Bin 0 -> 32147 bytes .../__pycache__/sandbox.cpython-310.pyc | Bin 0 -> 11970 bytes .../jinja2/__pycache__/tests.cpython-310.pyc | Bin 0 -> 6692 bytes .../jinja2/__pycache__/utils.cpython-310.pyc | Bin 0 -> 24511 bytes .../__pycache__/visitor.cpython-310.pyc | Bin 0 -> 3977 bytes .../site-packages/jinja2/_identifier.py | 6 + .../site-packages/jinja2/async_utils.py | 84 + .../site-packages/jinja2/bccache.py | 406 + .../site-packages/jinja2/compiler.py | 1956 ++ .../site-packages/jinja2/constants.py | 20 + .../python3.10/site-packages/jinja2/debug.py | 191 + .../site-packages/jinja2/defaults.py | 48 + .../site-packages/jinja2/environment.py | 1667 + .../site-packages/jinja2/exceptions.py | 166 + .../python3.10/site-packages/jinja2/ext.py | 869 + .../site-packages/jinja2/filters.py | 1854 ++ .../site-packages/jinja2/idtracking.py | 318 + .../python3.10/site-packages/jinja2/lexer.py | 866 + .../site-packages/jinja2/loaders.py | 661 + .../python3.10/site-packages/jinja2/meta.py | 111 + .../site-packages/jinja2/nativetypes.py | 130 + .../python3.10/site-packages/jinja2/nodes.py | 1204 + .../site-packages/jinja2/optimizer.py | 47 + .../python3.10/site-packages/jinja2/parser.py | 1034 + .../python3.10/site-packages/jinja2/py.typed | 0 .../site-packages/jinja2/runtime.py | 1051 + .../site-packages/jinja2/sandbox.py | 428 + .../python3.10/site-packages/jinja2/tests.py | 255 + .../python3.10/site-packages/jinja2/utils.py | 755 + .../site-packages/jinja2/visitor.py | 92 + .../site-packages/markupsafe/__init__.py | 332 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 11347 bytes .../__pycache__/_native.cpython-310.pyc | Bin 0 -> 2002 bytes .../site-packages/markupsafe/_native.py | 63 + .../site-packages/markupsafe/_speedups.c | 320 + .../_speedups.cpython-310-x86_64-linux-gnu.so | Bin 0 -> 44240 bytes .../site-packages/markupsafe/_speedups.pyi | 9 + .../site-packages/markupsafe/py.typed | 0 .../marshmallow-3.21.1.dist-info/INSTALLER | 1 + .../marshmallow-3.21.1.dist-info/LICENSE | 19 + .../marshmallow-3.21.1.dist-info/METADATA | 200 + .../marshmallow-3.21.1.dist-info/RECORD | 33 + .../marshmallow-3.21.1.dist-info/REQUESTED | 0 .../marshmallow-3.21.1.dist-info/WHEEL | 4 + .../site-packages/marshmallow/__init__.py | 81 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1995 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2204 bytes .../class_registry.cpython-310.pyc | Bin 0 -> 2425 bytes .../__pycache__/decorators.cpython-310.pyc | Bin 0 -> 8074 bytes .../__pycache__/error_store.cpython-310.pyc | Bin 0 -> 1688 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 2986 bytes .../__pycache__/fields.cpython-310.pyc | Bin 0 -> 64075 bytes .../__pycache__/orderedset.cpython-310.pyc | Bin 0 -> 2407 bytes .../__pycache__/schema.cpython-310.pyc | Bin 0 -> 35862 bytes .../__pycache__/types.cpython-310.pyc | Bin 0 -> 511 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 13002 bytes .../__pycache__/validate.cpython-310.pyc | Bin 0 -> 23709 bytes .../__pycache__/warnings.cpython-310.pyc | Bin 0 -> 373 bytes .../site-packages/marshmallow/base.py | 64 + .../marshmallow/class_registry.py | 92 + .../site-packages/marshmallow/decorators.py | 224 + .../site-packages/marshmallow/error_store.py | 60 + .../site-packages/marshmallow/exceptions.py | 70 + .../site-packages/marshmallow/fields.py | 2112 ++ .../site-packages/marshmallow/orderedset.py | 89 + .../site-packages/marshmallow/py.typed | 0 .../site-packages/marshmallow/schema.py | 1229 + .../site-packages/marshmallow/types.py | 11 + .../site-packages/marshmallow/utils.py | 375 + .../site-packages/marshmallow/validate.py | 680 + .../site-packages/marshmallow/warnings.py | 2 + .../packaging-24.0.dist-info/INSTALLER | 1 + .../packaging-24.0.dist-info/LICENSE | 3 + .../packaging-24.0.dist-info/LICENSE.APACHE | 177 + .../packaging-24.0.dist-info/LICENSE.BSD | 23 + .../packaging-24.0.dist-info/METADATA | 102 + .../packaging-24.0.dist-info/RECORD | 36 + .../packaging-24.0.dist-info/WHEEL | 4 + .../site-packages/packaging/__init__.py | 15 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 507 bytes .../__pycache__/_elffile.cpython-310.pyc | Bin 0 -> 3299 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 0 -> 6410 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 0 -> 3329 bytes .../__pycache__/_parser.cpython-310.pyc | Bin 0 -> 8951 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 0 -> 2689 bytes .../__pycache__/_tokenizer.cpython-310.pyc | Bin 0 -> 5809 bytes .../__pycache__/markers.cpython-310.pyc | Bin 0 -> 6883 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 0 -> 17808 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 0 -> 2822 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 0 -> 30981 bytes .../__pycache__/tags.cpython-310.pyc | Bin 0 -> 13789 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 4507 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 14152 bytes .../site-packages/packaging/_elffile.py | 108 + .../site-packages/packaging/_manylinux.py | 260 + .../site-packages/packaging/_musllinux.py | 83 + .../site-packages/packaging/_parser.py | 356 + .../site-packages/packaging/_structures.py | 61 + .../site-packages/packaging/_tokenizer.py | 192 + .../site-packages/packaging/markers.py | 252 + .../site-packages/packaging/metadata.py | 825 + .../site-packages/packaging/py.typed | 0 .../site-packages/packaging/requirements.py | 90 + .../site-packages/packaging/specifiers.py | 1017 + .../site-packages/packaging/tags.py | 571 + .../site-packages/packaging/utils.py | 172 + .../site-packages/packaging/version.py | 563 + .../pip-22.0.2.dist-info/INSTALLER | 1 + .../pip-22.0.2.dist-info/LICENSE.txt | 20 + .../pip-22.0.2.dist-info/METADATA | 92 + .../site-packages/pip-22.0.2.dist-info/RECORD | 1037 + .../pip-22.0.2.dist-info/REQUESTED | 0 .../site-packages/pip-22.0.2.dist-info/WHEEL | 5 + .../pip-22.0.2.dist-info/entry_points.txt | 5 + .../pip-22.0.2.dist-info/top_level.txt | 1 + .../python3.10/site-packages/pip/__init__.py | 13 + .../python3.10/site-packages/pip/__main__.py | 31 + .../pip/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 627 bytes .../pip/__pycache__/__main__.cpython-310.pyc | Bin 0 -> 589 bytes .../site-packages/pip/_internal/__init__.py | 19 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 748 bytes .../__pycache__/build_env.cpython-310.pyc | Bin 0 -> 9592 bytes .../__pycache__/cache.cpython-310.pyc | Bin 0 -> 8375 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 0 -> 11121 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 23118 bytes .../__pycache__/main.cpython-310.pyc | Bin 0 -> 613 bytes .../__pycache__/pyproject.cpython-310.pyc | Bin 0 -> 3532 bytes .../self_outdated_check.cpython-310.pyc | Bin 0 -> 4572 bytes .../__pycache__/wheel_builder.cpython-310.pyc | Bin 0 -> 9134 bytes .../site-packages/pip/_internal/build_env.py | 296 + .../site-packages/pip/_internal/cache.py | 264 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 268 bytes .../autocompletion.cpython-310.pyc | Bin 0 -> 5301 bytes .../__pycache__/base_command.cpython-310.pyc | Bin 0 -> 6244 bytes .../__pycache__/cmdoptions.cpython-310.pyc | Bin 0 -> 22543 bytes .../command_context.cpython-310.pyc | Bin 0 -> 1302 bytes .../cli/__pycache__/main.cpython-310.pyc | Bin 0 -> 1366 bytes .../__pycache__/main_parser.cpython-310.pyc | Bin 0 -> 2152 bytes .../cli/__pycache__/parser.cpython-310.pyc | Bin 0 -> 9939 bytes .../__pycache__/progress_bars.cpython-310.pyc | Bin 0 -> 9228 bytes .../__pycache__/req_command.cpython-310.pyc | Bin 0 -> 13529 bytes .../cli/__pycache__/spinners.cpython-310.pyc | Bin 0 -> 4942 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 0 -> 347 bytes .../pip/_internal/cli/autocompletion.py | 171 + .../pip/_internal/cli/base_command.py | 220 + .../pip/_internal/cli/cmdoptions.py | 1018 + .../pip/_internal/cli/command_context.py | 27 + .../site-packages/pip/_internal/cli/main.py | 70 + .../pip/_internal/cli/main_parser.py | 87 + .../site-packages/pip/_internal/cli/parser.py | 292 + .../pip/_internal/cli/progress_bars.py | 321 + .../pip/_internal/cli/req_command.py | 506 + .../pip/_internal/cli/spinners.py | 157 + .../pip/_internal/cli/status_codes.py | 6 + .../pip/_internal/commands/__init__.py | 127 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 3131 bytes .../__pycache__/cache.cpython-310.pyc | Bin 0 -> 6172 bytes .../__pycache__/check.cpython-310.pyc | Bin 0 -> 1565 bytes .../__pycache__/completion.cpython-310.pyc | Bin 0 -> 3132 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 0 -> 8314 bytes .../__pycache__/debug.cpython-310.pyc | Bin 0 -> 6669 bytes .../__pycache__/download.cpython-310.pyc | Bin 0 -> 3979 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 0 -> 2645 bytes .../commands/__pycache__/hash.cpython-310.pyc | Bin 0 -> 2144 bytes .../commands/__pycache__/help.cpython-310.pyc | Bin 0 -> 1305 bytes .../__pycache__/index.cpython-310.pyc | Bin 0 -> 4628 bytes .../__pycache__/install.cpython-310.pyc | Bin 0 -> 17787 bytes .../commands/__pycache__/list.cpython-310.pyc | Bin 0 -> 10354 bytes .../__pycache__/search.cpython-310.pyc | Bin 0 -> 5358 bytes .../commands/__pycache__/show.cpython-310.pyc | Bin 0 -> 6111 bytes .../__pycache__/uninstall.cpython-310.pyc | Bin 0 -> 3102 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 0 -> 4834 bytes .../pip/_internal/commands/cache.py | 223 + .../pip/_internal/commands/check.py | 53 + .../pip/_internal/commands/completion.py | 96 + .../pip/_internal/commands/configuration.py | 266 + .../pip/_internal/commands/debug.py | 202 + .../pip/_internal/commands/download.py | 140 + .../pip/_internal/commands/freeze.py | 97 + .../pip/_internal/commands/hash.py | 59 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/index.py | 139 + .../pip/_internal/commands/install.py | 771 + .../pip/_internal/commands/list.py | 363 + .../pip/_internal/commands/search.py | 174 + .../pip/_internal/commands/show.py | 178 + .../pip/_internal/commands/uninstall.py | 105 + .../pip/_internal/commands/wheel.py | 178 + .../pip/_internal/configuration.py | 366 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 795 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 1852 bytes .../__pycache__/installed.cpython-310.pyc | Bin 0 -> 1229 bytes .../__pycache__/sdist.cpython-310.pyc | Bin 0 -> 4441 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 0 -> 1596 bytes .../pip/_internal/distributions/base.py | 36 + .../pip/_internal/distributions/installed.py | 20 + .../pip/_internal/distributions/sdist.py | 127 + .../pip/_internal/distributions/wheel.py | 31 + .../site-packages/pip/_internal/exceptions.py | 658 + .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 222 bytes .../__pycache__/collector.cpython-310.pyc | Bin 0 -> 19301 bytes .../package_finder.cpython-310.pyc | Bin 0 -> 28110 bytes .../index/__pycache__/sources.cpython-310.pyc | Bin 0 -> 7115 bytes .../pip/_internal/index/collector.py | 648 + .../pip/_internal/index/package_finder.py | 1004 + .../pip/_internal/index/sources.py | 224 + .../pip/_internal/locations/__init__.py | 520 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 12382 bytes .../__pycache__/_distutils.cpython-310.pyc | Bin 0 -> 4650 bytes .../__pycache__/_sysconfig.cpython-310.pyc | Bin 0 -> 6233 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 1532 bytes .../pip/_internal/locations/_distutils.py | 169 + .../pip/_internal/locations/_sysconfig.py | 219 + .../pip/_internal/locations/base.py | 52 + .../site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 62 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2288 bytes .../metadata/__pycache__/base.cpython-310.pyc | Bin 0 -> 20842 bytes .../__pycache__/pkg_resources.cpython-310.pyc | Bin 0 -> 9858 bytes .../pip/_internal/metadata/base.py | 546 + .../pip/_internal/metadata/pkg_resources.py | 256 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 256 bytes .../__pycache__/candidate.cpython-310.pyc | Bin 0 -> 1408 bytes .../__pycache__/direct_url.cpython-310.pyc | Bin 0 -> 7281 bytes .../format_control.cpython-310.pyc | Bin 0 -> 2733 bytes .../models/__pycache__/index.cpython-310.pyc | Bin 0 -> 1225 bytes .../models/__pycache__/link.cpython-310.pyc | Bin 0 -> 10157 bytes .../models/__pycache__/scheme.cpython-310.pyc | Bin 0 -> 1024 bytes .../__pycache__/search_scope.cpython-310.pyc | Bin 0 -> 3479 bytes .../selection_prefs.cpython-310.pyc | Bin 0 -> 1686 bytes .../__pycache__/target_python.cpython-310.pyc | Bin 0 -> 3437 bytes .../models/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 4353 bytes .../pip/_internal/models/candidate.py | 34 + .../pip/_internal/models/direct_url.py | 220 + .../pip/_internal/models/format_control.py | 80 + .../pip/_internal/models/index.py | 28 + .../pip/_internal/models/link.py | 288 + .../pip/_internal/models/scheme.py | 31 + .../pip/_internal/models/search_scope.py | 129 + .../pip/_internal/models/selection_prefs.py | 51 + .../pip/_internal/models/target_python.py | 110 + .../pip/_internal/models/wheel.py | 89 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 244 bytes .../network/__pycache__/auth.cpython-310.pyc | Bin 0 -> 7512 bytes .../network/__pycache__/cache.cpython-310.pyc | Bin 0 -> 2925 bytes .../__pycache__/download.cpython-310.pyc | Bin 0 -> 5491 bytes .../__pycache__/lazy_wheel.cpython-310.pyc | Bin 0 -> 8399 bytes .../__pycache__/session.cpython-310.pyc | Bin 0 -> 10720 bytes .../network/__pycache__/utils.cpython-310.pyc | Bin 0 -> 1440 bytes .../__pycache__/xmlrpc.cpython-310.pyc | Bin 0 -> 2057 bytes .../pip/_internal/network/auth.py | 323 + .../pip/_internal/network/cache.py | 69 + .../pip/_internal/network/download.py | 185 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 454 + .../pip/_internal/network/utils.py | 96 + .../pip/_internal/network/xmlrpc.py | 60 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 192 bytes .../__pycache__/check.cpython-310.pyc | Bin 0 -> 4005 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 0 -> 6190 bytes .../__pycache__/prepare.cpython-310.pyc | Bin 0 -> 14888 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 198 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 0 -> 1425 bytes .../metadata_editable.cpython-310.pyc | Bin 0 -> 1459 bytes .../metadata_legacy.cpython-310.pyc | Bin 0 -> 2370 bytes .../build/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 1215 bytes .../wheel_editable.cpython-310.pyc | Bin 0 -> 1439 bytes .../__pycache__/wheel_legacy.cpython-310.pyc | Bin 0 -> 2755 bytes .../_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 | 149 + .../pip/_internal/operations/freeze.py | 254 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 256 bytes .../editable_legacy.cpython-310.pyc | Bin 0 -> 1543 bytes .../__pycache__/legacy.cpython-310.pyc | Bin 0 -> 3327 bytes .../install/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 21085 bytes .../operations/install/editable_legacy.py | 47 + .../_internal/operations/install/legacy.py | 120 + .../pip/_internal/operations/install/wheel.py | 738 + .../pip/_internal/operations/prepare.py | 642 + .../site-packages/pip/_internal/pyproject.py | 168 + .../pip/_internal/req/__init__.py | 94 + .../req/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2592 bytes .../__pycache__/constructors.cpython-310.pyc | Bin 0 -> 12155 bytes .../req/__pycache__/req_file.cpython-310.pyc | Bin 0 -> 13483 bytes .../__pycache__/req_install.cpython-310.pyc | Bin 0 -> 22172 bytes .../req/__pycache__/req_set.cpython-310.pyc | Bin 0 -> 5832 bytes .../__pycache__/req_tracker.cpython-310.pyc | Bin 0 -> 4300 bytes .../__pycache__/req_uninstall.cpython-310.pyc | Bin 0 -> 18938 bytes .../pip/_internal/req/constructors.py | 490 + .../pip/_internal/req/req_file.py | 536 + .../pip/_internal/req/req_install.py | 858 + .../pip/_internal/req/req_set.py | 189 + .../pip/_internal/req/req_tracker.py | 124 + .../pip/_internal/req/req_uninstall.py | 633 + .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 192 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 1044 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 199 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 0 -> 12286 bytes .../_internal/resolution/legacy/resolver.py | 467 + .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 203 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 6446 bytes .../__pycache__/candidates.cpython-310.pyc | Bin 0 -> 18353 bytes .../__pycache__/factory.cpython-310.pyc | Bin 0 -> 19211 bytes .../found_candidates.cpython-310.pyc | Bin 0 -> 4863 bytes .../__pycache__/provider.cpython-310.pyc | Bin 0 -> 7705 bytes .../__pycache__/reporter.cpython-310.pyc | Bin 0 -> 3172 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 0 -> 7461 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 0 -> 8098 bytes .../_internal/resolution/resolvelib/base.py | 141 + .../resolution/resolvelib/candidates.py | 547 + .../resolution/resolvelib/factory.py | 739 + .../resolution/resolvelib/found_candidates.py | 155 + .../resolution/resolvelib/provider.py | 248 + .../resolution/resolvelib/reporter.py | 68 + .../resolution/resolvelib/requirements.py | 166 + .../resolution/resolvelib/resolver.py | 292 + .../pip/_internal/self_outdated_check.py | 189 + .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 187 bytes .../utils/__pycache__/_log.cpython-310.pyc | Bin 0 -> 1515 bytes .../utils/__pycache__/appdirs.cpython-310.pyc | Bin 0 -> 1613 bytes .../utils/__pycache__/compat.cpython-310.pyc | Bin 0 -> 1503 bytes .../compatibility_tags.cpython-310.pyc | Bin 0 -> 4072 bytes .../__pycache__/datetime.cpython-310.pyc | Bin 0 -> 510 bytes .../__pycache__/deprecation.cpython-310.pyc | Bin 0 -> 3308 bytes .../direct_url_helpers.cpython-310.pyc | Bin 0 -> 2078 bytes .../distutils_args.cpython-310.pyc | Bin 0 -> 1094 bytes .../__pycache__/egg_link.cpython-310.pyc | Bin 0 -> 2143 bytes .../__pycache__/encoding.cpython-310.pyc | Bin 0 -> 1300 bytes .../__pycache__/entrypoints.cpython-310.pyc | Bin 0 -> 1297 bytes .../__pycache__/filesystem.cpython-310.pyc | Bin 0 -> 5155 bytes .../__pycache__/filetypes.cpython-310.pyc | Bin 0 -> 937 bytes .../utils/__pycache__/glibc.cpython-310.pyc | Bin 0 -> 1666 bytes .../utils/__pycache__/hashes.cpython-310.pyc | Bin 0 -> 5189 bytes .../inject_securetransport.cpython-310.pyc | Bin 0 -> 982 bytes .../utils/__pycache__/logging.cpython-310.pyc | Bin 0 -> 9626 bytes .../utils/__pycache__/misc.cpython-310.pyc | Bin 0 -> 19392 bytes .../utils/__pycache__/models.cpython-310.pyc | Bin 0 -> 1983 bytes .../__pycache__/packaging.cpython-310.pyc | Bin 0 -> 2075 bytes .../setuptools_build.cpython-310.pyc | Bin 0 -> 4590 bytes .../__pycache__/subprocess.cpython-310.pyc | Bin 0 -> 5769 bytes .../__pycache__/temp_dir.cpython-310.pyc | Bin 0 -> 7292 bytes .../__pycache__/unpacking.cpython-310.pyc | Bin 0 -> 6647 bytes .../utils/__pycache__/urls.cpython-310.pyc | Bin 0 -> 1580 bytes .../__pycache__/virtualenv.cpython-310.pyc | Bin 0 -> 3283 bytes .../utils/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 4408 bytes .../site-packages/pip/_internal/utils/_log.py | 38 + .../pip/_internal/utils/appdirs.py | 52 + .../pip/_internal/utils/compat.py | 63 + .../pip/_internal/utils/compatibility_tags.py | 165 + .../pip/_internal/utils/datetime.py | 11 + .../pip/_internal/utils/deprecation.py | 120 + .../pip/_internal/utils/direct_url_helpers.py | 87 + .../pip/_internal/utils/distutils_args.py | 42 + .../pip/_internal/utils/egg_link.py | 75 + .../pip/_internal/utils/encoding.py | 36 + .../pip/_internal/utils/entrypoints.py | 27 + .../pip/_internal/utils/filesystem.py | 182 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 88 + .../pip/_internal/utils/hashes.py | 144 + .../_internal/utils/inject_securetransport.py | 35 + .../pip/_internal/utils/logging.py | 343 + .../site-packages/pip/_internal/utils/misc.py | 653 + .../pip/_internal/utils/models.py | 39 + .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/setuptools_build.py | 195 + .../pip/_internal/utils/subprocess.py | 260 + .../pip/_internal/utils/temp_dir.py | 246 + .../pip/_internal/utils/unpacking.py | 258 + .../site-packages/pip/_internal/utils/urls.py | 62 + .../pip/_internal/utils/virtualenv.py | 104 + .../pip/_internal/utils/wheel.py | 136 + .../pip/_internal/vcs/__init__.py | 15 + .../vcs/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 510 bytes .../vcs/__pycache__/bazaar.cpython-310.pyc | Bin 0 -> 3337 bytes .../vcs/__pycache__/git.cpython-310.pyc | Bin 0 -> 12540 bytes .../vcs/__pycache__/mercurial.cpython-310.pyc | Bin 0 -> 5056 bytes .../__pycache__/subversion.cpython-310.pyc | Bin 0 -> 8444 bytes .../versioncontrol.cpython-310.pyc | Bin 0 -> 21139 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 101 + .../site-packages/pip/_internal/vcs/git.py | 526 + .../pip/_internal/vcs/mercurial.py | 163 + .../pip/_internal/vcs/subversion.py | 324 + .../pip/_internal/vcs/versioncontrol.py | 705 + .../pip/_internal/wheel_builder.py | 377 + .../site-packages/pip/_vendor/__init__.py | 111 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2910 bytes .../__pycache__/distro.cpython-310.pyc | Bin 0 -> 38228 bytes .../_vendor/__pycache__/six.cpython-310.pyc | Bin 0 -> 27577 bytes .../typing_extensions.cpython-310.pyc | Bin 0 -> 66573 bytes .../pip/_vendor/cachecontrol/__init__.py | 18 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 638 bytes .../__pycache__/_cmd.cpython-310.pyc | Bin 0 -> 1576 bytes .../__pycache__/adapter.cpython-310.pyc | Bin 0 -> 3152 bytes .../__pycache__/cache.cpython-310.pyc | Bin 0 -> 1842 bytes .../__pycache__/compat.cpython-310.pyc | Bin 0 -> 752 bytes .../__pycache__/controller.cpython-310.pyc | Bin 0 -> 8206 bytes .../__pycache__/filewrapper.cpython-310.pyc | Bin 0 -> 2788 bytes .../__pycache__/heuristics.cpython-310.pyc | Bin 0 -> 4712 bytes .../__pycache__/serialize.cpython-310.pyc | Bin 0 -> 4247 bytes .../__pycache__/wrapper.cpython-310.pyc | Bin 0 -> 683 bytes .../pip/_vendor/cachecontrol/_cmd.py | 61 + .../pip/_vendor/cachecontrol/adapter.py | 137 + .../pip/_vendor/cachecontrol/cache.py | 43 + .../_vendor/cachecontrol/caches/__init__.py | 6 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 289 bytes .../__pycache__/file_cache.cpython-310.pyc | Bin 0 -> 3363 bytes .../__pycache__/redis_cache.cpython-310.pyc | Bin 0 -> 1569 bytes .../_vendor/cachecontrol/caches/file_cache.py | 150 + .../cachecontrol/caches/redis_cache.py | 37 + .../pip/_vendor/cachecontrol/compat.py | 32 + .../pip/_vendor/cachecontrol/controller.py | 415 + .../pip/_vendor/cachecontrol/filewrapper.py | 111 + .../pip/_vendor/cachecontrol/heuristics.py | 139 + .../pip/_vendor/cachecontrol/serialize.py | 186 + .../pip/_vendor/cachecontrol/wrapper.py | 33 + .../pip/_vendor/certifi/__init__.py | 3 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 271 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 450 bytes .../certifi/__pycache__/core.cpython-310.pyc | Bin 0 -> 1509 bytes .../pip/_vendor/certifi/cacert.pem | 4362 +++ .../site-packages/pip/_vendor/certifi/core.py | 76 + .../pip/_vendor/chardet/__init__.py | 83 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1895 bytes .../__pycache__/big5freq.cpython-310.pyc | Bin 0 -> 27174 bytes .../__pycache__/big5prober.cpython-310.pyc | Bin 0 -> 1125 bytes .../chardistribution.cpython-310.pyc | Bin 0 -> 5735 bytes .../charsetgroupprober.cpython-310.pyc | Bin 0 -> 2224 bytes .../__pycache__/charsetprober.cpython-310.pyc | Bin 0 -> 3478 bytes .../codingstatemachine.cpython-310.pyc | Bin 0 -> 2897 bytes .../__pycache__/compat.cpython-310.pyc | Bin 0 -> 396 bytes .../__pycache__/cp949prober.cpython-310.pyc | Bin 0 -> 1132 bytes .../chardet/__pycache__/enums.cpython-310.pyc | Bin 0 -> 2579 bytes .../__pycache__/escprober.cpython-310.pyc | Bin 0 -> 2626 bytes .../chardet/__pycache__/escsm.cpython-310.pyc | Bin 0 -> 8373 bytes .../__pycache__/eucjpprober.cpython-310.pyc | Bin 0 -> 2428 bytes .../__pycache__/euckrfreq.cpython-310.pyc | Bin 0 -> 12058 bytes .../__pycache__/euckrprober.cpython-310.pyc | Bin 0 -> 1133 bytes .../__pycache__/euctwfreq.cpython-310.pyc | Bin 0 -> 27178 bytes .../__pycache__/euctwprober.cpython-310.pyc | Bin 0 -> 1133 bytes .../__pycache__/gb2312freq.cpython-310.pyc | Bin 0 -> 19102 bytes .../__pycache__/gb2312prober.cpython-310.pyc | Bin 0 -> 1141 bytes .../__pycache__/hebrewprober.cpython-310.pyc | Bin 0 -> 3014 bytes .../__pycache__/jisfreq.cpython-310.pyc | Bin 0 -> 22130 bytes .../__pycache__/jpcntx.cpython-310.pyc | Bin 0 -> 37637 bytes .../langbulgarianmodel.cpython-310.pyc | Bin 0 -> 47918 bytes .../langgreekmodel.cpython-310.pyc | Bin 0 -> 46108 bytes .../langhebrewmodel.cpython-310.pyc | Bin 0 -> 44557 bytes .../langhungarianmodel.cpython-310.pyc | Bin 0 -> 47878 bytes .../langrussianmodel.cpython-310.pyc | Bin 0 -> 61011 bytes .../__pycache__/langthaimodel.cpython-310.pyc | Bin 0 -> 44733 bytes .../langturkishmodel.cpython-310.pyc | Bin 0 -> 44574 bytes .../__pycache__/latin1prober.cpython-310.pyc | Bin 0 -> 4424 bytes .../mbcharsetprober.cpython-310.pyc | Bin 0 -> 2243 bytes .../mbcsgroupprober.cpython-310.pyc | Bin 0 -> 1128 bytes .../__pycache__/mbcssm.cpython-310.pyc | Bin 0 -> 18755 bytes .../sbcharsetprober.cpython-310.pyc | Bin 0 -> 3074 bytes .../sbcsgroupprober.cpython-310.pyc | Bin 0 -> 1697 bytes .../__pycache__/sjisprober.cpython-310.pyc | Bin 0 -> 2466 bytes .../universaldetector.cpython-310.pyc | Bin 0 -> 5820 bytes .../__pycache__/utf8prober.cpython-310.pyc | Bin 0 -> 1977 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 434 bytes .../pip/_vendor/chardet/big5freq.py | 386 + .../pip/_vendor/chardet/big5prober.py | 47 + .../pip/_vendor/chardet/chardistribution.py | 233 + .../pip/_vendor/chardet/charsetgroupprober.py | 107 + .../pip/_vendor/chardet/charsetprober.py | 145 + .../pip/_vendor/chardet/cli/__init__.py | 1 + .../cli/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 191 bytes .../__pycache__/chardetect.cpython-310.pyc | Bin 0 -> 2690 bytes .../pip/_vendor/chardet/cli/chardetect.py | 84 + .../pip/_vendor/chardet/codingstatemachine.py | 88 + .../pip/_vendor/chardet/compat.py | 36 + .../pip/_vendor/chardet/cp949prober.py | 49 + .../pip/_vendor/chardet/enums.py | 76 + .../pip/_vendor/chardet/escprober.py | 101 + .../pip/_vendor/chardet/escsm.py | 246 + .../pip/_vendor/chardet/eucjpprober.py | 92 + .../pip/_vendor/chardet/euckrfreq.py | 195 + .../pip/_vendor/chardet/euckrprober.py | 47 + .../pip/_vendor/chardet/euctwfreq.py | 387 + .../pip/_vendor/chardet/euctwprober.py | 46 + .../pip/_vendor/chardet/gb2312freq.py | 283 + .../pip/_vendor/chardet/gb2312prober.py | 46 + .../pip/_vendor/chardet/hebrewprober.py | 292 + .../pip/_vendor/chardet/jisfreq.py | 325 + .../pip/_vendor/chardet/jpcntx.py | 233 + .../pip/_vendor/chardet/langbulgarianmodel.py | 4650 +++ .../pip/_vendor/chardet/langgreekmodel.py | 4398 +++ .../pip/_vendor/chardet/langhebrewmodel.py | 4383 +++ .../pip/_vendor/chardet/langhungarianmodel.py | 4650 +++ .../pip/_vendor/chardet/langrussianmodel.py | 5718 ++++ .../pip/_vendor/chardet/langthaimodel.py | 4383 +++ .../pip/_vendor/chardet/langturkishmodel.py | 4383 +++ .../pip/_vendor/chardet/latin1prober.py | 145 + .../pip/_vendor/chardet/mbcharsetprober.py | 91 + .../pip/_vendor/chardet/mbcsgroupprober.py | 54 + .../pip/_vendor/chardet/mbcssm.py | 572 + .../pip/_vendor/chardet/metadata/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 196 bytes .../__pycache__/languages.cpython-310.pyc | Bin 0 -> 7958 bytes .../pip/_vendor/chardet/metadata/languages.py | 310 + .../pip/_vendor/chardet/sbcharsetprober.py | 145 + .../pip/_vendor/chardet/sbcsgroupprober.py | 83 + .../pip/_vendor/chardet/sjisprober.py | 92 + .../pip/_vendor/chardet/universaldetector.py | 286 + .../pip/_vendor/chardet/utf8prober.py | 82 + .../pip/_vendor/chardet/version.py | 9 + .../pip/_vendor/colorama/__init__.py | 6 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 439 bytes .../colorama/__pycache__/ansi.cpython-310.pyc | Bin 0 -> 3000 bytes .../__pycache__/ansitowin32.cpython-310.pyc | Bin 0 -> 7898 bytes .../__pycache__/initialise.cpython-310.pyc | Bin 0 -> 1686 bytes .../__pycache__/win32.cpython-310.pyc | Bin 0 -> 3946 bytes .../__pycache__/winterm.cpython-310.pyc | Bin 0 -> 4563 bytes .../pip/_vendor/colorama/ansi.py | 102 + .../pip/_vendor/colorama/ansitowin32.py | 258 + .../pip/_vendor/colorama/initialise.py | 80 + .../pip/_vendor/colorama/win32.py | 152 + .../pip/_vendor/colorama/winterm.py | 169 + .../pip/_vendor/distlib/__init__.py | 23 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1058 bytes .../__pycache__/compat.cpython-310.pyc | Bin 0 -> 31404 bytes .../__pycache__/database.cpython-310.pyc | Bin 0 -> 42859 bytes .../distlib/__pycache__/index.cpython-310.pyc | Bin 0 -> 17313 bytes .../__pycache__/locators.cpython-310.pyc | Bin 0 -> 38372 bytes .../__pycache__/manifest.cpython-310.pyc | Bin 0 -> 10226 bytes .../__pycache__/markers.cpython-310.pyc | Bin 0 -> 5030 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 0 -> 26558 bytes .../__pycache__/resources.cpython-310.pyc | Bin 0 -> 11032 bytes .../__pycache__/scripts.cpython-310.pyc | Bin 0 -> 11248 bytes .../distlib/__pycache__/util.cpython-310.pyc | Bin 0 -> 51691 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 20145 bytes .../distlib/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 27305 bytes .../pip/_vendor/distlib/compat.py | 1116 + .../pip/_vendor/distlib/database.py | 1345 + .../pip/_vendor/distlib/index.py | 509 + .../pip/_vendor/distlib/locators.py | 1300 + .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 152 + .../pip/_vendor/distlib/metadata.py | 1058 + .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 429 + .../site-packages/pip/_vendor/distlib/util.py | 1932 ++ .../pip/_vendor/distlib/version.py | 739 + .../pip/_vendor/distlib/wheel.py | 1053 + .../site-packages/pip/_vendor/distro.py | 1386 + .../pip/_vendor/html5lib/__init__.py | 35 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1298 bytes .../__pycache__/_ihatexml.cpython-310.pyc | Bin 0 -> 13853 bytes .../__pycache__/_inputstream.cpython-310.pyc | Bin 0 -> 21670 bytes .../__pycache__/_tokenizer.cpython-310.pyc | Bin 0 -> 37316 bytes .../__pycache__/_utils.cpython-310.pyc | Bin 0 -> 4792 bytes .../__pycache__/constants.cpython-310.pyc | Bin 0 -> 161257 bytes .../__pycache__/html5parser.cpython-310.pyc | Bin 0 -> 88467 bytes .../__pycache__/serializer.cpython-310.pyc | Bin 0 -> 10733 bytes .../pip/_vendor/html5lib/_ihatexml.py | 289 + .../pip/_vendor/html5lib/_inputstream.py | 918 + .../pip/_vendor/html5lib/_tokenizer.py | 1735 + .../pip/_vendor/html5lib/_trie/__init__.py | 5 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 348 bytes .../_trie/__pycache__/_base.cpython-310.pyc | Bin 0 -> 1600 bytes .../_trie/__pycache__/py.cpython-310.pyc | Bin 0 -> 2263 bytes .../pip/_vendor/html5lib/_trie/_base.py | 40 + .../pip/_vendor/html5lib/_trie/py.py | 67 + .../pip/_vendor/html5lib/_utils.py | 159 + .../pip/_vendor/html5lib/constants.py | 2946 ++ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 196 bytes .../alphabeticalattributes.cpython-310.pyc | Bin 0 -> 1326 bytes .../filters/__pycache__/base.cpython-310.pyc | Bin 0 -> 866 bytes .../inject_meta_charset.cpython-310.pyc | Bin 0 -> 1864 bytes .../filters/__pycache__/lint.cpython-310.pyc | Bin 0 -> 2572 bytes .../__pycache__/optionaltags.cpython-310.pyc | Bin 0 -> 2723 bytes .../__pycache__/sanitizer.cpython-310.pyc | Bin 0 -> 20020 bytes .../__pycache__/whitespace.cpython-310.pyc | Bin 0 -> 1370 bytes .../filters/alphabeticalattributes.py | 29 + .../pip/_vendor/html5lib/filters/base.py | 12 + .../html5lib/filters/inject_meta_charset.py | 73 + .../pip/_vendor/html5lib/filters/lint.py | 93 + .../_vendor/html5lib/filters/optionaltags.py | 207 + .../pip/_vendor/html5lib/filters/sanitizer.py | 916 + .../_vendor/html5lib/filters/whitespace.py | 38 + .../pip/_vendor/html5lib/html5parser.py | 2795 ++ .../pip/_vendor/html5lib/serializer.py | 409 + .../_vendor/html5lib/treeadapters/__init__.py | 30 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 937 bytes .../__pycache__/genshi.cpython-310.pyc | Bin 0 -> 1549 bytes .../__pycache__/sax.cpython-310.pyc | Bin 0 -> 1456 bytes .../_vendor/html5lib/treeadapters/genshi.py | 54 + .../pip/_vendor/html5lib/treeadapters/sax.py | 50 + .../_vendor/html5lib/treebuilders/__init__.py | 88 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 3328 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 11319 bytes .../__pycache__/dom.cpython-310.pyc | Bin 0 -> 9406 bytes .../__pycache__/etree.cpython-310.pyc | Bin 0 -> 11708 bytes .../__pycache__/etree_lxml.cpython-310.pyc | Bin 0 -> 13023 bytes .../pip/_vendor/html5lib/treebuilders/base.py | 417 + .../pip/_vendor/html5lib/treebuilders/dom.py | 239 + .../_vendor/html5lib/treebuilders/etree.py | 343 + .../html5lib/treebuilders/etree_lxml.py | 392 + .../_vendor/html5lib/treewalkers/__init__.py | 154 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 3978 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 6939 bytes .../__pycache__/dom.cpython-310.pyc | Bin 0 -> 1710 bytes .../__pycache__/etree.cpython-310.pyc | Bin 0 -> 3468 bytes .../__pycache__/etree_lxml.cpython-310.pyc | Bin 0 -> 6555 bytes .../__pycache__/genshi.cpython-310.pyc | Bin 0 -> 1916 bytes .../pip/_vendor/html5lib/treewalkers/base.py | 252 + .../pip/_vendor/html5lib/treewalkers/dom.py | 43 + .../pip/_vendor/html5lib/treewalkers/etree.py | 131 + .../html5lib/treewalkers/etree_lxml.py | 215 + .../_vendor/html5lib/treewalkers/genshi.py | 69 + .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 843 bytes .../idna/__pycache__/codec.cpython-310.pyc | Bin 0 -> 2814 bytes .../idna/__pycache__/compat.cpython-310.pyc | Bin 0 -> 743 bytes .../idna/__pycache__/core.cpython-310.pyc | Bin 0 -> 9558 bytes .../idna/__pycache__/idnadata.cpython-310.pyc | Bin 0 -> 38221 bytes .../__pycache__/intranges.cpython-310.pyc | Bin 0 -> 1980 bytes .../__pycache__/package_data.cpython-310.pyc | Bin 0 -> 207 bytes .../__pycache__/uts46data.cpython-310.pyc | Bin 0 -> 150942 bytes .../site-packages/pip/_vendor/idna/codec.py | 112 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 397 + .../pip/_vendor/idna/idnadata.py | 2137 ++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../pip/_vendor/idna/uts46data.py | 8512 +++++ .../pip/_vendor/msgpack/__init__.py | 54 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1423 bytes .../__pycache__/_version.cpython-310.pyc | Bin 0 -> 214 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 1804 bytes .../msgpack/__pycache__/ext.cpython-310.pyc | Bin 0 -> 6312 bytes .../__pycache__/fallback.cpython-310.pyc | Bin 0 -> 25441 bytes .../pip/_vendor/msgpack/_version.py | 1 + .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 193 + .../pip/_vendor/msgpack/fallback.py | 1012 + .../pip/_vendor/packaging/__about__.py | 26 + .../pip/_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-310.pyc | Bin 0 -> 586 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 442 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 0 -> 7296 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 0 -> 4608 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 0 -> 2701 bytes .../__pycache__/markers.cpython-310.pyc | Bin 0 -> 9283 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 0 -> 3971 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 0 -> 21523 bytes .../__pycache__/tags.cpython-310.pyc | Bin 0 -> 12186 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 3571 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 12921 bytes .../pip/_vendor/packaging/_manylinux.py | 301 + .../pip/_vendor/packaging/_musllinux.py | 136 + .../pip/_vendor/packaging/_structures.py | 61 + .../pip/_vendor/packaging/markers.py | 304 + .../pip/_vendor/packaging/requirements.py | 146 + .../pip/_vendor/packaging/specifiers.py | 802 + .../pip/_vendor/packaging/tags.py | 487 + .../pip/_vendor/packaging/utils.py | 136 + .../pip/_vendor/packaging/version.py | 504 + .../pip/_vendor/pep517/__init__.py | 6 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 309 bytes .../pep517/__pycache__/build.cpython-310.pyc | Bin 0 -> 3592 bytes .../pep517/__pycache__/check.cpython-310.pyc | Bin 0 -> 4556 bytes .../__pycache__/colorlog.cpython-310.pyc | Bin 0 -> 2960 bytes .../pep517/__pycache__/compat.cpython-310.pyc | Bin 0 -> 1533 bytes .../__pycache__/dirtools.cpython-310.pyc | Bin 0 -> 1351 bytes .../__pycache__/envbuild.cpython-310.pyc | Bin 0 -> 4374 bytes .../pep517/__pycache__/meta.cpython-310.pyc | Bin 0 -> 2956 bytes .../__pycache__/wrappers.cpython-310.pyc | Bin 0 -> 12302 bytes .../site-packages/pip/_vendor/pep517/build.py | 127 + .../site-packages/pip/_vendor/pep517/check.py | 207 + .../pip/_vendor/pep517/colorlog.py | 115 + .../pip/_vendor/pep517/compat.py | 51 + .../pip/_vendor/pep517/dirtools.py | 44 + .../pip/_vendor/pep517/envbuild.py | 171 + .../pip/_vendor/pep517/in_process/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 917 bytes .../__pycache__/_in_process.cpython-310.pyc | Bin 0 -> 10064 bytes .../_vendor/pep517/in_process/_in_process.py | 363 + .../site-packages/pip/_vendor/pep517/meta.py | 92 + .../pip/_vendor/pep517/wrappers.py | 375 + .../pip/_vendor/pkg_resources/__init__.py | 3296 ++ .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 99872 bytes .../__pycache__/py31compat.cpython-310.pyc | Bin 0 -> 656 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/platformdirs/__init__.py | 331 + .../pip/_vendor/platformdirs/__main__.py | 46 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 10472 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 1232 bytes .../__pycache__/android.cpython-310.pyc | Bin 0 -> 4264 bytes .../__pycache__/api.cpython-310.pyc | Bin 0 -> 5198 bytes .../__pycache__/macos.cpython-310.pyc | Bin 0 -> 3186 bytes .../__pycache__/unix.cpython-310.pyc | Bin 0 -> 6887 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 291 bytes .../__pycache__/windows.cpython-310.pyc | Bin 0 -> 6430 bytes .../pip/_vendor/platformdirs/android.py | 119 + .../pip/_vendor/platformdirs/api.py | 156 + .../pip/_vendor/platformdirs/macos.py | 64 + .../pip/_vendor/platformdirs/unix.py | 181 + .../pip/_vendor/platformdirs/version.py | 4 + .../pip/_vendor/platformdirs/windows.py | 182 + .../pip/_vendor/progress/__init__.py | 189 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 5726 bytes .../progress/__pycache__/bar.cpython-310.pyc | Bin 0 -> 2691 bytes .../__pycache__/colors.cpython-310.pyc | Bin 0 -> 1484 bytes .../__pycache__/counter.cpython-310.pyc | Bin 0 -> 1555 bytes .../__pycache__/spinner.cpython-310.pyc | Bin 0 -> 1385 bytes .../site-packages/pip/_vendor/progress/bar.py | 93 + .../pip/_vendor/progress/colors.py | 79 + .../pip/_vendor/progress/counter.py | 47 + .../pip/_vendor/progress/spinner.py | 45 + .../pip/_vendor/pygments/__init__.py | 83 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2988 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 584 bytes .../__pycache__/cmdline.cpython-310.pyc | Bin 0 -> 15447 bytes .../__pycache__/console.cpython-310.pyc | Bin 0 -> 1879 bytes .../__pycache__/filter.cpython-310.pyc | Bin 0 -> 2650 bytes .../__pycache__/formatter.cpython-310.pyc | Bin 0 -> 3006 bytes .../__pycache__/lexer.cpython-310.pyc | Bin 0 -> 24360 bytes .../__pycache__/modeline.cpython-310.pyc | Bin 0 -> 1188 bytes .../__pycache__/plugin.cpython-310.pyc | Bin 0 -> 2040 bytes .../__pycache__/regexopt.cpython-310.pyc | Bin 0 -> 2952 bytes .../__pycache__/scanner.cpython-310.pyc | Bin 0 -> 3553 bytes .../__pycache__/sphinxext.cpython-310.pyc | Bin 0 -> 4538 bytes .../__pycache__/style.cpython-310.pyc | Bin 0 -> 4575 bytes .../__pycache__/token.cpython-310.pyc | Bin 0 -> 4647 bytes .../__pycache__/unistring.cpython-310.pyc | Bin 0 -> 31201 bytes .../pygments/__pycache__/util.cpython-310.pyc | Bin 0 -> 9158 bytes .../pip/_vendor/pygments/cmdline.py | 663 + .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 71 + .../pip/_vendor/pygments/filters/__init__.py | 937 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 29509 bytes .../pip/_vendor/pygments/formatter.py | 94 + .../_vendor/pygments/formatters/__init__.py | 153 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 4664 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 0 -> 5531 bytes .../__pycache__/bbcode.cpython-310.pyc | Bin 0 -> 3081 bytes .../__pycache__/groff.cpython-310.pyc | Bin 0 -> 4354 bytes .../__pycache__/html.cpython-310.pyc | Bin 0 -> 29065 bytes .../__pycache__/img.cpython-310.pyc | Bin 0 -> 17493 bytes .../__pycache__/irc.cpython-310.pyc | Bin 0 -> 4584 bytes .../__pycache__/latex.cpython-310.pyc | Bin 0 -> 13490 bytes .../__pycache__/other.cpython-310.pyc | Bin 0 -> 4800 bytes .../__pycache__/pangomarkup.cpython-310.pyc | Bin 0 -> 2100 bytes .../__pycache__/rtf.cpython-310.pyc | Bin 0 -> 4130 bytes .../__pycache__/svg.cpython-310.pyc | Bin 0 -> 6328 bytes .../__pycache__/terminal.cpython-310.pyc | Bin 0 -> 3995 bytes .../__pycache__/terminal256.cpython-310.pyc | Bin 0 -> 9245 bytes .../_vendor/pygments/formatters/_mapping.py | 84 + .../pip/_vendor/pygments/formatters/bbcode.py | 108 + .../pip/_vendor/pygments/formatters/groff.py | 168 + .../pip/_vendor/pygments/formatters/html.py | 983 + .../pip/_vendor/pygments/formatters/img.py | 641 + .../pip/_vendor/pygments/formatters/irc.py | 179 + .../pip/_vendor/pygments/formatters/latex.py | 511 + .../pip/_vendor/pygments/formatters/other.py | 161 + .../pygments/formatters/pangomarkup.py | 83 + .../pip/_vendor/pygments/formatters/rtf.py | 146 + .../pip/_vendor/pygments/formatters/svg.py | 188 + .../_vendor/pygments/formatters/terminal.py | 127 + .../pygments/formatters/terminal256.py | 338 + .../pip/_vendor/pygments/lexer.py | 879 + .../pip/_vendor/pygments/lexers/__init__.py | 341 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 9180 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 0 -> 58118 bytes .../lexers/__pycache__/python.cpython-310.pyc | Bin 0 -> 29379 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 580 + .../pip/_vendor/pygments/lexers/python.py | 1188 + .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 69 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 155 + .../pip/_vendor/pygments/style.py | 197 + .../pip/_vendor/pygments/styles/__init__.py | 93 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 3216 bytes .../pip/_vendor/pygments/token.py | 212 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 308 + .../pip/_vendor/pyparsing/__init__.py | 328 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 7121 bytes .../__pycache__/actions.cpython-310.pyc | Bin 0 -> 7178 bytes .../__pycache__/common.cpython-310.pyc | Bin 0 -> 10101 bytes .../__pycache__/core.cpython-310.pyc | Bin 0 -> 175231 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 9068 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 0 -> 34763 bytes .../__pycache__/results.cpython-310.pyc | Bin 0 -> 24775 bytes .../__pycache__/testing.cpython-310.pyc | Bin 0 -> 12096 bytes .../__pycache__/unicode.cpython-310.pyc | Bin 0 -> 9810 bytes .../__pycache__/util.cpython-310.pyc | Bin 0 -> 8601 bytes .../pip/_vendor/pyparsing/actions.py | 207 + .../pip/_vendor/pyparsing/common.py | 424 + .../pip/_vendor/pyparsing/core.py | 5789 ++++ .../pip/_vendor/pyparsing/diagram/__init__.py | 593 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 15641 bytes .../pip/_vendor/pyparsing/exceptions.py | 267 + .../pip/_vendor/pyparsing/helpers.py | 1069 + .../pip/_vendor/pyparsing/results.py | 760 + .../pip/_vendor/pyparsing/testing.py | 331 + .../pip/_vendor/pyparsing/unicode.py | 332 + .../pip/_vendor/pyparsing/util.py | 235 + .../pip/_vendor/requests/__init__.py | 154 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 4034 bytes .../__pycache__/__version__.cpython-310.pyc | Bin 0 -> 551 bytes .../_internal_utils.cpython-310.pyc | Bin 0 -> 1303 bytes .../__pycache__/adapters.cpython-310.pyc | Bin 0 -> 17039 bytes .../requests/__pycache__/api.cpython-310.pyc | Bin 0 -> 6650 bytes .../requests/__pycache__/auth.cpython-310.pyc | Bin 0 -> 8093 bytes .../__pycache__/certs.cpython-310.pyc | Bin 0 -> 635 bytes .../__pycache__/compat.cpython-310.pyc | Bin 0 -> 1670 bytes .../__pycache__/cookies.cpython-310.pyc | Bin 0 -> 18683 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 5244 bytes .../requests/__pycache__/help.cpython-310.pyc | Bin 0 -> 2903 bytes .../__pycache__/hooks.cpython-310.pyc | Bin 0 -> 990 bytes .../__pycache__/models.cpython-310.pyc | Bin 0 -> 24309 bytes .../__pycache__/packages.cpython-310.pyc | Bin 0 -> 504 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 0 -> 19617 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 0 -> 4667 bytes .../__pycache__/structures.cpython-310.pyc | Bin 0 -> 4449 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 24392 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 42 + .../pip/_vendor/requests/adapters.py | 538 + .../site-packages/pip/_vendor/requests/api.py | 159 + .../pip/_vendor/requests/auth.py | 305 + .../pip/_vendor/requests/certs.py | 18 + .../pip/_vendor/requests/compat.py | 77 + .../pip/_vendor/requests/cookies.py | 549 + .../pip/_vendor/requests/exceptions.py | 133 + .../pip/_vendor/requests/help.py | 132 + .../pip/_vendor/requests/hooks.py | 34 + .../pip/_vendor/requests/models.py | 973 + .../pip/_vendor/requests/packages.py | 16 + .../pip/_vendor/requests/sessions.py | 771 + .../pip/_vendor/requests/status_codes.py | 123 + .../pip/_vendor/requests/structures.py | 105 + .../pip/_vendor/requests/utils.py | 1060 + .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 602 bytes .../__pycache__/providers.cpython-310.pyc | Bin 0 -> 6653 bytes .../__pycache__/reporters.cpython-310.pyc | Bin 0 -> 2573 bytes .../__pycache__/resolvers.cpython-310.pyc | Bin 0 -> 15126 bytes .../__pycache__/structs.cpython-310.pyc | Bin 0 -> 7159 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 197 bytes .../collections_abc.cpython-310.pyc | Bin 0 -> 373 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/reporters.py | 43 + .../pip/_vendor/resolvelib/resolvers.py | 482 + .../pip/_vendor/resolvelib/structs.py | 165 + .../pip/_vendor/rich/__init__.py | 172 + .../pip/_vendor/rich/__main__.py | 280 + .../rich/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 5887 bytes .../rich/__pycache__/__main__.cpython-310.pyc | Bin 0 -> 7321 bytes .../__pycache__/_cell_widths.cpython-310.pyc | Bin 0 -> 7810 bytes .../__pycache__/_emoji_codes.cpython-310.pyc | Bin 0 -> 360050 bytes .../_emoji_replace.cpython-310.pyc | Bin 0 -> 1190 bytes .../__pycache__/_extension.cpython-310.pyc | Bin 0 -> 491 bytes .../rich/__pycache__/_inspect.cpython-310.pyc | Bin 0 -> 6608 bytes .../__pycache__/_log_render.cpython-310.pyc | Bin 0 -> 2636 bytes .../rich/__pycache__/_loop.cpython-310.pyc | Bin 0 -> 1288 bytes .../__pycache__/_lru_cache.cpython-310.pyc | Bin 0 -> 1571 bytes .../__pycache__/_palettes.cpython-310.pyc | Bin 0 -> 5093 bytes .../rich/__pycache__/_pick.cpython-310.pyc | Bin 0 -> 636 bytes .../rich/__pycache__/_ratio.cpython-310.pyc | Bin 0 -> 5153 bytes .../__pycache__/_spinners.cpython-310.pyc | Bin 0 -> 15209 bytes .../rich/__pycache__/_stack.cpython-310.pyc | Bin 0 -> 834 bytes .../rich/__pycache__/_timer.cpython-310.pyc | Bin 0 -> 683 bytes .../rich/__pycache__/_windows.cpython-310.pyc | Bin 0 -> 1874 bytes .../rich/__pycache__/_wrap.cpython-310.pyc | Bin 0 -> 1512 bytes .../rich/__pycache__/abc.cpython-310.pyc | Bin 0 -> 1310 bytes .../rich/__pycache__/align.cpython-310.pyc | Bin 0 -> 7964 bytes .../rich/__pycache__/ansi.cpython-310.pyc | Bin 0 -> 6013 bytes .../rich/__pycache__/bar.cpython-310.pyc | Bin 0 -> 2979 bytes .../rich/__pycache__/box.cpython-310.pyc | Bin 0 -> 7753 bytes .../rich/__pycache__/cells.cpython-310.pyc | Bin 0 -> 3495 bytes .../rich/__pycache__/color.cpython-310.pyc | Bin 0 -> 16751 bytes .../__pycache__/color_triplet.cpython-310.pyc | Bin 0 -> 1433 bytes .../rich/__pycache__/columns.cpython-310.pyc | Bin 0 -> 6193 bytes .../rich/__pycache__/console.cpython-310.pyc | Bin 0 -> 70438 bytes .../__pycache__/constrain.cpython-310.pyc | Bin 0 -> 1750 bytes .../__pycache__/containers.cpython-310.pyc | Bin 0 -> 6482 bytes .../rich/__pycache__/control.cpython-310.pyc | Bin 0 -> 6825 bytes .../default_styles.cpython-310.pyc | Bin 0 -> 6025 bytes .../rich/__pycache__/diagnose.cpython-310.pyc | Bin 0 -> 351 bytes .../rich/__pycache__/emoji.cpython-310.pyc | Bin 0 -> 3263 bytes .../rich/__pycache__/errors.cpython-310.pyc | Bin 0 -> 1523 bytes .../__pycache__/file_proxy.cpython-310.pyc | Bin 0 -> 2260 bytes .../rich/__pycache__/filesize.cpython-310.pyc | Bin 0 -> 2612 bytes .../__pycache__/highlighter.cpython-310.pyc | Bin 0 -> 5339 bytes .../rich/__pycache__/json.cpython-310.pyc | Bin 0 -> 4743 bytes .../rich/__pycache__/jupyter.cpython-310.pyc | Bin 0 -> 3822 bytes .../rich/__pycache__/layout.cpython-310.pyc | Bin 0 -> 14674 bytes .../rich/__pycache__/live.cpython-310.pyc | Bin 0 -> 11564 bytes .../__pycache__/live_render.cpython-310.pyc | Bin 0 -> 3398 bytes .../rich/__pycache__/logging.cpython-310.pyc | Bin 0 -> 9290 bytes .../rich/__pycache__/markup.cpython-310.pyc | Bin 0 -> 5909 bytes .../rich/__pycache__/measure.cpython-310.pyc | Bin 0 -> 5054 bytes .../rich/__pycache__/padding.cpython-310.pyc | Bin 0 -> 4478 bytes .../rich/__pycache__/pager.cpython-310.pyc | Bin 0 -> 1491 bytes .../rich/__pycache__/palette.cpython-310.pyc | Bin 0 -> 3704 bytes .../rich/__pycache__/panel.cpython-310.pyc | Bin 0 -> 6387 bytes .../rich/__pycache__/pretty.cpython-310.pyc | Bin 0 -> 25099 bytes .../rich/__pycache__/progress.cpython-310.pyc | Bin 0 -> 33327 bytes .../__pycache__/progress_bar.cpython-310.pyc | Bin 0 -> 6703 bytes .../rich/__pycache__/prompt.cpython-310.pyc | Bin 0 -> 11295 bytes .../rich/__pycache__/protocol.cpython-310.pyc | Bin 0 -> 1367 bytes .../rich/__pycache__/region.cpython-310.pyc | Bin 0 -> 523 bytes .../rich/__pycache__/repr.cpython-310.pyc | Bin 0 -> 4036 bytes .../rich/__pycache__/rule.cpython-310.pyc | Bin 0 -> 3733 bytes .../rich/__pycache__/scope.cpython-310.pyc | Bin 0 -> 2984 bytes .../rich/__pycache__/screen.cpython-310.pyc | Bin 0 -> 1875 bytes .../rich/__pycache__/segment.cpython-310.pyc | Bin 0 -> 20565 bytes .../rich/__pycache__/spinner.cpython-310.pyc | Bin 0 -> 4395 bytes .../rich/__pycache__/status.cpython-310.pyc | Bin 0 -> 4589 bytes .../rich/__pycache__/style.cpython-310.pyc | Bin 0 -> 20518 bytes .../rich/__pycache__/styled.cpython-310.pyc | Bin 0 -> 1759 bytes .../rich/__pycache__/syntax.cpython-310.pyc | Bin 0 -> 19032 bytes .../rich/__pycache__/table.cpython-310.pyc | Bin 0 -> 26970 bytes .../rich/__pycache__/tabulate.cpython-310.pyc | Bin 0 -> 1752 bytes .../terminal_theme.cpython-310.pyc | Bin 0 -> 1716 bytes .../rich/__pycache__/text.cpython-310.pyc | Bin 0 -> 39280 bytes .../rich/__pycache__/theme.cpython-310.pyc | Bin 0 -> 4696 bytes .../rich/__pycache__/themes.cpython-310.pyc | Bin 0 -> 289 bytes .../__pycache__/traceback.cpython-310.pyc | Bin 0 -> 19533 bytes .../rich/__pycache__/tree.cpython-310.pyc | Bin 0 -> 7313 bytes .../pip/_vendor/rich/_cell_widths.py | 451 + .../pip/_vendor/rich/_emoji_codes.py | 3610 +++ .../pip/_vendor/rich/_emoji_replace.py | 32 + .../pip/_vendor/rich/_extension.py | 10 + .../pip/_vendor/rich/_inspect.py | 210 + .../pip/_vendor/rich/_log_render.py | 94 + .../site-packages/pip/_vendor/rich/_loop.py | 43 + .../pip/_vendor/rich/_lru_cache.py | 34 + .../pip/_vendor/rich/_palettes.py | 309 + .../site-packages/pip/_vendor/rich/_pick.py | 17 + .../site-packages/pip/_vendor/rich/_ratio.py | 160 + .../pip/_vendor/rich/_spinners.py | 848 + .../site-packages/pip/_vendor/rich/_stack.py | 16 + .../site-packages/pip/_vendor/rich/_timer.py | 19 + .../pip/_vendor/rich/_windows.py | 72 + .../site-packages/pip/_vendor/rich/_wrap.py | 55 + .../site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 312 + .../site-packages/pip/_vendor/rich/ansi.py | 228 + .../site-packages/pip/_vendor/rich/bar.py | 94 + .../site-packages/pip/_vendor/rich/box.py | 483 + .../site-packages/pip/_vendor/rich/cells.py | 147 + .../site-packages/pip/_vendor/rich/color.py | 581 + .../pip/_vendor/rich/color_triplet.py | 38 + .../site-packages/pip/_vendor/rich/columns.py | 187 + .../site-packages/pip/_vendor/rich/console.py | 2211 ++ .../pip/_vendor/rich/constrain.py | 37 + .../pip/_vendor/rich/containers.py | 167 + .../site-packages/pip/_vendor/rich/control.py | 175 + .../pip/_vendor/rich/default_styles.py | 183 + .../pip/_vendor/rich/diagnose.py | 6 + .../site-packages/pip/_vendor/rich/emoji.py | 96 + .../site-packages/pip/_vendor/rich/errors.py | 34 + .../pip/_vendor/rich/file_proxy.py | 54 + .../pip/_vendor/rich/filesize.py | 89 + .../pip/_vendor/rich/highlighter.py | 147 + .../site-packages/pip/_vendor/rich/json.py | 140 + .../site-packages/pip/_vendor/rich/jupyter.py | 92 + .../site-packages/pip/_vendor/rich/layout.py | 444 + .../site-packages/pip/_vendor/rich/live.py | 365 + .../pip/_vendor/rich/live_render.py | 113 + .../site-packages/pip/_vendor/rich/logging.py | 268 + .../site-packages/pip/_vendor/rich/markup.py | 244 + .../site-packages/pip/_vendor/rich/measure.py | 149 + .../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 | 250 + .../site-packages/pip/_vendor/rich/pretty.py | 903 + .../pip/_vendor/rich/progress.py | 1036 + .../pip/_vendor/rich/progress_bar.py | 216 + .../site-packages/pip/_vendor/rich/prompt.py | 376 + .../pip/_vendor/rich/protocol.py | 42 + .../site-packages/pip/_vendor/rich/region.py | 10 + .../site-packages/pip/_vendor/rich/repr.py | 151 + .../site-packages/pip/_vendor/rich/rule.py | 115 + .../site-packages/pip/_vendor/rich/scope.py | 86 + .../site-packages/pip/_vendor/rich/screen.py | 54 + .../site-packages/pip/_vendor/rich/segment.py | 720 + .../site-packages/pip/_vendor/rich/spinner.py | 134 + .../site-packages/pip/_vendor/rich/status.py | 132 + .../site-packages/pip/_vendor/rich/style.py | 785 + .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 735 + .../site-packages/pip/_vendor/rich/table.py | 968 + .../pip/_vendor/rich/tabulate.py | 51 + .../pip/_vendor/rich/terminal_theme.py | 55 + .../site-packages/pip/_vendor/rich/text.py | 1282 + .../site-packages/pip/_vendor/rich/theme.py | 112 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 678 + .../site-packages/pip/_vendor/rich/tree.py | 249 + .../site-packages/pip/_vendor/six.py | 998 + .../pip/_vendor/tenacity/__init__.py | 517 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 16370 bytes .../__pycache__/_asyncio.cpython-310.pyc | Bin 0 -> 2610 bytes .../__pycache__/_utils.cpython-310.pyc | Bin 0 -> 1223 bytes .../__pycache__/after.cpython-310.pyc | Bin 0 -> 1227 bytes .../__pycache__/before.cpython-310.pyc | Bin 0 -> 1105 bytes .../__pycache__/before_sleep.cpython-310.pyc | Bin 0 -> 1407 bytes .../tenacity/__pycache__/nap.cpython-310.pyc | Bin 0 -> 1195 bytes .../__pycache__/retry.cpython-310.pyc | Bin 0 -> 8425 bytes .../tenacity/__pycache__/stop.cpython-310.pyc | Bin 0 -> 4013 bytes .../__pycache__/tornadoweb.cpython-310.pyc | Bin 0 -> 1760 bytes .../tenacity/__pycache__/wait.cpython-310.pyc | Bin 0 -> 7957 bytes .../pip/_vendor/tenacity/_asyncio.py | 92 + .../pip/_vendor/tenacity/_utils.py | 68 + .../pip/_vendor/tenacity/after.py | 46 + .../pip/_vendor/tenacity/before.py | 41 + .../pip/_vendor/tenacity/before_sleep.py | 58 + .../site-packages/pip/_vendor/tenacity/nap.py | 43 + .../pip/_vendor/tenacity/retry.py | 213 + .../pip/_vendor/tenacity/stop.py | 96 + .../pip/_vendor/tenacity/tornadoweb.py | 59 + .../pip/_vendor/tenacity/wait.py | 191 + .../pip/_vendor/tomli/__init__.py | 6 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 375 bytes .../tomli/__pycache__/_parser.cpython-310.pyc | Bin 0 -> 16329 bytes .../tomli/__pycache__/_re.cpython-310.pyc | Bin 0 -> 2419 bytes .../pip/_vendor/tomli/_parser.py | 703 + .../site-packages/pip/_vendor/tomli/_re.py | 83 + .../pip/_vendor/typing_extensions.py | 2296 ++ .../pip/_vendor/urllib3/__init__.py | 85 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2185 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 0 -> 11350 bytes .../__pycache__/_version.cpython-310.pyc | Bin 0 -> 209 bytes .../__pycache__/connection.cpython-310.pyc | Bin 0 -> 13632 bytes .../connectionpool.cpython-310.pyc | Bin 0 -> 25474 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 10990 bytes .../__pycache__/fields.cpython-310.pyc | Bin 0 -> 8179 bytes .../__pycache__/filepost.cpython-310.pyc | Bin 0 -> 2746 bytes .../__pycache__/poolmanager.cpython-310.pyc | Bin 0 -> 15294 bytes .../__pycache__/request.cpython-310.pyc | Bin 0 -> 5622 bytes .../__pycache__/response.cpython-310.pyc | Bin 0 -> 20913 bytes .../pip/_vendor/urllib3/_collections.py | 355 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 569 + .../pip/_vendor/urllib3/connectionpool.py | 1113 + .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 195 bytes .../_appengine_environ.cpython-310.pyc | Bin 0 -> 1375 bytes .../__pycache__/appengine.cpython-310.pyc | Bin 0 -> 8191 bytes .../__pycache__/ntlmpool.cpython-310.pyc | Bin 0 -> 3630 bytes .../__pycache__/pyopenssl.cpython-310.pyc | Bin 0 -> 15532 bytes .../securetransport.cpython-310.pyc | Bin 0 -> 21937 bytes .../contrib/__pycache__/socks.cpython-310.pyc | Bin 0 -> 5597 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 212 bytes .../__pycache__/bindings.cpython-310.pyc | Bin 0 -> 10708 bytes .../__pycache__/low_level.cpython-310.pyc | Bin 0 -> 9095 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 | 511 + .../urllib3/contrib/securetransport.py | 922 + .../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-310.pyc | Bin 0 -> 196 bytes .../packages/__pycache__/six.cpython-310.pyc | Bin 0 -> 27650 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 206 bytes .../__pycache__/makefile.cpython-310.pyc | Bin 0 -> 1306 bytes .../urllib3/packages/backports/makefile.py | 51 + .../pip/_vendor/urllib3/packages/six.py | 1077 + .../pip/_vendor/urllib3/poolmanager.py | 539 + .../pip/_vendor/urllib3/request.py | 170 + .../pip/_vendor/urllib3/response.py | 821 + .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1105 bytes .../__pycache__/connection.cpython-310.pyc | Bin 0 -> 3433 bytes .../util/__pycache__/proxy.cpython-310.pyc | Bin 0 -> 1338 bytes .../util/__pycache__/queue.cpython-310.pyc | Bin 0 -> 1060 bytes .../util/__pycache__/request.cpython-310.pyc | Bin 0 -> 3468 bytes .../util/__pycache__/response.cpython-310.pyc | Bin 0 -> 2353 bytes .../util/__pycache__/retry.cpython-310.pyc | Bin 0 -> 16148 bytes .../util/__pycache__/ssl_.cpython-310.pyc | Bin 0 -> 11305 bytes .../ssl_match_hostname.cpython-310.pyc | Bin 0 -> 3277 bytes .../__pycache__/ssltransport.cpython-310.pyc | Bin 0 -> 7395 bytes .../util/__pycache__/timeout.cpython-310.pyc | Bin 0 -> 8929 bytes .../util/__pycache__/url.cpython-310.pyc | Bin 0 -> 10674 bytes .../util/__pycache__/wait.cpython-310.pyc | Bin 0 -> 3089 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 | 143 + .../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 | 161 + .../pip/_vendor/urllib3/util/ssltransport.py | 221 + .../pip/_vendor/urllib3/util/timeout.py | 268 + .../pip/_vendor/urllib3/util/url.py | 432 + .../pip/_vendor/urllib3/util/wait.py | 153 + .../site-packages/pip/_vendor/vendor.txt | 25 + .../pip/_vendor/webencodings/__init__.py | 342 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 9742 bytes .../__pycache__/labels.cpython-310.pyc | Bin 0 -> 5232 bytes .../__pycache__/mklabels.cpython-310.pyc | Bin 0 -> 1937 bytes .../__pycache__/tests.cpython-310.pyc | Bin 0 -> 5039 bytes .../x_user_defined.cpython-310.pyc | Bin 0 -> 2588 bytes .../pip/_vendor/webencodings/labels.py | 231 + .../pip/_vendor/webencodings/mklabels.py | 59 + .../pip/_vendor/webencodings/tests.py | 153 + .../_vendor/webencodings/x_user_defined.py | 325 + .../lib/python3.10/site-packages/pip/py.typed | 4 + .../site-packages/pkg_resources/__init__.py | 3303 ++ .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 100597 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 189 bytes .../__pycache__/appdirs.cpython-310.pyc | Bin 0 -> 20250 bytes .../__pycache__/pyparsing.cpython-310.pyc | Bin 0 -> 198742 bytes .../pkg_resources/_vendor/appdirs.py | 608 + .../_vendor/packaging/__about__.py | 26 + .../_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-310.pyc | Bin 0 -> 596 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 452 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 0 -> 7306 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 0 -> 4618 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 0 -> 2976 bytes .../__pycache__/markers.cpython-310.pyc | Bin 0 -> 9302 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 0 -> 3990 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 0 -> 22194 bytes .../__pycache__/tags.cpython-310.pyc | Bin 0 -> 12220 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 3581 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 12931 bytes .../_vendor/packaging/_manylinux.py | 301 + .../_vendor/packaging/_musllinux.py | 136 + .../_vendor/packaging/_structures.py | 67 + .../_vendor/packaging/markers.py | 304 + .../_vendor/packaging/requirements.py | 146 + .../_vendor/packaging/specifiers.py | 828 + .../pkg_resources/_vendor/packaging/tags.py | 484 + .../pkg_resources/_vendor/packaging/utils.py | 136 + .../_vendor/packaging/version.py | 504 + .../pkg_resources/_vendor/pyparsing.py | 5742 ++++ .../pkg_resources/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2897 bytes .../__pycache__/setup.cpython-310.pyc | Bin 0 -> 317 bytes .../data/my-test-package-source/setup.py | 6 + .../setuptools-59.6.0.dist-info/INSTALLER | 1 + .../setuptools-59.6.0.dist-info/LICENSE | 19 + .../setuptools-59.6.0.dist-info/METADATA | 124 + .../setuptools-59.6.0.dist-info/RECORD | 298 + .../setuptools-59.6.0.dist-info/REQUESTED | 0 .../setuptools-59.6.0.dist-info/WHEEL | 5 + .../entry_points.txt | 56 + .../setuptools-59.6.0.dist-info/top_level.txt | 4 + .../site-packages/setuptools/__init__.py | 242 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 8593 bytes .../_deprecation_warning.cpython-310.pyc | Bin 0 -> 550 bytes .../__pycache__/_imp.cpython-310.pyc | Bin 0 -> 2076 bytes .../__pycache__/archive_util.cpython-310.pyc | Bin 0 -> 5846 bytes .../__pycache__/build_meta.cpython-310.pyc | Bin 0 -> 9460 bytes .../__pycache__/config.cpython-310.pyc | Bin 0 -> 20929 bytes .../__pycache__/dep_util.cpython-310.pyc | Bin 0 -> 857 bytes .../__pycache__/depends.cpython-310.pyc | Bin 0 -> 5296 bytes .../__pycache__/dist.cpython-310.pyc | Bin 0 -> 36337 bytes .../__pycache__/errors.cpython-310.pyc | Bin 0 -> 1502 bytes .../__pycache__/extension.cpython-310.pyc | Bin 0 -> 1946 bytes .../__pycache__/glob.cpython-310.pyc | Bin 0 -> 3735 bytes .../__pycache__/installer.cpython-310.pyc | Bin 0 -> 2981 bytes .../__pycache__/launch.cpython-310.pyc | Bin 0 -> 907 bytes .../__pycache__/monkey.cpython-310.pyc | Bin 0 -> 4635 bytes .../__pycache__/msvc.cpython-310.pyc | Bin 0 -> 42639 bytes .../__pycache__/namespaces.cpython-310.pyc | Bin 0 -> 3618 bytes .../__pycache__/package_index.cpython-310.pyc | Bin 0 -> 32731 bytes .../__pycache__/py34compat.cpython-310.pyc | Bin 0 -> 482 bytes .../__pycache__/sandbox.cpython-310.pyc | Bin 0 -> 15758 bytes .../__pycache__/unicode_utils.cpython-310.pyc | Bin 0 -> 1112 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 324 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 0 -> 7350 bytes .../windows_support.cpython-310.pyc | Bin 0 -> 1025 bytes .../setuptools/_deprecation_warning.py | 7 + .../setuptools/_distutils/__init__.py | 24 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 558 bytes .../__pycache__/_msvccompiler.cpython-310.pyc | Bin 0 -> 13835 bytes .../__pycache__/archive_util.cpython-310.pyc | Bin 0 -> 6563 bytes .../__pycache__/bcppcompiler.cpython-310.pyc | Bin 0 -> 6550 bytes .../__pycache__/ccompiler.cpython-310.pyc | Bin 0 -> 33307 bytes .../__pycache__/cmd.cpython-310.pyc | Bin 0 -> 13950 bytes .../__pycache__/config.cpython-310.pyc | Bin 0 -> 3589 bytes .../__pycache__/core.cpython-310.pyc | Bin 0 -> 7090 bytes .../cygwinccompiler.cpython-310.pyc | Bin 0 -> 8997 bytes .../__pycache__/debug.cpython-310.pyc | Bin 0 -> 252 bytes .../__pycache__/dep_util.cpython-310.pyc | Bin 0 -> 2773 bytes .../__pycache__/dir_util.cpython-310.pyc | Bin 0 -> 5884 bytes .../__pycache__/dist.cpython-310.pyc | Bin 0 -> 34049 bytes .../__pycache__/errors.cpython-310.pyc | Bin 0 -> 4994 bytes .../__pycache__/extension.cpython-310.pyc | Bin 0 -> 7008 bytes .../__pycache__/fancy_getopt.cpython-310.pyc | Bin 0 -> 10632 bytes .../__pycache__/file_util.cpython-310.pyc | Bin 0 -> 5978 bytes .../__pycache__/filelist.cpython-310.pyc | Bin 0 -> 10824 bytes .../__pycache__/log.cpython-310.pyc | Bin 0 -> 2309 bytes .../__pycache__/msvc9compiler.cpython-310.pyc | Bin 0 -> 17564 bytes .../__pycache__/msvccompiler.cpython-310.pyc | Bin 0 -> 14783 bytes .../__pycache__/py35compat.cpython-310.pyc | Bin 0 -> 628 bytes .../__pycache__/py38compat.cpython-310.pyc | Bin 0 -> 425 bytes .../__pycache__/spawn.cpython-310.pyc | Bin 0 -> 2895 bytes .../__pycache__/sysconfig.cpython-310.pyc | Bin 0 -> 12876 bytes .../__pycache__/text_file.cpython-310.pyc | Bin 0 -> 8471 bytes .../__pycache__/unixccompiler.cpython-310.pyc | Bin 0 -> 6803 bytes .../__pycache__/util.cpython-310.pyc | Bin 0 -> 14744 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 7845 bytes .../versionpredicate.cpython-310.pyc | Bin 0 -> 5338 bytes .../setuptools/_distutils/_msvccompiler.py | 561 + .../setuptools/_distutils/archive_util.py | 256 + .../setuptools/_distutils/bcppcompiler.py | 393 + .../setuptools/_distutils/ccompiler.py | 1123 + .../setuptools/_distutils/cmd.py | 403 + .../setuptools/_distutils/command/__init__.py | 31 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 531 bytes .../command/__pycache__/bdist.cpython-310.pyc | Bin 0 -> 3665 bytes .../__pycache__/bdist_dumb.cpython-310.pyc | Bin 0 -> 3644 bytes .../__pycache__/bdist_msi.cpython-310.pyc | Bin 0 -> 19720 bytes .../__pycache__/bdist_rpm.cpython-310.pyc | Bin 0 -> 12288 bytes .../__pycache__/bdist_wininst.cpython-310.pyc | Bin 0 -> 8631 bytes .../command/__pycache__/build.cpython-310.pyc | Bin 0 -> 3893 bytes .../__pycache__/build_clib.cpython-310.pyc | Bin 0 -> 4870 bytes .../__pycache__/build_ext.cpython-310.pyc | Bin 0 -> 16218 bytes .../__pycache__/build_py.cpython-310.pyc | Bin 0 -> 9889 bytes .../__pycache__/build_scripts.cpython-310.pyc | Bin 0 -> 4012 bytes .../command/__pycache__/check.cpython-310.pyc | Bin 0 -> 5009 bytes .../command/__pycache__/clean.cpython-310.pyc | Bin 0 -> 2148 bytes .../__pycache__/config.cpython-310.pyc | Bin 0 -> 10330 bytes .../__pycache__/install.cpython-310.pyc | Bin 0 -> 15268 bytes .../__pycache__/install_data.cpython-310.pyc | Bin 0 -> 2347 bytes .../install_egg_info.cpython-310.pyc | Bin 0 -> 3312 bytes .../install_headers.cpython-310.pyc | Bin 0 -> 1770 bytes .../__pycache__/install_lib.cpython-310.pyc | Bin 0 -> 5172 bytes .../install_scripts.cpython-310.pyc | Bin 0 -> 2199 bytes .../__pycache__/py37compat.cpython-310.pyc | Bin 0 -> 1040 bytes .../__pycache__/register.cpython-310.pyc | Bin 0 -> 8683 bytes .../command/__pycache__/sdist.cpython-310.pyc | Bin 0 -> 14499 bytes .../__pycache__/upload.cpython-310.pyc | Bin 0 -> 5375 bytes .../setuptools/_distutils/command/bdist.py | 143 + .../_distutils/command/bdist_dumb.py | 123 + .../_distutils/command/bdist_msi.py | 749 + .../_distutils/command/bdist_rpm.py | 579 + .../_distutils/command/bdist_wininst.py | 377 + .../setuptools/_distutils/command/build.py | 157 + .../_distutils/command/build_clib.py | 209 + .../_distutils/command/build_ext.py | 755 + .../setuptools/_distutils/command/build_py.py | 392 + .../_distutils/command/build_scripts.py | 152 + .../setuptools/_distutils/command/check.py | 148 + .../setuptools/_distutils/command/clean.py | 76 + .../setuptools/_distutils/command/config.py | 344 + .../setuptools/_distutils/command/install.py | 721 + .../_distutils/command/install_data.py | 79 + .../_distutils/command/install_egg_info.py | 84 + .../_distutils/command/install_headers.py | 47 + .../_distutils/command/install_lib.py | 217 + .../_distutils/command/install_scripts.py | 60 + .../_distutils/command/py37compat.py | 30 + .../setuptools/_distutils/command/register.py | 304 + .../setuptools/_distutils/command/sdist.py | 494 + .../setuptools/_distutils/command/upload.py | 214 + .../setuptools/_distutils/config.py | 130 + .../setuptools/_distutils/core.py | 249 + .../setuptools/_distutils/cygwinccompiler.py | 425 + .../setuptools/_distutils/debug.py | 5 + .../setuptools/_distutils/dep_util.py | 92 + .../setuptools/_distutils/dir_util.py | 210 + .../setuptools/_distutils/dist.py | 1257 + .../setuptools/_distutils/errors.py | 97 + .../setuptools/_distutils/extension.py | 240 + .../setuptools/_distutils/fancy_getopt.py | 457 + .../setuptools/_distutils/file_util.py | 238 + .../setuptools/_distutils/filelist.py | 355 + .../setuptools/_distutils/log.py | 77 + .../setuptools/_distutils/msvc9compiler.py | 788 + .../setuptools/_distutils/msvccompiler.py | 643 + .../setuptools/_distutils/py35compat.py | 19 + .../setuptools/_distutils/py38compat.py | 7 + .../setuptools/_distutils/spawn.py | 106 + .../setuptools/_distutils/sysconfig.py | 601 + .../setuptools/_distutils/text_file.py | 286 + .../setuptools/_distutils/unixccompiler.py | 325 + .../setuptools/_distutils/util.py | 548 + .../setuptools/_distutils/version.py | 363 + .../setuptools/_distutils/versionpredicate.py | 169 + .../site-packages/setuptools/_imp.py | 82 + .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 186 bytes .../__pycache__/ordered_set.cpython-310.pyc | Bin 0 -> 16322 bytes .../__pycache__/pyparsing.cpython-310.pyc | Bin 0 -> 198739 bytes .../_vendor/more_itertools/__init__.py | 4 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 267 bytes .../__pycache__/more.cpython-310.pyc | Bin 0 -> 109985 bytes .../__pycache__/recipes.cpython-310.pyc | Bin 0 -> 17967 bytes .../setuptools/_vendor/more_itertools/more.py | 3825 +++ .../_vendor/more_itertools/recipes.py | 620 + .../setuptools/_vendor/ordered_set.py | 488 + .../setuptools/_vendor/packaging/__about__.py | 26 + .../setuptools/_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-310.pyc | Bin 0 -> 593 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 449 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 0 -> 7303 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 0 -> 4615 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 0 -> 2973 bytes .../__pycache__/markers.cpython-310.pyc | Bin 0 -> 9296 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 0 -> 3984 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 0 -> 22191 bytes .../__pycache__/tags.cpython-310.pyc | Bin 0 -> 12217 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 3578 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 12928 bytes .../_vendor/packaging/_manylinux.py | 301 + .../_vendor/packaging/_musllinux.py | 136 + .../_vendor/packaging/_structures.py | 67 + .../setuptools/_vendor/packaging/markers.py | 304 + .../_vendor/packaging/requirements.py | 146 + .../_vendor/packaging/specifiers.py | 828 + .../setuptools/_vendor/packaging/tags.py | 484 + .../setuptools/_vendor/packaging/utils.py | 136 + .../setuptools/_vendor/packaging/version.py | 504 + .../setuptools/_vendor/pyparsing.py | 5742 ++++ .../site-packages/setuptools/archive_util.py | 205 + .../site-packages/setuptools/build_meta.py | 290 + .../site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../site-packages/setuptools/cli-arm64.exe | Bin 0 -> 137216 bytes .../site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 8 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 375 bytes .../command/__pycache__/alias.cpython-310.pyc | Bin 0 -> 2377 bytes .../__pycache__/bdist_egg.cpython-310.pyc | Bin 0 -> 13103 bytes .../__pycache__/bdist_rpm.cpython-310.pyc | Bin 0 -> 1590 bytes .../__pycache__/build_clib.cpython-310.pyc | Bin 0 -> 2464 bytes .../__pycache__/build_ext.cpython-310.pyc | Bin 0 -> 9893 bytes .../__pycache__/build_py.cpython-310.pyc | Bin 0 -> 8266 bytes .../__pycache__/develop.cpython-310.pyc | Bin 0 -> 6153 bytes .../__pycache__/dist_info.cpython-310.pyc | Bin 0 -> 1395 bytes .../__pycache__/easy_install.cpython-310.pyc | Bin 0 -> 65172 bytes .../__pycache__/egg_info.cpython-310.pyc | Bin 0 -> 22751 bytes .../__pycache__/install.cpython-310.pyc | Bin 0 -> 4201 bytes .../install_egg_info.cpython-310.pyc | Bin 0 -> 2926 bytes .../__pycache__/install_lib.cpython-310.pyc | Bin 0 -> 5141 bytes .../install_scripts.cpython-310.pyc | Bin 0 -> 2430 bytes .../__pycache__/py36compat.cpython-310.pyc | Bin 0 -> 4537 bytes .../__pycache__/register.cpython-310.pyc | Bin 0 -> 841 bytes .../__pycache__/rotate.cpython-310.pyc | Bin 0 -> 2508 bytes .../__pycache__/saveopts.cpython-310.pyc | Bin 0 -> 927 bytes .../command/__pycache__/sdist.cpython-310.pyc | Bin 0 -> 6956 bytes .../__pycache__/setopt.cpython-310.pyc | Bin 0 -> 4689 bytes .../command/__pycache__/test.cpython-310.pyc | Bin 0 -> 8133 bytes .../__pycache__/upload.cpython-310.pyc | Bin 0 -> 814 bytes .../__pycache__/upload_docs.cpython-310.pyc | Bin 0 -> 6183 bytes .../site-packages/setuptools/command/alias.py | 78 + .../setuptools/command/bdist_egg.py | 456 + .../setuptools/command/bdist_rpm.py | 40 + .../setuptools/command/build_clib.py | 101 + .../setuptools/command/build_ext.py | 328 + .../setuptools/command/build_py.py | 242 + .../setuptools/command/develop.py | 193 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2354 ++ .../setuptools/command/egg_info.py | 755 + .../setuptools/command/install.py | 132 + .../setuptools/command/install_egg_info.py | 82 + .../setuptools/command/install_lib.py | 148 + .../setuptools/command/install_scripts.py | 69 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 134 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 64 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 196 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 252 + .../setuptools/command/upload.py | 17 + .../setuptools/command/upload_docs.py | 202 + .../site-packages/setuptools/config.py | 751 + .../site-packages/setuptools/dep_util.py | 25 + .../site-packages/setuptools/depends.py | 176 + .../site-packages/setuptools/dist.py | 1156 + .../site-packages/setuptools/errors.py | 40 + .../site-packages/setuptools/extension.py | 55 + .../setuptools/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2936 bytes .../site-packages/setuptools/glob.py | 167 + .../site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../site-packages/setuptools/gui-arm64.exe | Bin 0 -> 137728 bytes .../site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/installer.py | 104 + .../site-packages/setuptools/launch.py | 36 + .../site-packages/setuptools/monkey.py | 177 + .../site-packages/setuptools/msvc.py | 1805 ++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1127 + .../site-packages/setuptools/py34compat.py | 13 + .../site-packages/setuptools/sandbox.py | 530 + .../setuptools/script (dev).tmpl | 6 + .../site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/unicode_utils.py | 42 + .../site-packages/setuptools/version.py | 6 + .../site-packages/setuptools/wheel.py | 213 + .../setuptools/windows_support.py | 29 + .../werkzeug-3.0.1.dist-info/INSTALLER | 1 + .../werkzeug-3.0.1.dist-info/LICENSE.rst | 28 + .../werkzeug-3.0.1.dist-info/METADATA | 118 + .../werkzeug-3.0.1.dist-info/RECORD | 125 + .../werkzeug-3.0.1.dist-info/WHEEL | 4 + .../site-packages/werkzeug/__init__.py | 25 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 934 bytes .../__pycache__/_internal.cpython-310.pyc | Bin 0 -> 7056 bytes .../__pycache__/_reloader.cpython-310.pyc | Bin 0 -> 12626 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 27326 bytes .../__pycache__/formparser.cpython-310.pyc | Bin 0 -> 12648 bytes .../werkzeug/__pycache__/http.cpython-310.pyc | Bin 0 -> 38891 bytes .../__pycache__/local.cpython-310.pyc | Bin 0 -> 20922 bytes .../__pycache__/security.cpython-310.pyc | Bin 0 -> 5353 bytes .../__pycache__/serving.cpython-310.pyc | Bin 0 -> 30449 bytes .../werkzeug/__pycache__/test.cpython-310.pyc | Bin 0 -> 42891 bytes .../__pycache__/testapp.cpython-310.pyc | Bin 0 -> 6395 bytes .../werkzeug/__pycache__/urls.cpython-310.pyc | Bin 0 -> 6447 bytes .../__pycache__/user_agent.cpython-310.pyc | Bin 0 -> 1862 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 22280 bytes .../werkzeug/__pycache__/wsgi.cpython-310.pyc | Bin 0 -> 19954 bytes .../site-packages/werkzeug/_internal.py | 214 + .../site-packages/werkzeug/_reloader.py | 458 + .../werkzeug/datastructures/__init__.py | 34 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1556 bytes .../__pycache__/accept.cpython-310.pyc | Bin 0 -> 10648 bytes .../__pycache__/auth.cpython-310.pyc | Bin 0 -> 10471 bytes .../__pycache__/cache_control.cpython-310.pyc | Bin 0 -> 6615 bytes .../__pycache__/csp.cpython-310.pyc | Bin 0 -> 4151 bytes .../__pycache__/etag.cpython-310.pyc | Bin 0 -> 3915 bytes .../__pycache__/file_storage.cpython-310.pyc | Bin 0 -> 6064 bytes .../__pycache__/headers.cpython-310.pyc | Bin 0 -> 17756 bytes .../__pycache__/mixins.cpython-310.pyc | Bin 0 -> 9051 bytes .../__pycache__/range.cpython-310.pyc | Bin 0 -> 6018 bytes .../__pycache__/structures.cpython-310.pyc | Bin 0 -> 35935 bytes .../werkzeug/datastructures/accept.py | 326 + .../werkzeug/datastructures/accept.pyi | 54 + .../werkzeug/datastructures/auth.py | 318 + .../werkzeug/datastructures/cache_control.py | 175 + .../werkzeug/datastructures/cache_control.pyi | 109 + .../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 | 47 + .../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 | 1006 + .../werkzeug/datastructures/structures.pyi | 208 + .../site-packages/werkzeug/debug/__init__.py | 534 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 14366 bytes .../debug/__pycache__/console.cpython-310.pyc | Bin 0 -> 8320 bytes .../debug/__pycache__/repr.cpython-310.pyc | Bin 0 -> 9071 bytes .../debug/__pycache__/tbtools.cpython-310.pyc | Bin 0 -> 11802 bytes .../site-packages/werkzeug/debug/console.py | 219 + .../site-packages/werkzeug/debug/repr.py | 283 + .../werkzeug/debug/shared/ICON_LICENSE.md | 6 + .../werkzeug/debug/shared/console.png | Bin 0 -> 507 bytes .../werkzeug/debug/shared/debugger.js | 360 + .../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 | 437 + .../site-packages/werkzeug/exceptions.py | 879 + .../site-packages/werkzeug/formparser.py | 421 + .../python3.10/site-packages/werkzeug/http.py | 1372 + .../site-packages/werkzeug/local.py | 643 + .../werkzeug/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 187 bytes .../__pycache__/dispatcher.cpython-310.pyc | Bin 0 -> 2836 bytes .../__pycache__/http_proxy.cpython-310.pyc | Bin 0 -> 6929 bytes .../__pycache__/lint.cpython-310.pyc | Bin 0 -> 12990 bytes .../__pycache__/profiler.cpython-310.pyc | Bin 0 -> 5628 bytes .../__pycache__/proxy_fix.cpython-310.pyc | Bin 0 -> 6029 bytes .../__pycache__/shared_data.cpython-310.pyc | Bin 0 -> 9281 bytes .../werkzeug/middleware/dispatcher.py | 80 + .../werkzeug/middleware/http_proxy.py | 235 + .../site-packages/werkzeug/middleware/lint.py | 420 + .../werkzeug/middleware/profiler.py | 154 + .../werkzeug/middleware/proxy_fix.py | 182 + .../werkzeug/middleware/shared_data.py | 282 + .../site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 133 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 4625 bytes .../__pycache__/converters.cpython-310.pyc | Bin 0 -> 9152 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 0 -> 5637 bytes .../routing/__pycache__/map.cpython-310.pyc | Bin 0 -> 30927 bytes .../__pycache__/matcher.cpython-310.pyc | Bin 0 -> 5130 bytes .../routing/__pycache__/rules.cpython-310.pyc | Bin 0 -> 27660 bytes .../werkzeug/routing/converters.py | 261 + .../werkzeug/routing/exceptions.py | 148 + .../site-packages/werkzeug/routing/map.py | 946 + .../site-packages/werkzeug/routing/matcher.py | 202 + .../site-packages/werkzeug/routing/rules.py | 909 + .../site-packages/werkzeug/sansio/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 183 bytes .../sansio/__pycache__/http.cpython-310.pyc | Bin 0 -> 4133 bytes .../__pycache__/multipart.cpython-310.pyc | Bin 0 -> 7493 bytes .../__pycache__/request.cpython-310.pyc | Bin 0 -> 17298 bytes .../__pycache__/response.cpython-310.pyc | Bin 0 -> 24517 bytes .../sansio/__pycache__/utils.cpython-310.pyc | Bin 0 -> 4622 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 | 751 + .../site-packages/werkzeug/sansio/utils.py | 159 + .../site-packages/werkzeug/security.py | 157 + .../site-packages/werkzeug/serving.py | 1109 + .../python3.10/site-packages/werkzeug/test.py | 1462 + .../site-packages/werkzeug/testapp.py | 181 + .../python3.10/site-packages/werkzeug/urls.py | 216 + .../site-packages/werkzeug/user_agent.py | 47 + .../site-packages/werkzeug/utils.py | 690 + .../werkzeug/wrappers/__init__.py | 3 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 302 bytes .../__pycache__/request.cpython-310.pyc | Bin 0 -> 21650 bytes .../__pycache__/response.cpython-310.pyc | Bin 0 -> 28420 bytes .../werkzeug/wrappers/request.py | 650 + .../werkzeug/wrappers/response.py | 835 + .../python3.10/site-packages/werkzeug/wsgi.py | 595 + .venv/lib64 | 1 + .venv/pyvenv.cfg | 6 + mons.json | 1 + vrpmdvfrontend/.gitignore | 2 + vrpmdvfrontend/.vscode/launch.json | 46 + vrpmdvfrontend/Dockerfile | 37 + vrpmdvfrontend/README.MD | 49 + vrpmdvfrontend/dist/.gitignore | 2 + vrpmdvfrontend/dist/assets/.gitignore | 1 + vrpmdvfrontend/index.html | 41 + vrpmdvfrontend/package-lock.json | 11266 +++++++ vrpmdvfrontend/package.json | 60 + vrpmdvfrontend/public/favicon.ico | Bin 0 -> 101076 bytes vrpmdvfrontend/src/App.tsx | 184 + vrpmdvfrontend/src/authProvider.ts | 59 + .../src/components/app-icon/index.tsx | 22 + .../src/components/header/index.tsx | 80 + vrpmdvfrontend/src/components/index.ts | 1 + .../src/components/input/numericInput.tsx | 51 + .../src/contexts/color-mode/index.tsx | 59 + .../src/dataprovider/dataprovider.ts | 197 + .../src/dataprovider/utils/axios.ts | 21 + .../src/dataprovider/utils/generateFilter.ts | 30 + .../src/dataprovider/utils/generateSort.ts | 20 + .../src/dataprovider/utils/index.ts | 4 + .../src/dataprovider/utils/mapOperator.ts | 14 + vrpmdvfrontend/src/index.tsx | 13 + .../src/pages/blog-posts/create.tsx | 119 + vrpmdvfrontend/src/pages/blog-posts/edit.tsx | 124 + vrpmdvfrontend/src/pages/blog-posts/index.ts | 4 + vrpmdvfrontend/src/pages/blog-posts/list.tsx | 112 + vrpmdvfrontend/src/pages/blog-posts/show.tsx | 59 + .../src/pages/categories/create.tsx | 36 + vrpmdvfrontend/src/pages/categories/edit.tsx | 35 + vrpmdvfrontend/src/pages/categories/index.ts | 4 + vrpmdvfrontend/src/pages/categories/list.tsx | 58 + vrpmdvfrontend/src/pages/categories/show.tsx | 29 + .../src/pages/forgotPassword/index.tsx | 17 + vrpmdvfrontend/src/pages/login/index.tsx | 20 + .../src/pages/monitorings/create.tsx | 179 + vrpmdvfrontend/src/pages/monitorings/edit.tsx | 163 + vrpmdvfrontend/src/pages/monitorings/index.ts | 4 + vrpmdvfrontend/src/pages/monitorings/list.tsx | 147 + .../pages/monitorings/monitorings.types.ts | 12 + vrpmdvfrontend/src/pages/monitorings/show.tsx | 59 + vrpmdvfrontend/src/pages/register/index.tsx | 17 + vrpmdvfrontend/src/vite-env.d.ts | 1 + .../.parentlock | 0 .../0004E58FD4BE53C6576719E1100EB880734DB746 | 741 + .../00BDD0E393B4DCA56150E4AACE07C727099A6A0F | 494 + .../00DBEC973F226ED6FF736469F4C292FEB379ECB7 | Bin 0 -> 11002 bytes .../00FD6E68F1512BD7D1989B35746C3E89524D1182 | Bin 0 -> 9965 bytes .../01A05FFD8C7422ED59F1FF2AC6FBD1CB7E2520E5 | Bin 0 -> 12889 bytes .../02E3375613468F761F1DD820605D038F0FE29A6A | Bin 0 -> 10998 bytes .../02F0D98919760C4961E03578DC8A12C24AD3D0AC | Bin 0 -> 11121 bytes .../05B10060DC0E26A7C8129DBC528E928155E0D4DF | Bin 0 -> 9650 bytes .../05EEA87C835A45CC49E328CA49011AB84516C581 | Bin 0 -> 10517 bytes .../0A02E64D2153590E52FCB585D310AD3A69AC0181 | Bin 0 -> 195481 bytes .../0A5FD4027375226ECF1B25C5831FDDC41A76280F | Bin 0 -> 31804 bytes .../0A69992649A9C7EBB62141AD0A587E145B060D05 | 1921 ++ .../0A9650834D3983316F9461A18C54E4E0C979EADB | 16 + .../0AC2BC585010F8948A3B0A7E8E4FEBEE32D7F7DD | Bin 0 -> 2170 bytes .../0B1151500EBFF43BE6ED09E07693EF8467C5510F | Bin 0 -> 9637 bytes .../0C283FDFCAD372A2D1D7B99B38CFA35E4CA2ECD1 | Bin 0 -> 10196 bytes .../0C3A5DB7A2466D9A8DBB3C833F1083ECBB4C35D2 | Bin 0 -> 9381 bytes .../0C3F5EE12C307E29700D0AEFC7B3F7941E8A10E8 | Bin 0 -> 10083 bytes .../0C5C88D1B2D42F6D72890412F9DC56E97202EA64 | Bin 0 -> 12568 bytes .../0C8346CE6447C91BE6873788FBDAA9C71BE99A11 | Bin 0 -> 52083 bytes .../0D0867C9CAEB8E11A5DB035AE76404B7A4B24647 | Bin 0 -> 21600 bytes .../0D276E59A43C0B4CD93E096264D0F51CA50FF609 | Bin 0 -> 9756 bytes .../0D5B183B64A827E5B591F59FC88EC1DBE940F03F | Bin 0 -> 9017 bytes .../0E0D3B026FDBDC4EBE49873DFE123B8DE94DCFF5 | Bin 0 -> 8631 bytes .../0E236663E30FB63AB3DC586B733CCDE394432D1C | Bin 0 -> 8270 bytes .../0E249AEE985DB5A73B8120AACE44CB7D18CC2A81 | 605 + .../0E41D25EB2186FB96838FE30039E622C94CA4325 | Bin 0 -> 11193 bytes .../0ECCC3BF26B52C46B144ED563682173F9BE5DFD6 | Bin 0 -> 8818 bytes .../0EECFA7C7821374732160FC9539E31A06CB19AC8 | Bin 0 -> 14988 bytes .../0F44B3C599D7ED532AED5ECC8C0AA612604C9803 | Bin 0 -> 9477 bytes .../0F9B8AB0D9A8270C27DF4C433B0944D7C909843B | Bin 0 -> 12610 bytes .../0FA2AC01FE70BE00EFDC9851F43A0B67E3A3B36A | Bin 0 -> 32328 bytes .../0FE83C125301683FF54B8DBF0B76D95090E75743 | Bin 0 -> 8081 bytes .../0FEE7D382A507D160A17A248F361F291521CD59F | Bin 0 -> 13769 bytes .../1A3CD800FCC442FE795EBE9E37FA971C82876E03 | Bin 0 -> 10947 bytes .../1A526EBCC4019E597C176C1BEF60FFF9D4CB667D | Bin 0 -> 8644 bytes .../1A531009C678BFBF4CDDD1B3C264593307D46841 | 187 + .../1AA1CC316392361797225B5DCBC1F57E18CA83AB | Bin 0 -> 58543 bytes .../1B5A7253F0430BB47285D9B28A271A9022B711A1 | Bin 0 -> 12630 bytes .../1BEE5FC6CFAF5222626A74644DF93AD01834EA27 | 16 + .../1C08F2A5B7D42EA6AFE8B28415372631443377DA | Bin 0 -> 1332 bytes .../1C23CE642523691F2D103E6A0D3F3FEC3C7318C2 | Bin 0 -> 26408 bytes .../1C362B0BE38B5A50CF9D3527497809A90268C9C3 | Bin 0 -> 16648 bytes .../1C977B2A8F17C2768C17331F76B09CC36C598837 | Bin 0 -> 85937 bytes .../1CA634B758EA2A6F1EE7322AAB2B853DC0888613 | Bin 0 -> 95981 bytes .../1CD2AC4BE7BEBACE5016A4F24266E92B155B3870 | Bin 0 -> 12303 bytes .../1D3CD029126AE3BDCDC5428FEE4A16E3BAF2A1BA | 26702 ++++++++++++++++ .../1D81002C226854562FA91B6CB2AB583746235819 | Bin 0 -> 9510 bytes .../1DDC16205DA00254CED655F31B8434DA8F83A9E8 | Bin 0 -> 1194 bytes .../1DEFEA283F9722201AE219D0A5F4005D89C34F72 | Bin 0 -> 54562 bytes .../1DFEE4697FC72C2E6250061BDB86BC78671C2C2F | Bin 0 -> 9942 bytes .../1EA482080F5D93956D96E462FCEE07FB8F8D3B97 | Bin 0 -> 9975 bytes .../1F70B6CE06F86481A2038FFAE2CB6EAF07D17D83 | Bin 0 -> 8669 bytes .../1F711B82BDEFEAD01CF69F4097BE75C1B8C30F26 | Bin 0 -> 2272 bytes .../1F7715D3A0AD2DB4DF699117069E3841C71C29CE | Bin 0 -> 31790 bytes .../1FE0F91C2E06EFFE344E968592278B167D378BAF | Bin 0 -> 12412 bytes .../2A30FFA7B02D163BB882DB7E528C8330A89872FB | Bin 0 -> 82237 bytes .../2A9C510E93C40507CEFE7768078ED66943C67D55 | Bin 0 -> 13918 bytes .../2AB0B228CDC21395327051A70A2334E7F8C68FBC | Bin 0 -> 1563 bytes .../2AEEA30E1ABF20CE6EDCD6534789A8A96595E87A | Bin 0 -> 540 bytes .../2AF9C9F3327E67B7C7A5BE9BA25D1DF5088FED04 | Bin 0 -> 46710 bytes .../2B092FB3E3C56E88E73233D49D619EC6C4732C3C | Bin 0 -> 3971 bytes .../2B211FFC4DEC3CDED641818AECE4D79D1B76CF61 | Bin 0 -> 10088 bytes .../2B2E1D3F7D5F3BA43ABA4B94C36AB138371BFED3 | Bin 0 -> 10084 bytes .../2B6160529103B214D7A5ED7B1E9F766C20C214BE | Bin 0 -> 13625 bytes .../2B662789DFDD9C1308FF8ECD48E05F393053163C | Bin 0 -> 276 bytes .../2CA9BFC690E910493F8DFD9638907E2D8D04D72F | Bin 0 -> 17800 bytes .../2CB84DD9ABB4E1485D83397C59B193094E1ABFC7 | Bin 0 -> 9957 bytes .../2CF955AF9D25A160BAD29AE8B47A38025453DBB1 | Bin 0 -> 26339 bytes .../2D2A133F731F8F670C96D5628CC7AFF59BD2BDA0 | Bin 0 -> 18820 bytes .../2D3D9A151F361927C95B25FBF7408C4A6256BC3E | Bin 0 -> 162841 bytes .../2DA6E770AA8AB5752F8DFD7BE5C9A67FEA0D8397 | Bin 0 -> 9845 bytes .../2E23767F856D62B6C8776142E0F2EAD1A0D62D84 | Bin 0 -> 8559 bytes .../2E78767314F71527BC9B62C9F9B71F1946389EDE | Bin 0 -> 27224 bytes .../2EC4F928EC4366B2F229D66261100B7B22ECA9D5 | Bin 0 -> 17799 bytes .../2EE7FEF4C5958B50C8F8F0C9ADD5DFF5FF347C8A | Bin 0 -> 18841 bytes .../2F170C016EB778566467312FBE05CF604CD51CD9 | Bin 0 -> 5199 bytes .../2F7DDAF4BB315FEAFFE67EC3E254404674AC8EDC | Bin 0 -> 9187 bytes .../3A0938AEA7975BC7EC0A5F8D0DE5A88D7E1BEB62 | Bin 0 -> 149216 bytes .../3A7F1DC7B42A89627FB72AC496864A1D84ACF493 | Bin 0 -> 11093 bytes .../3B3624C9FACF0399A3DE61312CC83B4CCF38E2B7 | Bin 0 -> 8592 bytes .../3B662769D46E8A5DAB78B9E7A73ABF0A6F8D7D36 | 150 + .../3C6FC60678EE36A161E53BA76B337229D331FBFF | Bin 0 -> 41660 bytes .../3C7BEA52EF78D3FDEC6F165C3C24DD7429929968 | Bin 0 -> 10609 bytes .../3C7E646B11C44E78146E532557045D3A554ED23E | Bin 0 -> 11242 bytes .../3CF486F59F2A8657A2BC87EA6CD5E9A6BBBBB8FC | Bin 0 -> 10922 bytes .../3D55E86A288419549E734EF71BD7217088DD27F4 | Bin 0 -> 9758 bytes .../3D7EDEF387CAB22B8CED27D2CF09ADBC5AD3CCE4 | Bin 0 -> 10091 bytes .../3DB23FD0B121C3E0EF5335015EEB9E2FB88A6E3A | Bin 0 -> 10117 bytes .../3DBFA8AC9E78AD6101E877B520B704DB4555C8FE | 723 + .../3DE122AF51E9C396743DA36D6F24FC9288BA6D86 | Bin 0 -> 12312 bytes .../3DE677CE0AAA7203C204C1A1D78DB84887C8B274 | Bin 0 -> 98403 bytes .../3DF714109317EDA0BDD4BA0E788F05A73486A499 | Bin 0 -> 9914 bytes .../3E14DE34213B0FD055A26A5417A99C58CE80A78C | Bin 0 -> 20385 bytes .../3E4CC5E044AF9D81D32765F8BA9AFD89F53BD02B | Bin 0 -> 9936 bytes .../3EA7BCF04BC756EF1BFA5774BA67DD2251216411 | Bin 0 -> 9849 bytes .../3EFF7239512C1B697E51DC7B0B9D04272E089CE4 | Bin 0 -> 16004 bytes .../3F1EEEC5D2B96D2BA81B1C7A4500C1FFC61817A0 | Bin 0 -> 8905 bytes .../3FC4B3E70593AB7A0C8EDDB6D141DA263420B11E | Bin 0 -> 10524 bytes .../3FC4EC1905D417E2770F125624196BDFD2567D2E | Bin 0 -> 15081 bytes .../3FF5930089D2F21EE13231D906AC13EBBEC8C73B | Bin 0 -> 10874 bytes .../4A310EEF15BA8905EFB4A4C053A96628E368E3B3 | Bin 0 -> 10673 bytes .../4A3CDC590889A0B6FFFCCAE1AC47C5E8178B4390 | Bin 0 -> 7767 bytes .../4A7B7F0576BE8E2E9EC569F5ADD9235BB56670AA | Bin 0 -> 103793 bytes .../4B5FD4A7C01652EE8DF18A5257F5793DA4C81DD2 | Bin 0 -> 9900 bytes .../4B6A7FC81F64CEAB85AB4CB07E3A4622926D602B | 212 + .../4B9DC3D97C5CD076C056BB6CDAF64DFA54922D8E | Bin 0 -> 10214 bytes .../4C2362DB30DDAAE63F15C30BE6D7722E542773A8 | Bin 0 -> 336 bytes .../4C54AB2DD41349EC0A55D8033D97860B29D42326 | Bin 0 -> 7497 bytes .../4C79EC0ADBFBDED85C4FF28631362A36D544D01C | Bin 0 -> 18738 bytes .../4CFA604B52B0F2EA3107C210221524CC42BBD2FA | Bin 0 -> 17392 bytes .../4D016983D652912FFA55A3219988011657AEC7B2 | Bin 0 -> 39063 bytes .../4E2C7B57AA52DC6DEB6AB29232994497A1610ECD | Bin 0 -> 1939 bytes .../4E36BBD73D4B519B000CBBDA9355787EB3BBFFD7 | Bin 0 -> 10060 bytes .../4E8F2636CE051C7A23ED7E6A85D49261F936373D | Bin 0 -> 20788 bytes .../4EA31C4FB5B1D0CAF7541D964E04F65BE62358A9 | Bin 0 -> 9530 bytes .../4EF5E5069376A7DDF79142B3EB6F6C057615320B | Bin 0 -> 6703 bytes .../4EF637F10C4116B85191AD56189041CE569FD6C7 | Bin 0 -> 8792 bytes .../4EFA1B227789CBA787A0E4E1A7CBEDE234EAEC53 | Bin 0 -> 9243 bytes .../4FF86A458C36E2EDFDA52139D75E6DA5E06A8784 | Bin 0 -> 1673 bytes .../5A055F1FED056DA8E0A9DC43501194EA5462F6A7 | Bin 0 -> 21722 bytes .../5A0690359D936E785F52A274AEAC9D191197EABA | Bin 0 -> 14175 bytes .../5A18D81624A96D0E745FF8318E24C8E674FD5DEA | Bin 0 -> 7830 bytes .../5A1FD8243202EA1D506B2760E264ED17A54BA3B2 | Bin 0 -> 9278 bytes .../5A61798022B7BAA5829DE2E84F29D02ECDE3C0B3 | 16 + .../5B18E51878BB1BC88E4B3C8CDFF2A502F03F88EB | Bin 0 -> 8186 bytes .../5B3FE79E6818075B1859E4AB1DFBA5F952401619 | Bin 0 -> 10553 bytes .../5BAB9D9F2686DA484F7C03F104CF8E91DC952DE6 | Bin 0 -> 380 bytes .../5BABCB5F413C0DFB3B165951F836EDD43FD380AA | Bin 0 -> 21233 bytes .../5BB16E6C8A9BAFF468FC8257E8256B6CAEFAA6EC | Bin 0 -> 16833 bytes .../5C7348D5F5EEB15A7D264CEA543746B662CD5640 | Bin 0 -> 9610 bytes .../5D00DEEBCE782E7A6551F2AA34F132ED61AE84F7 | 69 + .../5DB00F4EEEC6618BE585BCB9F00B3EF77F215D21 | Bin 0 -> 304389 bytes .../5E935FE624DEE11D7FEA0560663276381579DCD2 | Bin 0 -> 8577 bytes .../http+++localhost+5001/.metadata-v2 | Bin 0 -> 51 bytes .../http+++localhost+5001/cache/.padding | Bin 0 -> 8 bytes .../http+++localhost+5173/.metadata-v2 | Bin 0 -> 51 bytes .../http+++localhost+5173/cache/.padding | Bin 0 -> 8 bytes .../.metadata-v2 | Bin 0 -> 147 bytes .../.metadata-v2 | Bin 0 -> 147 bytes .../default/https+++medium.com/.metadata-v2 | Bin 0 -> 48 bytes .../https+++stackoverflow.com/.metadata-v2 | Bin 0 -> 55 bytes .../https+++www.google.de/.metadata-v2 | Bin 0 -> 51 bytes .../storage/permanent/chrome/.metadata-v2 | Bin 0 -> 36 bytes .../indexeddb+++fx-devtools/.metadata-v2 | Bin 0 -> 53 bytes .../1e6d5302a7882ad4ddade23d57d8ca4e.png | Bin 0 -> 12256 bytes .../3c060da8-3a4d-4098-ab54-8ff5855bc4f6 | 2 + .../storage/permanent/chrome/.metadata-v2 | Bin 0 -> 36 bytes vrpmdvfrontend/tsconfig.json | 25 + vrpmdvfrontend/tsconfig.node.json | 8 + vrpmdvfrontend/vite.config.ts | 6 + vrpmdvserver/__init__.py | 0 vrpmdvserver/__pycache__/.gitignore | 5 + vrpmdvserver/vrpmdvdata.py | 139 + vrpmdvserver/vrpmdvmonitoring.py | 20 + vrpmdvserver/vrpmdvmonitoringschema.py | 34 + vrpmdvserver/vrpmdvmonreq.py | 13 + vrpmdvserver/vrpmdvmonreqschema.py | 19 + vrpmdvserver/vrpmdvserver.py | 74 + 1948 files changed, 361921 insertions(+) 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/pip create mode 100755 .venv/bin/pip3 create mode 100755 .venv/bin/pip3.10 create mode 120000 .venv/bin/python create mode 120000 .venv/bin/python3 create mode 120000 .venv/bin/python3.10 create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/entry_points.txt create mode 100644 .venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/_distutils_hack/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/_distutils_hack/override.py create mode 100644 .venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/blinker/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/blinker/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/blinker/__pycache__/_saferef.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/blinker/__pycache__/_utilities.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/blinker/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/blinker/_saferef.py create mode 100644 .venv/lib/python3.10/site-packages/blinker/_utilities.py create mode 100644 .venv/lib/python3.10/site-packages/blinker/base.py create mode 100644 .venv/lib/python3.10/site-packages/blinker/py.typed create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/click-8.1.7.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/click/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/shell_completion.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/click/_compat.py create mode 100644 .venv/lib/python3.10/site-packages/click/_termui_impl.py create mode 100644 .venv/lib/python3.10/site-packages/click/_textwrap.py create mode 100644 .venv/lib/python3.10/site-packages/click/_winconsole.py create mode 100644 .venv/lib/python3.10/site-packages/click/core.py create mode 100644 .venv/lib/python3.10/site-packages/click/decorators.py create mode 100644 .venv/lib/python3.10/site-packages/click/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/click/formatting.py create mode 100644 .venv/lib/python3.10/site-packages/click/globals.py create mode 100644 .venv/lib/python3.10/site-packages/click/parser.py create mode 100644 .venv/lib/python3.10/site-packages/click/py.typed create mode 100644 .venv/lib/python3.10/site-packages/click/shell_completion.py create mode 100644 .venv/lib/python3.10/site-packages/click/termui.py create mode 100644 .venv/lib/python3.10/site-packages/click/testing.py create mode 100644 .venv/lib/python3.10/site-packages/click/types.py create mode 100644 .venv/lib/python3.10/site-packages/click/utils.py create mode 100644 .venv/lib/python3.10/site-packages/distutils-precedence.pth create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/entry_points.txt create mode 100644 .venv/lib/python3.10/site-packages/flask/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/flask/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/app.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/blueprints.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/ctx.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/globals.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/helpers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/templating.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/typing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/app.py create mode 100644 .venv/lib/python3.10/site-packages/flask/blueprints.py create mode 100644 .venv/lib/python3.10/site-packages/flask/cli.py create mode 100644 .venv/lib/python3.10/site-packages/flask/config.py create mode 100644 .venv/lib/python3.10/site-packages/flask/ctx.py create mode 100644 .venv/lib/python3.10/site-packages/flask/debughelpers.py create mode 100644 .venv/lib/python3.10/site-packages/flask/globals.py create mode 100644 .venv/lib/python3.10/site-packages/flask/helpers.py create mode 100644 .venv/lib/python3.10/site-packages/flask/json/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/flask/json/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/json/__pycache__/provider.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/json/__pycache__/tag.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/json/provider.py create mode 100644 .venv/lib/python3.10/site-packages/flask/json/tag.py create mode 100644 .venv/lib/python3.10/site-packages/flask/logging.py create mode 100644 .venv/lib/python3.10/site-packages/flask/py.typed create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/README.md create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/__pycache__/app.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/__pycache__/blueprints.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/__pycache__/scaffold.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/app.py create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/blueprints.py create mode 100644 .venv/lib/python3.10/site-packages/flask/sansio/scaffold.py create mode 100644 .venv/lib/python3.10/site-packages/flask/sessions.py create mode 100644 .venv/lib/python3.10/site-packages/flask/signals.py create mode 100644 .venv/lib/python3.10/site-packages/flask/templating.py create mode 100644 .venv/lib/python3.10/site-packages/flask/testing.py create mode 100644 .venv/lib/python3.10/site-packages/flask/typing.py create mode 100644 .venv/lib/python3.10/site-packages/flask/views.py create mode 100644 .venv/lib/python3.10/site-packages/flask/wrappers.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/_json.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/encoding.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/exc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/serializer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/signer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/timed.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/__pycache__/url_safe.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/_json.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/encoding.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/exc.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/py.typed create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/serializer.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/signer.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/timed.py create mode 100644 .venv/lib/python3.10/site-packages/itsdangerous/url_safe.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/_identifier.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/async_utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/bccache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/compiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/constants.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/debug.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/defaults.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/environment.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/ext.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/filters.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/idtracking.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/lexer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/loaders.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/meta.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/nativetypes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/nodes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/optimizer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/runtime.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/sandbox.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/tests.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/__pycache__/visitor.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/jinja2/_identifier.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/async_utils.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/bccache.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/compiler.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/constants.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/debug.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/defaults.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/environment.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/ext.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/filters.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/idtracking.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/lexer.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/loaders.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/meta.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/nativetypes.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/nodes.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/optimizer.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/parser.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/py.typed create mode 100644 .venv/lib/python3.10/site-packages/jinja2/runtime.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/sandbox.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/tests.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/utils.py create mode 100644 .venv/lib/python3.10/site-packages/jinja2/visitor.py create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/__pycache__/_native.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/_native.py create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/_speedups.c create mode 100755 .venv/lib/python3.10/site-packages/markupsafe/_speedups.cpython-310-x86_64-linux-gnu.so create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/_speedups.pyi create mode 100644 .venv/lib/python3.10/site-packages/markupsafe/py.typed create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/marshmallow-3.21.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/class_registry.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/decorators.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/error_store.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/fields.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/orderedset.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/schema.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/types.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/validate.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/__pycache__/warnings.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/base.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/class_registry.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/decorators.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/error_store.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/fields.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/orderedset.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/py.typed create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/schema.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/types.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/utils.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/validate.py create mode 100644 .venv/lib/python3.10/site-packages/marshmallow/warnings.py create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/LICENSE.APACHE create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/LICENSE.BSD create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/packaging-24.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/packaging/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_elffile.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_manylinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_musllinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/_tokenizer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/markers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/metadata.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/requirements.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/specifiers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/tags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/packaging/_elffile.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/_manylinux.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/_musllinux.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/_parser.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/_structures.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/_tokenizer.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/markers.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/metadata.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/py.typed create mode 100644 .venv/lib/python3.10/site-packages/packaging/requirements.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/specifiers.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/tags.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/utils.py create mode 100644 .venv/lib/python3.10/site-packages/packaging/version.py create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/LICENSE.txt create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/entry_points.txt create mode 100644 .venv/lib/python3.10/site-packages/pip-22.0.2.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/pip/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/build_env.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/configuration.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/main.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/pyproject.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/build_env.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/main.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/base_command.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/command_context.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/main.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/main_parser.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/parser.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/req_command.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/spinners.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/cli/status_codes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/check.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/completion.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/debug.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/download.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/hash.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/help.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/index.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/install.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/list.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/search.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/show.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/check.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/completion.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/configuration.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/debug.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/download.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/freeze.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/hash.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/help.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/index.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/install.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/list.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/search.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/show.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/uninstall.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/commands/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/configuration.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/installed.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/distributions/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/__pycache__/collector.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/__pycache__/sources.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/collector.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/package_finder.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/index/sources.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/_distutils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/locations/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/main.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/candidate.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/format_control.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/index.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/link.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/scheme.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/target_python.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/candidate.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/direct_url.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/format_control.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/index.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/link.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/scheme.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/search_scope.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/target_python.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/models/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/auth.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/download.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/session.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/auth.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/download.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/session.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/__pycache__/check.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/check.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/freeze.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/operations/prepare.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/pyproject.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/constructors.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/req_file.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/req_install.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/req_set.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/constructors.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/req_file.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/req_install.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/req_set.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/req_tracker.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/self_outdated_check.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/_log.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/logging.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/misc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/models.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/urls.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/_log.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/appdirs.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/datetime.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/deprecation.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/distutils_args.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/egg_link.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/encoding.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/filesystem.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/filetypes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/glibc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/hashes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/logging.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/misc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/models.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/packaging.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/subprocess.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/unpacking.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/urls.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/utils/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/git.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/git.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/subversion.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_internal/wheel_builder.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/__pycache__/distro.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/__pycache__/six.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/certifi/core.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/enums.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langrussianmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/metadata/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/metadata/languages.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/chardet/version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/win32.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/database.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/index.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/locators.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/markers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/resources.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/util.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/distro.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_ihatexml.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_inputstream.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_tokenizer.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/_base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_trie/py.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/_utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/constants.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/lint.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/html5parser.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/serializer.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/core.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/codec.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/core.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/intranges.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/package_data.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/_version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/markers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/tags.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/packaging/version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/build.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/check.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/colorlog.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/dirtools.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/envbuild.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/meta.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pep517/wrappers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__pycache__/bar.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__pycache__/colors.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__pycache__/counter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/bar.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/colors.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/counter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/progress/spinner.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/console.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/filter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/style.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/token.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pygments/util.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/actions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/common.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/core.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/diagram/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/helpers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/results.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/testing.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/unicode.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/pyparsing/util.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/api.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/help.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/models.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/__version__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/adapters.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/api.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/auth.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/certs.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/compat.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/cookies.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/help.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/hooks.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/models.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/packages.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/sessions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/structures.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/requests/utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_lru_cache.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/align.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/box.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/color.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/console.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/control.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/json.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/live.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/region.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/status.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/style.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/table.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/tabulate.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/text.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_extension.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_loop.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_lru_cache.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_pick.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_stack.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_timer.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_windows.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/abc.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/align.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/ansi.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/bar.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/box.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/cells.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/color.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/columns.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/console.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/constrain.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/containers.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/control.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/emoji.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/errors.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/filesize.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/json.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/layout.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/live.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/live_render.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/logging.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/markup.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/measure.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/padding.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/pager.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/palette.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/panel.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/pretty.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/progress.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/prompt.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/protocol.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/region.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/repr.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/rule.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/scope.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/screen.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/segment.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/spinner.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/status.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/style.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/styled.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/syntax.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/table.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/tabulate.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/text.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/theme.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/themes.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/traceback.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/rich/tree.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/six.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/_asyncio.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/_utils.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/after.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/before.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/before_sleep.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/nap.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/retry.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/stop.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/tornadoweb.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tenacity/wait.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/tomli/_re.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/typing_extensions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/request.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/response.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/vendor.txt create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 .venv/lib/python3.10/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 .venv/lib/python3.10/site-packages/pip/py.typed create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_manylinux.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_musllinux.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/tags.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/extern/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/entry_points.txt create mode 100644 .venv/lib/python3.10/site-packages/setuptools-59.6.0.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/_imp.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/archive_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/build_meta.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/config.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/dep_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/depends.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/dist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/errors.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/extension.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/glob.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/installer.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/launch.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/monkey.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/msvc.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/namespaces.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/package_index.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/py34compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/sandbox.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/unicode_utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/wheel.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/__pycache__/windows_support.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_deprecation_warning.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/config.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/core.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/debug.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/dist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/errors.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/extension.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/log.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/py35compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/util.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/_msvccompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/archive_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/bcppcompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/ccompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/cmd.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/bdist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/bdist_dumb.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/bdist_msi.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/bdist_rpm.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/bdist_wininst.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/build.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/build_clib.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/build_ext.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/build_py.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/build_scripts.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/check.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/clean.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/config.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install_data.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install_egg_info.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install_headers.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install_lib.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/install_scripts.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/py37compat.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/register.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/sdist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/command/upload.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/config.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/core.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/cygwinccompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/debug.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/dep_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/dir_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/dist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/errors.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/extension.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/fancy_getopt.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/file_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/filelist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/log.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/msvc9compiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/msvccompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/py35compat.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/py38compat.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/spawn.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/sysconfig.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/text_file.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/unixccompiler.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/version.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_distutils/versionpredicate.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_imp.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/more.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/recipes.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/ordered_set.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/_manylinux.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/_musllinux.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/tags.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/archive_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/build_meta.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/cli-32.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/cli-64.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/cli-arm64.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/cli.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/alias.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/build_clib.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/build_ext.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/build_py.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/develop.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/dist_info.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/easy_install.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/egg_info.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/install.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/install_lib.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/install_scripts.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/py36compat.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/register.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/rotate.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/saveopts.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/sdist.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/setopt.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/test.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/upload.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/__pycache__/upload_docs.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/alias.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/bdist_egg.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/bdist_rpm.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/build_clib.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/build_ext.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/build_py.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/develop.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/dist_info.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/easy_install.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/egg_info.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/install.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/install_egg_info.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/install_lib.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/install_scripts.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/launcher manifest.xml create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/py36compat.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/register.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/rotate.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/saveopts.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/sdist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/setopt.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/test.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/upload.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/command/upload_docs.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/config.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/dep_util.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/depends.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/dist.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/errors.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/extension.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/extern/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/extern/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/setuptools/glob.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/gui-32.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/gui-64.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/gui-arm64.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/gui.exe create mode 100644 .venv/lib/python3.10/site-packages/setuptools/installer.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/launch.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/monkey.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/msvc.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/namespaces.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/package_index.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/py34compat.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/sandbox.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/script (dev).tmpl create mode 100644 .venv/lib/python3.10/site-packages/setuptools/script.tmpl create mode 100644 .venv/lib/python3.10/site-packages/setuptools/unicode_utils.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/version.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/wheel.py create mode 100644 .venv/lib/python3.10/site-packages/setuptools/windows_support.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug-3.0.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/werkzeug-3.0.1.dist-info/LICENSE.rst create mode 100644 .venv/lib/python3.10/site-packages/werkzeug-3.0.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/werkzeug-3.0.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/werkzeug-3.0.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/_internal.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/_reloader.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/formparser.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/http.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/local.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/security.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/serving.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/test.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/testapp.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/urls.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/user_agent.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/__pycache__/wsgi.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/_internal.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/_reloader.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/range.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/accept.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/accept.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/auth.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/cache_control.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/cache_control.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/csp.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/csp.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/etag.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/etag.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/file_storage.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/file_storage.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/headers.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/headers.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/mixins.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/mixins.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/range.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/range.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/structures.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/datastructures/structures.pyi create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/__pycache__/console.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/__pycache__/repr.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/console.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/repr.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/ICON_LICENSE.md create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/console.png create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/debugger.js create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/less.png create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/more.png create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/shared/style.css create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/debug/tbtools.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/formparser.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/http.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/local.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/lint.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/lint.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/profiler.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/py.typed create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/converters.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/map.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/matcher.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/rules.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/converters.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/map.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/matcher.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/routing/rules.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/http.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/request.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/response.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/utils.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/http.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/multipart.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/request.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/response.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/sansio/utils.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/security.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/serving.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/test.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/testapp.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/urls.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/user_agent.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/utils.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/request.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/response.cpython-310.pyc create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/request.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wrappers/response.py create mode 100644 .venv/lib/python3.10/site-packages/werkzeug/wsgi.py create mode 120000 .venv/lib64 create mode 100644 .venv/pyvenv.cfg create mode 100644 mons.json create mode 100644 vrpmdvfrontend/.gitignore create mode 100644 vrpmdvfrontend/.vscode/launch.json create mode 100644 vrpmdvfrontend/Dockerfile create mode 100644 vrpmdvfrontend/README.MD create mode 100644 vrpmdvfrontend/dist/.gitignore create mode 100644 vrpmdvfrontend/dist/assets/.gitignore create mode 100644 vrpmdvfrontend/index.html create mode 100644 vrpmdvfrontend/package-lock.json create mode 100644 vrpmdvfrontend/package.json create mode 100644 vrpmdvfrontend/public/favicon.ico create mode 100644 vrpmdvfrontend/src/App.tsx create mode 100644 vrpmdvfrontend/src/authProvider.ts create mode 100644 vrpmdvfrontend/src/components/app-icon/index.tsx create mode 100644 vrpmdvfrontend/src/components/header/index.tsx create mode 100644 vrpmdvfrontend/src/components/index.ts create mode 100644 vrpmdvfrontend/src/components/input/numericInput.tsx create mode 100644 vrpmdvfrontend/src/contexts/color-mode/index.tsx create mode 100644 vrpmdvfrontend/src/dataprovider/dataprovider.ts create mode 100644 vrpmdvfrontend/src/dataprovider/utils/axios.ts create mode 100644 vrpmdvfrontend/src/dataprovider/utils/generateFilter.ts create mode 100644 vrpmdvfrontend/src/dataprovider/utils/generateSort.ts create mode 100644 vrpmdvfrontend/src/dataprovider/utils/index.ts create mode 100644 vrpmdvfrontend/src/dataprovider/utils/mapOperator.ts create mode 100644 vrpmdvfrontend/src/index.tsx create mode 100644 vrpmdvfrontend/src/pages/blog-posts/create.tsx create mode 100644 vrpmdvfrontend/src/pages/blog-posts/edit.tsx create mode 100644 vrpmdvfrontend/src/pages/blog-posts/index.ts create mode 100644 vrpmdvfrontend/src/pages/blog-posts/list.tsx create mode 100644 vrpmdvfrontend/src/pages/blog-posts/show.tsx create mode 100644 vrpmdvfrontend/src/pages/categories/create.tsx create mode 100644 vrpmdvfrontend/src/pages/categories/edit.tsx create mode 100644 vrpmdvfrontend/src/pages/categories/index.ts create mode 100644 vrpmdvfrontend/src/pages/categories/list.tsx create mode 100644 vrpmdvfrontend/src/pages/categories/show.tsx create mode 100644 vrpmdvfrontend/src/pages/forgotPassword/index.tsx create mode 100644 vrpmdvfrontend/src/pages/login/index.tsx create mode 100644 vrpmdvfrontend/src/pages/monitorings/create.tsx create mode 100644 vrpmdvfrontend/src/pages/monitorings/edit.tsx create mode 100644 vrpmdvfrontend/src/pages/monitorings/index.ts create mode 100644 vrpmdvfrontend/src/pages/monitorings/list.tsx create mode 100644 vrpmdvfrontend/src/pages/monitorings/monitorings.types.ts create mode 100644 vrpmdvfrontend/src/pages/monitorings/show.tsx create mode 100644 vrpmdvfrontend/src/pages/register/index.tsx create mode 100644 vrpmdvfrontend/src/vite-env.d.ts create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/.parentlock create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0004E58FD4BE53C6576719E1100EB880734DB746 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/00BDD0E393B4DCA56150E4AACE07C727099A6A0F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/00DBEC973F226ED6FF736469F4C292FEB379ECB7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/00FD6E68F1512BD7D1989B35746C3E89524D1182 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/01A05FFD8C7422ED59F1FF2AC6FBD1CB7E2520E5 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/02E3375613468F761F1DD820605D038F0FE29A6A create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/02F0D98919760C4961E03578DC8A12C24AD3D0AC create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/05B10060DC0E26A7C8129DBC528E928155E0D4DF create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/05EEA87C835A45CC49E328CA49011AB84516C581 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0A02E64D2153590E52FCB585D310AD3A69AC0181 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0A5FD4027375226ECF1B25C5831FDDC41A76280F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0A69992649A9C7EBB62141AD0A587E145B060D05 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0A9650834D3983316F9461A18C54E4E0C979EADB create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0AC2BC585010F8948A3B0A7E8E4FEBEE32D7F7DD create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0B1151500EBFF43BE6ED09E07693EF8467C5510F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0C283FDFCAD372A2D1D7B99B38CFA35E4CA2ECD1 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0C3A5DB7A2466D9A8DBB3C833F1083ECBB4C35D2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0C3F5EE12C307E29700D0AEFC7B3F7941E8A10E8 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0C5C88D1B2D42F6D72890412F9DC56E97202EA64 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0C8346CE6447C91BE6873788FBDAA9C71BE99A11 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0D0867C9CAEB8E11A5DB035AE76404B7A4B24647 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0D276E59A43C0B4CD93E096264D0F51CA50FF609 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0D5B183B64A827E5B591F59FC88EC1DBE940F03F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0E0D3B026FDBDC4EBE49873DFE123B8DE94DCFF5 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0E236663E30FB63AB3DC586B733CCDE394432D1C create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0E249AEE985DB5A73B8120AACE44CB7D18CC2A81 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0E41D25EB2186FB96838FE30039E622C94CA4325 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0ECCC3BF26B52C46B144ED563682173F9BE5DFD6 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0EECFA7C7821374732160FC9539E31A06CB19AC8 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0F44B3C599D7ED532AED5ECC8C0AA612604C9803 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0F9B8AB0D9A8270C27DF4C433B0944D7C909843B create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0FA2AC01FE70BE00EFDC9851F43A0B67E3A3B36A create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0FE83C125301683FF54B8DBF0B76D95090E75743 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/0FEE7D382A507D160A17A248F361F291521CD59F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1A3CD800FCC442FE795EBE9E37FA971C82876E03 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1A526EBCC4019E597C176C1BEF60FFF9D4CB667D create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1A531009C678BFBF4CDDD1B3C264593307D46841 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1AA1CC316392361797225B5DCBC1F57E18CA83AB create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1B5A7253F0430BB47285D9B28A271A9022B711A1 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1BEE5FC6CFAF5222626A74644DF93AD01834EA27 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1C08F2A5B7D42EA6AFE8B28415372631443377DA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1C23CE642523691F2D103E6A0D3F3FEC3C7318C2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1C362B0BE38B5A50CF9D3527497809A90268C9C3 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1C977B2A8F17C2768C17331F76B09CC36C598837 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1CA634B758EA2A6F1EE7322AAB2B853DC0888613 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1CD2AC4BE7BEBACE5016A4F24266E92B155B3870 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1D3CD029126AE3BDCDC5428FEE4A16E3BAF2A1BA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1D81002C226854562FA91B6CB2AB583746235819 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1DDC16205DA00254CED655F31B8434DA8F83A9E8 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1DEFEA283F9722201AE219D0A5F4005D89C34F72 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1DFEE4697FC72C2E6250061BDB86BC78671C2C2F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1EA482080F5D93956D96E462FCEE07FB8F8D3B97 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1F70B6CE06F86481A2038FFAE2CB6EAF07D17D83 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1F711B82BDEFEAD01CF69F4097BE75C1B8C30F26 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1F7715D3A0AD2DB4DF699117069E3841C71C29CE create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/1FE0F91C2E06EFFE344E968592278B167D378BAF create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2A30FFA7B02D163BB882DB7E528C8330A89872FB create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2A9C510E93C40507CEFE7768078ED66943C67D55 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2AB0B228CDC21395327051A70A2334E7F8C68FBC create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2AEEA30E1ABF20CE6EDCD6534789A8A96595E87A create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2AF9C9F3327E67B7C7A5BE9BA25D1DF5088FED04 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2B092FB3E3C56E88E73233D49D619EC6C4732C3C create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2B211FFC4DEC3CDED641818AECE4D79D1B76CF61 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2B2E1D3F7D5F3BA43ABA4B94C36AB138371BFED3 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2B6160529103B214D7A5ED7B1E9F766C20C214BE create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2B662789DFDD9C1308FF8ECD48E05F393053163C create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2CA9BFC690E910493F8DFD9638907E2D8D04D72F create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2CB84DD9ABB4E1485D83397C59B193094E1ABFC7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2CF955AF9D25A160BAD29AE8B47A38025453DBB1 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2D2A133F731F8F670C96D5628CC7AFF59BD2BDA0 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2D3D9A151F361927C95B25FBF7408C4A6256BC3E create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2DA6E770AA8AB5752F8DFD7BE5C9A67FEA0D8397 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2E23767F856D62B6C8776142E0F2EAD1A0D62D84 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2E78767314F71527BC9B62C9F9B71F1946389EDE create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2EC4F928EC4366B2F229D66261100B7B22ECA9D5 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2EE7FEF4C5958B50C8F8F0C9ADD5DFF5FF347C8A create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2F170C016EB778566467312FBE05CF604CD51CD9 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/2F7DDAF4BB315FEAFFE67EC3E254404674AC8EDC create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3A0938AEA7975BC7EC0A5F8D0DE5A88D7E1BEB62 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3A7F1DC7B42A89627FB72AC496864A1D84ACF493 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3B3624C9FACF0399A3DE61312CC83B4CCF38E2B7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3B662769D46E8A5DAB78B9E7A73ABF0A6F8D7D36 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3C6FC60678EE36A161E53BA76B337229D331FBFF create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3C7BEA52EF78D3FDEC6F165C3C24DD7429929968 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3C7E646B11C44E78146E532557045D3A554ED23E create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3CF486F59F2A8657A2BC87EA6CD5E9A6BBBBB8FC create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3D55E86A288419549E734EF71BD7217088DD27F4 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3D7EDEF387CAB22B8CED27D2CF09ADBC5AD3CCE4 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3DB23FD0B121C3E0EF5335015EEB9E2FB88A6E3A create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3DBFA8AC9E78AD6101E877B520B704DB4555C8FE create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3DE122AF51E9C396743DA36D6F24FC9288BA6D86 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3DE677CE0AAA7203C204C1A1D78DB84887C8B274 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3DF714109317EDA0BDD4BA0E788F05A73486A499 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3E14DE34213B0FD055A26A5417A99C58CE80A78C create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3E4CC5E044AF9D81D32765F8BA9AFD89F53BD02B create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3EA7BCF04BC756EF1BFA5774BA67DD2251216411 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3EFF7239512C1B697E51DC7B0B9D04272E089CE4 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3F1EEEC5D2B96D2BA81B1C7A4500C1FFC61817A0 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3FC4B3E70593AB7A0C8EDDB6D141DA263420B11E create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3FC4EC1905D417E2770F125624196BDFD2567D2E create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/3FF5930089D2F21EE13231D906AC13EBBEC8C73B create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4A310EEF15BA8905EFB4A4C053A96628E368E3B3 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4A3CDC590889A0B6FFFCCAE1AC47C5E8178B4390 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4A7B7F0576BE8E2E9EC569F5ADD9235BB56670AA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4B5FD4A7C01652EE8DF18A5257F5793DA4C81DD2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4B6A7FC81F64CEAB85AB4CB07E3A4622926D602B create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4B9DC3D97C5CD076C056BB6CDAF64DFA54922D8E create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4C2362DB30DDAAE63F15C30BE6D7722E542773A8 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4C54AB2DD41349EC0A55D8033D97860B29D42326 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4C79EC0ADBFBDED85C4FF28631362A36D544D01C create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4CFA604B52B0F2EA3107C210221524CC42BBD2FA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4D016983D652912FFA55A3219988011657AEC7B2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4E2C7B57AA52DC6DEB6AB29232994497A1610ECD create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4E36BBD73D4B519B000CBBDA9355787EB3BBFFD7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4E8F2636CE051C7A23ED7E6A85D49261F936373D create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4EA31C4FB5B1D0CAF7541D964E04F65BE62358A9 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4EF5E5069376A7DDF79142B3EB6F6C057615320B create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4EF637F10C4116B85191AD56189041CE569FD6C7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4EFA1B227789CBA787A0E4E1A7CBEDE234EAEC53 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/4FF86A458C36E2EDFDA52139D75E6DA5E06A8784 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5A055F1FED056DA8E0A9DC43501194EA5462F6A7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5A0690359D936E785F52A274AEAC9D191197EABA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5A18D81624A96D0E745FF8318E24C8E674FD5DEA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5A1FD8243202EA1D506B2760E264ED17A54BA3B2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5A61798022B7BAA5829DE2E84F29D02ECDE3C0B3 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5B18E51878BB1BC88E4B3C8CDFF2A502F03F88EB create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5B3FE79E6818075B1859E4AB1DFBA5F952401619 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5BAB9D9F2686DA484F7C03F104CF8E91DC952DE6 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5BABCB5F413C0DFB3B165951F836EDD43FD380AA create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5BB16E6C8A9BAFF468FC8257E8256B6CAEFAA6EC create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5C7348D5F5EEB15A7D264CEA543746B662CD5640 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5D00DEEBCE782E7A6551F2AA34F132ED61AE84F7 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5DB00F4EEEC6618BE585BCB9F00B3EF77F215D21 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/cache2/entries/5E935FE624DEE11D7FEA0560663276381579DCD2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/http+++localhost+5001/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/http+++localhost+5001/cache/.padding create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/http+++localhost+5173/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/http+++localhost+5173/cache/.padding create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/https+++35611eedb4b43fb1c88e3948e69d68d7.safeframe.googlesyndication.com^partitionKey=%28https%2Cstackoverflow.com%29/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/https+++8929ba9146aea67af3d859aaada11ce8.safeframe.googlesyndication.com^partitionKey=%28https%2Cstackoverflow.com%29/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/https+++medium.com/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/https+++stackoverflow.com/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/default/https+++www.google.de/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/permanent/chrome/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/storage/permanent/indexeddb+++fx-devtools/.metadata-v2 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-11775616-b228-42e3-b4e6-27d43f31aaa2/thumbnails/1e6d5302a7882ad4ddade23d57d8ca4e.png create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-23a1060c-e28f-41c5-bab3-b406206db5bd/datareporting/glean/pending_pings/3c060da8-3a4d-4098-ab54-8ff5855bc4f6 create mode 100644 vrpmdvfrontend/tmpDir/vscode-firefox-debug-profile-23a1060c-e28f-41c5-bab3-b406206db5bd/storage/permanent/chrome/.metadata-v2 create mode 100644 vrpmdvfrontend/tsconfig.json create mode 100644 vrpmdvfrontend/tsconfig.node.json create mode 100644 vrpmdvfrontend/vite.config.ts create mode 100644 vrpmdvserver/__init__.py create mode 100644 vrpmdvserver/__pycache__/.gitignore create mode 100644 vrpmdvserver/vrpmdvdata.py create mode 100644 vrpmdvserver/vrpmdvmonitoring.py create mode 100644 vrpmdvserver/vrpmdvmonitoringschema.py create mode 100644 vrpmdvserver/vrpmdvmonreq.py create mode 100644 vrpmdvserver/vrpmdvmonreqschema.py create mode 100644 vrpmdvserver/vrpmdvserver.py 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..1beb4b6 --- /dev/null +++ b/.venv/bin/activate @@ -0,0 +1,69 @@ +# 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 + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + 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 + +VIRTUAL_ENV="/home/markus/git/vrpmdv-web/.venv" +export VIRTUAL_ENV + +_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 + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/.venv/bin/activate.csh b/.venv/bin/activate.csh new file mode 100644 index 0000000..be21dd8 --- /dev/null +++ b/.venv/bin/activate.csh @@ -0,0 +1,26 @@ +# 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 "/home/markus/git/vrpmdv-web/.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..74558d1 --- /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 "/home/markus/git/vrpmdv-web/.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..d7a343d --- /dev/null +++ b/.venv/bin/flask @@ -0,0 +1,8 @@ +#!/home/markus/git/vrpmdv-web/.venv/bin/python3 +# -*- 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/pip b/.venv/bin/pip new file mode 100755 index 0000000..0f34a1f --- /dev/null +++ b/.venv/bin/pip @@ -0,0 +1,8 @@ +#!/home/markus/git/vrpmdv-web/.venv/bin/python3 +# -*- 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..0f34a1f --- /dev/null +++ b/.venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/markus/git/vrpmdv-web/.venv/bin/python3 +# -*- 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.10 b/.venv/bin/pip3.10 new file mode 100755 index 0000000..0f34a1f --- /dev/null +++ b/.venv/bin/pip3.10 @@ -0,0 +1,8 @@ +#!/home/markus/git/vrpmdv-web/.venv/bin/python3 +# -*- 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..b8a0adb --- /dev/null +++ b/.venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/.venv/bin/python3 b/.venv/bin/python3 new file mode 120000 index 0000000..ae65fda --- /dev/null +++ b/.venv/bin/python3 @@ -0,0 +1 @@ +/usr/bin/python3 \ No newline at end of file diff --git a/.venv/bin/python3.10 b/.venv/bin/python3.10 new file mode 120000 index 0000000..b8a0adb --- /dev/null +++ b/.venv/bin/python3.10 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/LICENSE.rst b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/LICENSE.rst new file mode 100644 index 0000000..c37cae4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/LICENSE.rst @@ -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.10/site-packages/Jinja2-3.1.3.dist-info/METADATA b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/METADATA new file mode 100644 index 0000000..56e9429 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/METADATA @@ -0,0 +1,105 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 3.1.3 +Summary: A very fast and expressive template engine. +Home-page: https://palletsprojects.com/p/jinja/ +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/jinja/ +Project-URL: Issue Tracker, https://github.com/pallets/jinja/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 +Requires-Dist: MarkupSafe >=2.0 +Provides-Extra: i18n +Requires-Dist: Babel >=2.7 ; 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. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Jinja2 + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +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 + + +Links +----- + +- Documentation: https://jinja.palletsprojects.com/ +- Changes: https://jinja.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Jinja2/ +- Source Code: https://github.com/pallets/jinja/ +- Issue Tracker: https://github.com/pallets/jinja/issues/ +- Chat: https://discord.gg/pallets diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/RECORD b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/RECORD new file mode 100644 index 0000000..8a511ac --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/RECORD @@ -0,0 +1,58 @@ +Jinja2-3.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Jinja2-3.1.3.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Jinja2-3.1.3.dist-info/METADATA,sha256=0cLNbRCI91jytc7Bzv3XAQfZzFDF2gxkJuH46eF5vew,3301 +Jinja2-3.1.3.dist-info/RECORD,, +Jinja2-3.1.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92 +Jinja2-3.1.3.dist-info/entry_points.txt,sha256=zRd62fbqIyfUpsRtU7EVIFyiu1tPwfgO7EvPErnxgTE,59 +Jinja2-3.1.3.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=NTBwMwsECrdHmxeXF7seusHLzrh6Ldn1A9qhS5cDuf0,1927 +jinja2/__pycache__/__init__.cpython-310.pyc,, +jinja2/__pycache__/_identifier.cpython-310.pyc,, +jinja2/__pycache__/async_utils.cpython-310.pyc,, +jinja2/__pycache__/bccache.cpython-310.pyc,, +jinja2/__pycache__/compiler.cpython-310.pyc,, +jinja2/__pycache__/constants.cpython-310.pyc,, +jinja2/__pycache__/debug.cpython-310.pyc,, +jinja2/__pycache__/defaults.cpython-310.pyc,, +jinja2/__pycache__/environment.cpython-310.pyc,, +jinja2/__pycache__/exceptions.cpython-310.pyc,, +jinja2/__pycache__/ext.cpython-310.pyc,, +jinja2/__pycache__/filters.cpython-310.pyc,, +jinja2/__pycache__/idtracking.cpython-310.pyc,, +jinja2/__pycache__/lexer.cpython-310.pyc,, +jinja2/__pycache__/loaders.cpython-310.pyc,, +jinja2/__pycache__/meta.cpython-310.pyc,, +jinja2/__pycache__/nativetypes.cpython-310.pyc,, +jinja2/__pycache__/nodes.cpython-310.pyc,, +jinja2/__pycache__/optimizer.cpython-310.pyc,, +jinja2/__pycache__/parser.cpython-310.pyc,, +jinja2/__pycache__/runtime.cpython-310.pyc,, +jinja2/__pycache__/sandbox.cpython-310.pyc,, +jinja2/__pycache__/tests.cpython-310.pyc,, +jinja2/__pycache__/utils.cpython-310.pyc,, +jinja2/__pycache__/visitor.cpython-310.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=dFcmh6lMNfbh7eLKrBio8JqAKLHdZbpCuurFN4OERtY,2447 +jinja2/bccache.py,sha256=mhz5xtLxCcHRAa56azOhphIAe19u1we0ojifNMClDio,14061 +jinja2/compiler.py,sha256=PJzYdRLStlEOqmnQs1YxlizPrJoj3jTZuUleREn6AIQ,72199 +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=0qldX3VQKZcm6lgn7zHz94oRFow7YPYERiqkquomNjU,61253 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=5fnMpllaXkfm2P_93RIvi-OnK7Tk8mCW8Du-GcD12Hc,31844 +jinja2/filters.py,sha256=vYjKb2zaPShvYtn_LpSmqfS8SScbrA_KOanNibsMDIE,53862 +jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704 +jinja2/lexer.py,sha256=DW2nX9zk-6MWp65YR2bqqj0xqCvLtD-u9NWT8AnFRxQ,29726 +jinja2/loaders.py,sha256=ayAwxfrA1SAffQta0nwSDm3TDT4KYiIGN_D9Z45B310,23085 +jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396 +jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 +jinja2/nodes.py,sha256=i34GPRAZexXMT6bwuf5SEyvdmS-bRCy9KMjwN5O6pjk,34550 +jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650 +jinja2/parser.py,sha256=Y199wPL-G67gJoi5G_5sHuu9uEP1PJkjjLEW_xTH8-k,39736 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=_6LkKIWFJjQdqlrgA3K39zBFQ-7Orm3wGDm96RwxQoE,33406 +jinja2/sandbox.py,sha256=Y0xZeXQnH6EX5VjaV2YixESxoepnRbW_3UeQosaBU3M,14584 +jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905 +jinja2/utils.py,sha256=IMwRIcN1SsTw2-jdQtlH2KzNABsXZBW_-tnFXafQBvY,23933 +jinja2/visitor.py,sha256=MH14C6yq24G_KVtWzjwaI7Wg14PCJIYlWW1kpkxYak0,3568 diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/WHEEL new file mode 100644 index 0000000..98c0d20 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/entry_points.txt b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/entry_points.txt new file mode 100644 index 0000000..7b9666c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract[i18n] diff --git a/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/top_level.txt new file mode 100644 index 0000000..7f7afbf --- /dev/null +++ b/.venv/lib/python3.10/site-packages/Jinja2-3.1.3.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/MarkupSafe-2.1.5.dist-info/METADATA b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/METADATA new file mode 100644 index 0000000..dfe37d5 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/MarkupSafe-2.1.5.dist-info/RECORD b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/RECORD new file mode 100644 index 0000000..1a961ed --- /dev/null +++ b/.venv/lib/python3.10/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=1FEjxEYgybphwh9S0FO9IcZ0B-NIeM2ko8OzhFZeOeQ,152 +MarkupSafe-2.1.5.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=r7VOTjUq7EMQ4v3p4R1LoVOGJg6ysfYRncLr34laRBs,10958 +markupsafe/__pycache__/__init__.cpython-310.pyc,, +markupsafe/__pycache__/_native.cpython-310.pyc,, +markupsafe/_native.py,sha256=GR86Qvo_GcgKmKreA1WmYN9ud17OFwkww8E-fiW-57s,1713 +markupsafe/_speedups.c,sha256=X2XvQVtIdcK4Usz70BvkzoOfjTCmQlDkkjYSn-swE0g,7083 +markupsafe/_speedups.cpython-310-x86_64-linux-gnu.so,sha256=kPt-fhZ_RG7PUbDvwmyC26ZvRJ9DvUlF3hszBIB6_xs,44240 +markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL new file mode 100644 index 0000000..1d81251 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: false +Tag: cp310-cp310-manylinux_2_17_x86_64 +Tag: cp310-cp310-manylinux2014_x86_64 + diff --git a/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt new file mode 100644 index 0000000..75bf729 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/.venv/lib/python3.10/site-packages/_distutils_hack/__init__.py b/.venv/lib/python3.10/site-packages/_distutils_hack/__init__.py new file mode 100644 index 0000000..f707416 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/_distutils_hack/__init__.py @@ -0,0 +1,132 @@ +import sys +import os +import re +import importlib +import warnings + + +is_pypy = '__pypy__' in sys.builtin_module_names + + +warnings.filterwarnings('ignore', + r'.+ distutils\b.+ deprecated', + DeprecationWarning) + + +def warn_distutils_present(): + if 'distutils' not in sys.modules: + return + if is_pypy and sys.version_info < (3, 7): + # PyPy for 3.6 unconditionally imports distutils, so bypass the warning + # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 + return + warnings.warn( + "Distutils was imported before Setuptools, but importing Setuptools " + "also replaces the `distutils` module in `sys.modules`. This may lead " + "to undesirable behaviors or errors. To avoid these issues, avoid " + "using distutils directly, ensure that setuptools is installed in the " + "traditional way (e.g. not an editable install), and/or make sure " + "that setuptools is always imported before distutils.") + + +def clear_distutils(): + if 'distutils' not in sys.modules: + return + warnings.warn("Setuptools is replacing distutils.") + mods = [name for name in sys.modules if re.match(r'distutils\b', name)] + for name in mods: + del sys.modules[name] + + +def enabled(): + """ + Allow selection of distutils by environment variable. + """ + which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'stdlib') + return which == 'local' + + +def ensure_local_distutils(): + clear_distutils() + + # With the DistutilsMetaFinder in place, + # perform an import to cause distutils to be + # loaded from setuptools._distutils. Ref #2906. + add_shim() + importlib.import_module('distutils') + remove_shim() + + # check that submodules load as expected + core = importlib.import_module('distutils.core') + assert '_distutils' in core.__file__, core.__file__ + + +def do_override(): + """ + Ensure that the local copy of distutils is preferred over stdlib. + + See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 + for more motivation. + """ + if enabled(): + warn_distutils_present() + ensure_local_distutils() + + +class DistutilsMetaFinder: + def find_spec(self, fullname, path, target=None): + if path is not None: + return + + method_name = 'spec_for_{fullname}'.format(**locals()) + method = getattr(self, method_name, lambda: None) + return method() + + def spec_for_distutils(self): + import importlib.abc + import importlib.util + + class DistutilsLoader(importlib.abc.Loader): + + def create_module(self, spec): + return importlib.import_module('setuptools._distutils') + + def exec_module(self, module): + pass + + return importlib.util.spec_from_loader('distutils', DistutilsLoader()) + + def spec_for_pip(self): + """ + Ensure stdlib distutils when running under pip. + See pypa/pip#8761 for rationale. + """ + if self.pip_imported_during_build(): + return + clear_distutils() + self.spec_for_distutils = lambda: None + + @staticmethod + def pip_imported_during_build(): + """ + Detect if pip is being imported in a build script. Ref #2355. + """ + import traceback + return any( + frame.f_globals['__file__'].endswith('setup.py') + for frame, line in traceback.walk_stack(None) + ) + + +DISTUTILS_FINDER = DistutilsMetaFinder() + + +def add_shim(): + sys.meta_path.insert(0, DISTUTILS_FINDER) + + +def remove_shim(): + try: + sys.meta_path.remove(DISTUTILS_FINDER) + except ValueError: + pass diff --git a/.venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67a145ff6dbab59d59130d4cb29568cb3f3808fa GIT binary patch literal 5109 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc b/.venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9005b5eb9787ab52df37c2982b0f9715cd2623c3 GIT binary patch literal 234 zcmZ9Hu?oU45QdZDAd1-65NuCz74ZpN++0F6M;mOKkff2$;(O@mD|Ph=T%Ak>LHyzV z6P9HC7f=_Bx=Wu3+rkpO3RAuaNLC1 zfH5JpGLEr!$Q4r_jS(F0#Pq_JkG*zKD2X65bF3}o!httha-W=V52?q>Ln-#48&{}m kk +Maintainer-email: Pallets Ecosystem +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development :: Libraries +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://blinker.readthedocs.io +Project-URL: Homepage, https://blinker.readthedocs.io +Project-URL: Issue Tracker, https://github.com/pallets-eco/blinker/issues/ +Project-URL: Source Code, 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". + +Signal receivers can subscribe to specific senders or receive signals +sent by any sender. + +.. code-block:: 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! + + +Links +----- + +- Documentation: https://blinker.readthedocs.io/ +- Changes: https://blinker.readthedocs.io/#changes +- PyPI Releases: https://pypi.org/project/blinker/ +- Source Code: https://github.com/pallets-eco/blinker/ +- Issue Tracker: https://github.com/pallets-eco/blinker/issues/ + diff --git a/.venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/RECORD b/.venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/RECORD new file mode 100644 index 0000000..51a7d03 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/RECORD @@ -0,0 +1,14 @@ +blinker-1.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +blinker-1.7.0.dist-info/LICENSE.rst,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 +blinker-1.7.0.dist-info/METADATA,sha256=kDgzPgrw4he78pEX88bSAqwYMVWrfUMk8QmNjekjg_U,1918 +blinker-1.7.0.dist-info/RECORD,, +blinker-1.7.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +blinker/__init__.py,sha256=s75XaRDHwSDzZ21BZUOEkQDQIcQEyT8hT7vk3EhYFQU,408 +blinker/__pycache__/__init__.cpython-310.pyc,, +blinker/__pycache__/_saferef.cpython-310.pyc,, +blinker/__pycache__/_utilities.cpython-310.pyc,, +blinker/__pycache__/base.cpython-310.pyc,, +blinker/_saferef.py,sha256=kWOTIWnCY3kOb8lZP74Rbx7bR_BLVg4TjwzNCRLhKHs,9096 +blinker/_utilities.py,sha256=S2njKDmlBpK_yCK4RT8hq98hEj30I0TQCC5mNhtY22I,2856 +blinker/base.py,sha256=FqZmAI5YzuRrvRmye1Jb-utyVOjXtF5vUVP3-1u-HtU,20544 +blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/.venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/blinker-1.7.0.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker-1.7.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.10/site-packages/blinker/__init__.py b/.venv/lib/python3.10/site-packages/blinker/__init__.py new file mode 100644 index 0000000..d014caa --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker/__init__.py @@ -0,0 +1,19 @@ +from blinker.base import ANY +from blinker.base import NamedSignal +from blinker.base import Namespace +from blinker.base import receiver_connected +from blinker.base import Signal +from blinker.base import signal +from blinker.base import WeakNamespace + +__all__ = [ + "ANY", + "NamedSignal", + "Namespace", + "Signal", + "WeakNamespace", + "receiver_connected", + "signal", +] + +__version__ = "1.7.0" diff --git a/.venv/lib/python3.10/site-packages/blinker/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/blinker/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..816addc216faf39e1d5c2a642885409380a7feeb GIT binary patch literal 498 zcmZ9Jy-ve07)9;;H%%AbqC?|W3@ix23v{3Z!i$x}pHeHoiqoL-B+P8gyiHanMph<1 zM?evda&oTao7hUTScC+}tN4H?O30fDe}{$P8gDHTl1N&TigHSgTj&M~40mKXf5$J8B^~XX?L9u`+oS@yQ+b_~ z7-uHxHpu|PSqB-Y0XmU2bq!e$5@)^N#h(7DE$$#GPF24%2kUGD$G|fP3|s>r@#t>i zi+H_VhGUeLsxF|5(?rAn>QtEerZv4}^o2;uQiyRb1a42OrWWFbbdgzM@OjJjO$Dq< zy5gW&u6j0fZ6$}*1Eee-pdMJMQq~^(eN&&un>Ev_hZP>YNOI8Zdq+$NRjXczxIK=+ XW!1<-30L?hi9SO_B%-G)u!8UlBl~vz literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/blinker/__pycache__/_saferef.cpython-310.pyc b/.venv/lib/python3.10/site-packages/blinker/__pycache__/_saferef.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72911cf19ad5db3a00e43f0c8194be77ae05e50d GIT binary patch literal 7185 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 E0E;3N&;S4c literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/blinker/__pycache__/base.cpython-310.pyc b/.venv/lib/python3.10/site-packages/blinker/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d065b3ce43bb2d75babaca4f19f78f6210bbbe45 GIT binary patch literal 17498 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/blinker/_saferef.py b/.venv/lib/python3.10/site-packages/blinker/_saferef.py new file mode 100644 index 0000000..dcb70c1 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker/_saferef.py @@ -0,0 +1,230 @@ +# extracted from Louie, http://pylouie.org/ +# updated for Python 3 +# +# Copyright (c) 2006 Patrick K. O'Brien, Mike C. Fletcher, +# Matthew R. Scott +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# * Neither the name of the nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +"""Refactored 'safe reference from dispatcher.py""" +import operator +import sys +import traceback +import weakref + + +get_self = operator.attrgetter("__self__") +get_func = operator.attrgetter("__func__") + + +def safe_ref(target, on_delete=None): + """Return a *safe* weak reference to a callable target. + + - ``target``: The object to be weakly referenced, if it's a bound + method reference, will create a BoundMethodWeakref, otherwise + creates a simple weakref. + + - ``on_delete``: If provided, will have a hard reference stored to + the callable to be called after the safe reference goes out of + scope with the reference object, (either a weakref or a + BoundMethodWeakref) as argument. + """ + try: + im_self = get_self(target) + except AttributeError: + if callable(on_delete): + return weakref.ref(target, on_delete) + else: + return weakref.ref(target) + else: + if im_self is not None: + # Turn a bound method into a BoundMethodWeakref instance. + # Keep track of these instances for lookup by disconnect(). + assert hasattr(target, "im_func") or hasattr(target, "__func__"), ( + f"safe_ref target {target!r} has im_self, but no im_func, " + "don't know how to create reference" + ) + reference = BoundMethodWeakref(target=target, on_delete=on_delete) + return reference + + +class BoundMethodWeakref: + """'Safe' and reusable weak references to instance methods. + + BoundMethodWeakref objects provide a mechanism for referencing a + bound method without requiring that the method object itself + (which is normally a transient object) is kept alive. Instead, + the BoundMethodWeakref object keeps weak references to both the + object and the function which together define the instance method. + + Attributes: + + - ``key``: The identity key for the reference, calculated by the + class's calculate_key method applied to the target instance method. + + - ``deletion_methods``: Sequence of callable objects taking single + argument, a reference to this object which will be called when + *either* the target object or target function is garbage + collected (i.e. when this object becomes invalid). These are + specified as the on_delete parameters of safe_ref calls. + + - ``weak_self``: Weak reference to the target object. + + - ``weak_func``: Weak reference to the target function. + + Class Attributes: + + - ``_all_instances``: Class attribute pointing to all live + BoundMethodWeakref objects indexed by the class's + calculate_key(target) method applied to the target objects. + This weak value dictionary is used to short-circuit creation so + that multiple references to the same (object, function) pair + produce the same BoundMethodWeakref instance. + """ + + _all_instances = weakref.WeakValueDictionary() # type: ignore[var-annotated] + + def __new__(cls, target, on_delete=None, *arguments, **named): + """Create new instance or return current instance. + + Basically this method of construction allows us to + short-circuit creation of references to already-referenced + instance methods. The key corresponding to the target is + calculated, and if there is already an existing reference, + that is returned, with its deletion_methods attribute updated. + Otherwise the new instance is created and registered in the + table of already-referenced methods. + """ + key = cls.calculate_key(target) + current = cls._all_instances.get(key) + if current is not None: + current.deletion_methods.append(on_delete) + return current + else: + base = super().__new__(cls) + cls._all_instances[key] = base + base.__init__(target, on_delete, *arguments, **named) + return base + + def __init__(self, target, on_delete=None): + """Return a weak-reference-like instance for a bound method. + + - ``target``: The instance-method target for the weak reference, + must have im_self and im_func attributes and be + reconstructable via the following, which is true of built-in + instance methods:: + + target.im_func.__get__( target.im_self ) + + - ``on_delete``: Optional callback which will be called when + this weak reference ceases to be valid (i.e. either the + object or the function is garbage collected). Should take a + single argument, which will be passed a pointer to this + object. + """ + + def remove(weak, self=self): + """Set self.isDead to True when method or instance is destroyed.""" + methods = self.deletion_methods[:] + del self.deletion_methods[:] + try: + del self.__class__._all_instances[self.key] + except KeyError: + pass + for function in methods: + try: + if callable(function): + function(self) + except Exception: + try: + traceback.print_exc() + except AttributeError: + e = sys.exc_info()[1] + print( + f"Exception during saferef {self} " + f"cleanup function {function}: {e}" + ) + + self.deletion_methods = [on_delete] + self.key = self.calculate_key(target) + im_self = get_self(target) + im_func = get_func(target) + self.weak_self = weakref.ref(im_self, remove) + self.weak_func = weakref.ref(im_func, remove) + self.self_name = str(im_self) + self.func_name = str(im_func.__name__) + + @classmethod + def calculate_key(cls, target): + """Calculate the reference key for this reference. + + Currently this is a two-tuple of the id()'s of the target + object and the target function respectively. + """ + return (id(get_self(target)), id(get_func(target))) + + def __str__(self): + """Give a friendly representation of the object.""" + return "{}({}.{})".format( + self.__class__.__name__, + self.self_name, + self.func_name, + ) + + __repr__ = __str__ + + def __hash__(self): + return hash((self.self_name, self.key)) + + def __nonzero__(self): + """Whether we are still a valid reference.""" + return self() is not None + + def __eq__(self, other): + """Compare with another reference.""" + if not isinstance(other, self.__class__): + return operator.eq(self.__class__, type(other)) + return operator.eq(self.key, other.key) + + def __call__(self): + """Return a strong reference to the bound method. + + If the target cannot be retrieved, then will return None, + otherwise returns a bound instance method for our object and + function. + + Note: You may call this method any number of times, as it does + not invalidate the reference. + """ + target = self.weak_self() + if target is not None: + function = self.weak_func() + if function is not None: + return function.__get__(target) + return None diff --git a/.venv/lib/python3.10/site-packages/blinker/_utilities.py b/.venv/lib/python3.10/site-packages/blinker/_utilities.py new file mode 100644 index 0000000..4b711c6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker/_utilities.py @@ -0,0 +1,105 @@ +from __future__ import annotations + +import typing as t +from weakref import ref + +from blinker._saferef import BoundMethodWeakref + +IdentityType = t.Union[t.Tuple[int, int], str, int] + + +class _symbol: + def __init__(self, name): + """Construct a new named symbol.""" + self.__name__ = self.name = name + + def __reduce__(self): + return symbol, (self.name,) + + def __repr__(self): + return self.name + + +_symbol.__name__ = "symbol" + + +class symbol: + """A constant symbol. + + >>> symbol('foo') is symbol('foo') + True + >>> symbol('foo') + foo + + A slight refinement of the MAGICCOOKIE=object() pattern. The primary + advantage of symbol() is its repr(). They are also singletons. + + Repeated calls of symbol('name') will all return the same instance. + + """ + + symbols = {} # type: ignore[var-annotated] + + def __new__(cls, name): + try: + return cls.symbols[name] + except KeyError: + return cls.symbols.setdefault(name, _symbol(name)) + + +def hashable_identity(obj: object) -> IdentityType: + if hasattr(obj, "__func__"): + return (id(obj.__func__), id(obj.__self__)) # type: ignore[attr-defined] + elif hasattr(obj, "im_func"): + return (id(obj.im_func), id(obj.im_self)) # type: ignore[attr-defined] + elif isinstance(obj, (int, str)): + return obj + else: + return id(obj) + + +WeakTypes = (ref, BoundMethodWeakref) + + +class annotatable_weakref(ref): + """A weakref.ref that supports custom instance attributes.""" + + receiver_id: t.Optional[IdentityType] + sender_id: t.Optional[IdentityType] + + +def reference( # type: ignore[no-untyped-def] + object, callback=None, **annotations +) -> annotatable_weakref: + """Return an annotated weak ref.""" + if callable(object): + weak = callable_reference(object, callback) + else: + weak = annotatable_weakref(object, callback) + for key, value in annotations.items(): + setattr(weak, key, value) + return weak # type: ignore[no-any-return] + + +def callable_reference(object, callback=None): + """Return an annotated weak ref, supporting bound instance methods.""" + if hasattr(object, "im_self") and object.im_self is not None: + return BoundMethodWeakref(target=object, on_delete=callback) + elif hasattr(object, "__self__") and object.__self__ is not None: + return BoundMethodWeakref(target=object, on_delete=callback) + return annotatable_weakref(object, callback) + + +class lazy_property: + """A @property that is only evaluated once.""" + + def __init__(self, deferred): + self._deferred = deferred + self.__doc__ = deferred.__doc__ + + def __get__(self, obj, cls): + if obj is None: + return self + value = self._deferred(obj) + setattr(obj, self._deferred.__name__, value) + return value diff --git a/.venv/lib/python3.10/site-packages/blinker/base.py b/.venv/lib/python3.10/site-packages/blinker/base.py new file mode 100644 index 0000000..b9d7035 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/blinker/base.py @@ -0,0 +1,558 @@ +"""Signals and events. + +A small implementation of signals, inspired by a snippet of Django signal +API client code seen in a blog post. Signals are first-class objects and +each manages its own receivers and message emission. + +The :func:`signal` function provides singleton behavior for named signals. + +""" +from __future__ import annotations + +import typing as t +from collections import defaultdict +from contextlib import contextmanager +from inspect import iscoroutinefunction +from warnings import warn +from weakref import WeakValueDictionary + +from blinker._utilities import annotatable_weakref +from blinker._utilities import hashable_identity +from blinker._utilities import IdentityType +from blinker._utilities import lazy_property +from blinker._utilities import reference +from blinker._utilities import symbol +from blinker._utilities import WeakTypes + +if t.TYPE_CHECKING: + import typing_extensions as te + + T_callable = t.TypeVar("T_callable", bound=t.Callable[..., t.Any]) + + T = t.TypeVar("T") + P = te.ParamSpec("P") + + AsyncWrapperType = t.Callable[[t.Callable[P, t.Awaitable[T]]], t.Callable[P, T]] + SyncWrapperType = t.Callable[[t.Callable[P, T]], t.Callable[P, t.Awaitable[T]]] + +ANY = symbol("ANY") +ANY.__doc__ = 'Token for "any sender".' +ANY_ID = 0 + +# NOTE: We need a reference to cast for use in weakref callbacks otherwise +# t.cast may have already been set to None during finalization. +cast = t.cast + + +class Signal: + """A notification emitter.""" + + #: An :obj:`ANY` convenience synonym, allows ``Signal.ANY`` + #: without an additional import. + ANY = ANY + + set_class: type[set] = set + + @lazy_property + def receiver_connected(self) -> Signal: + """Emitted after each :meth:`connect`. + + 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.") + + @lazy_property + def receiver_disconnected(self) -> Signal: + """Emitted after :meth:`disconnect`. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: *receiver* and *sender*. + + Note, this signal is emitted **only** when :meth:`disconnect` is + called explicitly. + + The disconnect signal can not be emitted by an automatic disconnect + (due to a weakly referenced receiver or sender going out of scope), + as the receiver and/or sender instances are no longer available for + use at the time this signal would be emitted. + + 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: + """ + :param doc: optional. If provided, will be assigned to the signal's + __doc__ attribute. + + """ + if doc: + self.__doc__ = doc + #: A mapping of connected receivers. + #: + #: The values of this mapping are not meaningful outside of the + #: internal :class:`Signal` implementation, however the boolean value + #: of the mapping is useful as an extremely efficient check to see if + #: any receivers are connected to the signal. + self.receivers: dict[IdentityType, t.Callable | annotatable_weakref] = {} + self.is_muted = False + self._by_receiver: dict[IdentityType, set[IdentityType]] = defaultdict( + self.set_class + ) + self._by_sender: dict[IdentityType, set[IdentityType]] = defaultdict( + self.set_class + ) + self._weak_senders: dict[IdentityType, annotatable_weakref] = {} + + def connect( + self, receiver: T_callable, sender: t.Any = ANY, weak: bool = True + ) -> T_callable: + """Connect *receiver* to signal events sent by *sender*. + + :param receiver: A callable. Will be invoked by :meth:`send` with + `sender=` as a single positional argument and any ``kwargs`` that + were provided to a call to :meth:`send`. + + :param sender: Any object or :obj:`ANY`, defaults to ``ANY``. + Restricts notifications delivered to *receiver* to only those + :meth:`send` emissions sent by *sender*. If ``ANY``, the receiver + will always be notified. A *receiver* may be connected to + multiple *sender* values on the same Signal through multiple calls + to :meth:`connect`. + + :param weak: If true, the Signal will hold a weakref to *receiver* + and automatically disconnect when *receiver* goes out of scope or + is garbage collected. Defaults to True. + + """ + receiver_id = hashable_identity(receiver) + receiver_ref: T_callable | annotatable_weakref + + if weak: + receiver_ref = reference(receiver, self._cleanup_receiver) + receiver_ref.receiver_id = receiver_id + else: + receiver_ref = receiver + sender_id: IdentityType + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = hashable_identity(sender) + + self.receivers.setdefault(receiver_id, receiver_ref) + self._by_sender[sender_id].add(receiver_id) + self._by_receiver[receiver_id].add(sender_id) + del receiver_ref + + if sender is not ANY and sender_id not in self._weak_senders: + # wire together a cleanup for weakref-able senders + try: + sender_ref = reference(sender, self._cleanup_sender) + sender_ref.sender_id = sender_id + except TypeError: + pass + else: + self._weak_senders.setdefault(sender_id, sender_ref) + del sender_ref + + # broadcast this connection. if receivers raise, disconnect. + 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 as e: + self.disconnect(receiver, sender) + raise e + 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 as e: + self.disconnect(receiver, sender) + raise e + return receiver + + def connect_via( + self, sender: t.Any, weak: bool = False + ) -> t.Callable[[T_callable], T_callable]: + """Connect the decorated function as a receiver for *sender*. + + :param sender: Any object or :obj:`ANY`. The decorated function + will only receive :meth:`send` emissions sent by *sender*. If + ``ANY``, the receiver will always be notified. A function may be + decorated multiple times with differing *sender* values. + + :param weak: If true, the Signal will hold a weakref to the + decorated function and automatically disconnect when *receiver* + goes out of scope or is garbage collected. Unlike + :meth:`connect`, this defaults to False. + + The decorated function will be invoked by :meth:`send` with + `sender=` as a single positional argument and any ``kwargs`` that + were provided to the call to :meth:`send`. + + + .. versionadded:: 1.1 + + """ + + def decorator(fn: T_callable) -> T_callable: + self.connect(fn, sender, weak) + return fn + + return decorator + + @contextmanager + def connected_to( + self, receiver: t.Callable, sender: t.Any = ANY + ) -> t.Generator[None, None, None]: + """Execute a block with the signal temporarily connected to *receiver*. + + :param receiver: a receiver callable + :param sender: optional, a sender to filter on + + This is a context manager for use in the ``with`` statement. It can + be useful in unit tests. *receiver* is connected to the signal for + the duration of the ``with`` block, and will be disconnected + automatically when exiting the block: + + .. code-block:: python + + with on_ready.connected_to(receiver): + # do stuff + on_ready.send(123) + + .. versionadded:: 1.1 + + """ + self.connect(receiver, sender=sender, weak=False) + try: + yield None + finally: + self.disconnect(receiver) + + @contextmanager + def muted(self) -> t.Generator[None, None, None]: + """Context manager for temporarily disabling signal. + Useful for test purposes. + """ + self.is_muted = True + try: + yield None + except Exception as e: + raise e + finally: + self.is_muted = False + + def temporarily_connected_to( + self, receiver: t.Callable, sender: t.Any = ANY + ) -> t.ContextManager[None]: + """An alias for :meth:`connected_to`. + + :param receiver: a receiver callable + :param sender: optional, a sender to filter on + + .. versionadded:: 0.9 + + .. versionchanged:: 1.1 + Renamed to :meth:`connected_to`. ``temporarily_connected_to`` was + deprecated in 1.2 and will be removed in a subsequent version. + + """ + warn( + "temporarily_connected_to is deprecated; use connected_to instead.", + DeprecationWarning, + ) + return self.connected_to(receiver, sender) + + def send( + self, + *sender: t.Any, + _async_wrapper: AsyncWrapperType | None = None, + **kwargs: t.Any, + ) -> list[tuple[t.Callable, t.Any]]: + """Emit this signal on behalf of *sender*, passing on ``kwargs``. + + Returns a list of 2-tuples, pairing receivers with their return + value. The ordering of receiver notification is undefined. + + :param sender: Any object or ``None``. If omitted, synonymous + with ``None``. Only accepts one positional argument. + :param _async_wrapper: A callable that should wrap a coroutine + receiver and run it when called synchronously. + + :param kwargs: Data to be sent to receivers. + """ + if self.is_muted: + return [] + + sender = self._extract_sender(sender) + results = [] + for receiver in self.receivers_for(sender): + if iscoroutinefunction(receiver): + if _async_wrapper is None: + raise RuntimeError("Cannot send to a coroutine function") + receiver = _async_wrapper(receiver) + result = receiver(sender, **kwargs) + results.append((receiver, result)) + return results + + async def send_async( + self, + *sender: t.Any, + _sync_wrapper: SyncWrapperType | None = None, + **kwargs: t.Any, + ) -> list[tuple[t.Callable, t.Any]]: + """Emit this signal on behalf of *sender*, passing on ``kwargs``. + + Returns a list of 2-tuples, pairing receivers with their return + value. The ordering of receiver notification is undefined. + + :param sender: Any object or ``None``. If omitted, synonymous + with ``None``. Only accepts one positional argument. + :param _sync_wrapper: A callable that should wrap a synchronous + receiver and run it when awaited. + + :param kwargs: Data to be sent to receivers. + """ + if self.is_muted: + return [] + + sender = self._extract_sender(sender) + 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") + receiver = _sync_wrapper(receiver) + result = await receiver(sender, **kwargs) + results.append((receiver, result)) + return results + + def _extract_sender(self, sender: t.Any) -> t.Any: + if not self.receivers: + # Ensure correct signature even on no-op sends, disable with -O + # for lowest possible cost. + if __debug__ and sender and len(sender) > 1: + raise TypeError( + f"send() accepts only one positional argument, {len(sender)} given" + ) + return [] + + # Using '*sender' rather than 'sender=None' allows 'sender' to be + # used as a keyword argument- i.e. it's an invisible name in the + # function signature. + if len(sender) == 0: + sender = None + elif len(sender) > 1: + raise TypeError( + f"send() accepts only one positional argument, {len(sender)} given" + ) + else: + sender = sender[0] + return sender + + def has_receivers_for(self, sender: t.Any) -> bool: + """True if there is probably a receiver for *sender*. + + Performs an optimistic check only. Does not guarantee that all + weakly referenced receivers are still alive. See + :meth:`receivers_for` for a stronger search. + + """ + if not self.receivers: + return False + if self._by_sender[ANY_ID]: + return True + if sender is ANY: + return False + return hashable_identity(sender) in self._by_sender + + def receivers_for( + self, sender: t.Any + ) -> t.Generator[t.Callable[[t.Any], t.Any], None, None]: + """Iterate all live receivers listening for *sender*.""" + # TODO: test receivers_for(ANY) + if self.receivers: + sender_id = hashable_identity(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, WeakTypes): + strong = receiver() + if strong is None: + self._disconnect(receiver_id, ANY_ID) + continue + receiver = strong + yield receiver # type: ignore[misc] + + def disconnect(self, receiver: t.Callable, sender: t.Any = ANY) -> None: + """Disconnect *receiver* from this signal's events. + + :param receiver: a previously :meth:`connected` callable + + :param sender: a specific sender to disconnect from, or :obj:`ANY` + to disconnect from all senders. Defaults to ``ANY``. + + """ + sender_id: IdentityType + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = hashable_identity(sender) + receiver_id = hashable_identity(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: IdentityType, sender_id: IdentityType) -> None: + if sender_id == ANY_ID: + if self._by_receiver.pop(receiver_id, False): + 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 _cleanup_receiver(self, receiver_ref: annotatable_weakref) -> None: + """Disconnect a receiver from all senders.""" + self._disconnect(cast(IdentityType, receiver_ref.receiver_id), ANY_ID) + + def _cleanup_sender(self, sender_ref: annotatable_weakref) -> None: + """Disconnect all receivers from a sender.""" + sender_id = cast(IdentityType, sender_ref.sender_id) + assert sender_id != ANY_ID + 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) + + def _cleanup_bookkeeping(self) -> None: + """Prune unused sender/receiver bookkeeping. Not threadsafe. + + Connecting & disconnecting leave behind a small amount of bookkeeping + for the receiver and sender values. 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 Python process performing dynamic signal routing + with high volume- e.g. connecting to function closures, "senders" are + all unique object instances, and doing all of this over and over- you + may see memory usage will 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 _id, bucket in list(mapping.items()): + if not bucket: + mapping.pop(_id, None) + + def _clear_state(self) -> None: + """Throw away all signal state. Useful for unit 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 + +As of 1.2, individual signals have their own private +:attr:`~Signal.receiver_connected` and +:attr:`~Signal.receiver_disconnected` signals with a slightly simplified +call signature. This global signal is planned to be removed in 1.6. + +""" +) + + +class NamedSignal(Signal): + """A named generic notification emitter.""" + + def __init__(self, name: str, doc: str | None = None) -> None: + Signal.__init__(self, doc) + + #: The name of this signal. + self.name = name + + def __repr__(self) -> str: + base = Signal.__repr__(self) + return f"{base[:-1]}; {self.name!r}>" # noqa: E702 + + +class Namespace(dict): + """A mapping of signal names to signals.""" + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` *name*, creating it if required. + + Repeated calls to this function will return the same signal object. + + """ + try: + return self[name] # type: ignore[no-any-return] + except KeyError: + result = self.setdefault(name, NamedSignal(name, doc)) + return result # type: ignore[no-any-return] + + +class WeakNamespace(WeakValueDictionary): + """A weak mapping of signal names to signals. + + Automatically cleans up unused Signals when the last reference goes out + of scope. This namespace implementation exists for a measure of legacy + compatibility with Blinker <= 1.2, and may be dropped in the future. + + .. versionadded:: 1.3 + + """ + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` *name*, creating it if required. + + Repeated calls to this function will return the same signal object. + + """ + try: + return self[name] # type: ignore[no-any-return] + except KeyError: + result = self.setdefault(name, NamedSignal(name, doc)) + return result # type: ignore[no-any-return] + + +signal = Namespace().signal diff --git a/.venv/lib/python3.10/site-packages/blinker/py.typed b/.venv/lib/python3.10/site-packages/blinker/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/LICENSE.rst b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/LICENSE.rst new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click-8.1.7.dist-info/METADATA b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/METADATA new file mode 100644 index 0000000..7a6bbb2 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click-8.1.7.dist-info/RECORD b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/RECORD new file mode 100644 index 0000000..3ff0797 --- /dev/null +++ b/.venv/lib/python3.10/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-310.pyc,, +click/__pycache__/_compat.cpython-310.pyc,, +click/__pycache__/_termui_impl.cpython-310.pyc,, +click/__pycache__/_textwrap.cpython-310.pyc,, +click/__pycache__/_winconsole.cpython-310.pyc,, +click/__pycache__/core.cpython-310.pyc,, +click/__pycache__/decorators.cpython-310.pyc,, +click/__pycache__/exceptions.cpython-310.pyc,, +click/__pycache__/formatting.cpython-310.pyc,, +click/__pycache__/globals.cpython-310.pyc,, +click/__pycache__/parser.cpython-310.pyc,, +click/__pycache__/shell_completion.cpython-310.pyc,, +click/__pycache__/termui.cpython-310.pyc,, +click/__pycache__/testing.cpython-310.pyc,, +click/__pycache__/types.cpython-310.pyc,, +click/__pycache__/utils.cpython-310.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.10/site-packages/click-8.1.7.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/WHEEL new file mode 100644 index 0000000..2c08da0 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click-8.1.7.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/top_level.txt new file mode 100644 index 0000000..dca9a90 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/click-8.1.7.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/.venv/lib/python3.10/site-packages/click/__init__.py b/.venv/lib/python3.10/site-packages/click/__init__.py new file mode 100644 index 0000000..9a1dab0 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff207f5b2f86768d190ab79886f15648ab867e47 GIT binary patch literal 2617 zcmc)M$yVD)6b4`eo^9qK%qS2-m~5snPi7411ULaUccUXqgp*G&hl3&@Iryj-%rcXD84JNU)RWBqZ4>bP7`JG&&7wb_Sh+3_FX?LYAF# zb6y_u>^!;^TG_4WHfUqFq1&OI-Hz^n4t58+6FS+Q=q~7DccHtXo867>fgW}bx)*xc zz34vZWB0jlyng6szd;Yc0J|SO2!rea^bicO2hqbY%pO9IzzBO7Jqn}j5%d_0u}9Gc z80<0ktv3$iYy&+36YRI{J8u#u+2iheZwjW^6Yd9Z8m8Ir&@(W@o^bxjEV1X&%dpHYpjTjpU35QstFX#mK(E0X zdl9`3>+B`;25hjG(VMWzUO{ic7W*T58@Ac2=pEQ$uc3Egm%WbOgFW^JdLQ=Lo9Ggh z*jwlWIACw158;r#;~sg(aLnFCpTG%w4}A)!?0xhn_{1)u&)|%Gfc^}h(TDJhb95D( zKK@b99=g)LGo&^wLrX7og>m^9RRiDf0;h&8>FZD`;TYvdBdQ8RM~*AYMi54!rL-`j z!0@a)k$q4yl77Xo1JAR3$8e>OgKZ_lNE^2`zhK<>uDlaQfU~Hl+4YJR!B)-#`iBr6|5Rv~{b0hhB zV)7z<8lAbcl;w#?C>)lyURO=oFDrK2fqyHNXVEz(7O}BVqVhC*t}5K{wZEH6YlfEA zrX%b?Sy4cfCtps?^D&(C=`z#Y4$8mcsCM#0pq$tF+U|wY|6RFM4iw#B$ARTMSL#Mv z6@h(i*w?td=bk+F{Ct~jynT+p+v53FGAGg%$4c>qc6^muB*cg>T$T*|I$M z^BJw5umC3kRj5(O%!9H*^Xc}wD0X3g z4a|FKVL2;2DlQyJcb>vY?JAE?x>n7%tJs+ct(vA9Tng35p~|iXu&sp`b^3J^Ql3waQU1KGtKZm76SYXx~u78MMlMY6?)G7{DUYL3-`jmFXDH8G2{osa$#|ysAVMP vL(9Iy&yp_M^b9GQru1cGnuYMOp5AUeKJbZ$|AhU95s&4Q`KJH(H{JX%YpS!N literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f1aba1e5bdea145090242fdab4d4e491cd4edab GIT binary patch literal 15675 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d2ce6848619ea784a5d1402a7204a55a7a6e2ab GIT binary patch literal 1551 zcmZWp&2QT_6elT)mKDcYgESw*x?2b6(74+Uy%a@(4H!BM2DT0>U~C{1ld)yXl0!;% z63D=YWPe35AUW>5|AyC{a@@81$ljCP&Rr?+iSO|}y~p4CQTgU(NMQUX|Ip8TLVibO zeQ;2o!nB`&P(;y`^p>7#vpU>#3kS_MLr9#sS~Q0pWD&|&;y6?d6+ql?mH-9A9}W;9`iaD4`|K14w(UU~Zf+67zq6&X=; zzoLpAkcFs(B9;F$t{au8d`0SYP_ZjkHLfWoRe-*a0qp0bV)kLZL$ADRg1czN8F}3s z3JGs+VMN?{llauVcVu)tmT8_1DSc4}p0!0Ia3+*)S zYnkff!tpe=h4cC)2&3(<#O#2}tFJr5e4;y(*o;ft86-t#W~LK0dob5Wox_>VW}P%S z>P*jyVV-?@`0>MzO$z-0zB`7-+fF}C`s0p7F3bV?!|9p3BZqOOQpo$dWGu#Fx^_db zfVSWXVRE`n`R)0=wZ0v`6YE5hDV-I42Jx>49yWl9ytChc_=!MA$bw;C7G4Fd8NJNs+{$FA9!7Zbagb0glp=ooM;ml8hMu{1zt95_QAp6fy^el z@==~-kyv7O4=v2hoR_FmU?>FCIQ}1;jV1ar&(gDxAjY;qaJmE71Tc44$jizix27fLzFRSDdbt|jG38K5I9{Zbd_80TnpG<_W*!KH$w^jQBY5_J3Z;lhi*)+)p nCW2TOuKurZ_v#XA_qB9&_L?}sB-U?(hIih$r1+x7kh_Ctfa literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..089f58556ab0ad067d1de2dcc09af370988e2a11 GIT binary patch literal 7667 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 QGUTQr)RHBsW&h`Y0fBq=x&QzG literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d1d7e760b996de63b5b35ac3644e17d7ff6898e GIT binary patch literal 91145 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..35078adea5da1322cfd08f7db15ff38f65cf4afa GIT binary patch literal 17215 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�&(q+QJ z!ZUL{hm&`ONw>v?HN9{QU$4Z_K(O&Mv&@lDf`eV?D#@>{(?q<((Dt(x` zb?GU(@4S(S`A&F_fB7V@>naH73Euvkq#U9f9B$ne>9HH+{0KG&uqP+b2fGp={U-tL zbEq#Pomk9aZ@{**-21E8_LsJU4NJ?$My7qs&f34WZx!=44(vI%_yk9PzpOaD#8%!d zSS+1B9b0341$|x88@Qi~iU=Nk;ACyWz{3~mXa*OChDxG&8S8XKbK?v#r-30+CI0&= zK_F3nxkey_HK?sLJ4-l;q~GJ~B`i)Ty9)jIQE%eOKuAy)mJhH>IG2VAQBJzhf5%ol zF*Xof{xyF-j9WAj&oSo2&&b*tJSff-!PcTRg@1Ooh#g>Fjy+)=x1C3mxMC7)Mr`pZ z8q{&6A8P#XoX$}dLETL4j1Q!FCPGK;i4i&W7}X>YIV{LPjJntRDW=g!x(` zp_?lPE8Rf$NN}*GjX$D82&M6NSn;7L=8}dxhjZ|Fk``D&%(c%`W--7R z)@2ZEf*gDz8q`Q7UZR)IK}vkgr(uq?8OuJ5G{15T$o{`NFtJ#3k}L z>?W9$U_c2&j6gFs#7=66u^IViXo%#?U*JnDPgF!WBWx5Kq<_K(UEbXEMuiY1Ifjf$ zK>4MCnL=)*cXVI@My8hXW~B#Bh5j4TlVs76*h*me6R?=bR@In^{75~g=`b17KV->G zZ=$13-1+He^xvX7 z%7r*Nfj{TO7uz7?6+1AD&5oz!@UGc?S8Th= z8+Vq>x-i)$xfL;jnyemJCYL{Dt%@%KVs@MU%NDAFAK+fh6nWZ4+?L!;8TUNwZrR2^ zYPz+Pvvjn9FD2O?}>*U=RV7UqvKonE0-@FxV{Oe@`Y2f zZMZ(xqQ-ITFD7!8UpZygCKP$jXTq+0X%}#^=S$do{4x}dIpr@VE_`*g;h2YLAKPz_ ynVIm383$%}^!B>r4;(*ePl-#1bI<=u#*R^PRz=LJn6rO{`QMxhtGkNyWrNf2uQ literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d60c03da4b831c729a1280d0350cc2268a509795 GIT binary patch literal 10259 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8949267729bf29936b6d42244385f6048e4f1509 GIT binary patch literal 9464 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ced5b8d619c432b4553325a62c46688d03fe5bbc GIT binary patch literal 2436 zcmZ`*-H#hJ5MOULxm@m}y=zPF+5$%6E2vEh2q8rXfle))Kxx&Ugc^hrXYFM7&RMT) zZ*nB_yRC*QS39=vP%T7}5)p&&ma%ocU)j?8u?DdvG z-r$${7H{yCC)LNKx8hc|c}=YHI*ix&^0qe$_*y9k?N?>%DC@28EBrj)coOv1`BlEj zFTm&=zs4`36|uVQ74~oh_Ac?);G6TD-1nNVzX0@Jw@LD?3BS9CAQbz+_xZ9$1FNzHf zSwe?`W=3$z3}tl2=G3YNg~q~Am{)8RWKlKT7onvittONu^I0UcC{2P@Mkh)O8c$N7 zKDLE536YU78&3sn;E;7jSrT>zDKn-#h5_XwRGL|(OM9qfW0la@I76w9ArxXcN7SQC z(vi|M5;7IqP?LobI`g4=OI!-ys0I2qH}8qkQ? zGzObPhOEHGr&uf)Xf>RfJw?;ZL}zJSr=5wgQD?Bola>ipDh4MRUl?h%=oGMni;Q!@ zJ01E->t<&Jv^19SedXWxg_0!f%W#u zQ=gMDr03JhvGt%S3JpAG1|&pxd93W>&cd{ufZ#X=Tt+Pa{;SR;leYhx~{DI zNAKJd6Ey|o7(`a3REnv9Y{Hzzr2=!eS#fY3_Pmm+^aLhX|FGcYDwtaFERqRkP;{^;2!5R^U_;L^ z1)Pdh>Hrl|N0ke9q^msYvcNh)cTeN>0HKLDf_}3YQ9P64bId`5VO{rDNzJbl?1RcW34&|n MO3>J9RNt=t0}q{Z)c^nh literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28dfc5a7b9e07d2736fc7c805b2e8a10eaded305 GIT binary patch literal 13677 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66ea583ab5d290f4a9d91b81f387a798e4bdf07b GIT binary patch literal 26137 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

pKrQpBRgXtRGSiNw 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 VvSdEWsCn=Bk^AsEt0PB?{|5*HwEh49 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed92e123b25dc4aa0b48b35dab834f4eeb88c153 GIT binary patch literal 15210 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc b/.venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b92089071dd786ced287d76b01fdc82ff095356 GIT binary patch literal 33694 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 gP1s|*a6LS>b8N@t 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�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 Qc~8c-adoGVAHV 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.10/site-packages/click/_termui_impl.py b/.venv/lib/python3.10/site-packages/click/_termui_impl.py new file mode 100644 index 0000000..f744657 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/_textwrap.py b/.venv/lib/python3.10/site-packages/click/_textwrap.py new file mode 100644 index 0000000..b47dcbd --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/_winconsole.py b/.venv/lib/python3.10/site-packages/click/_winconsole.py new file mode 100644 index 0000000..6b20df3 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/core.py b/.venv/lib/python3.10/site-packages/click/core.py new file mode 100644 index 0000000..cc65e89 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/decorators.py b/.venv/lib/python3.10/site-packages/click/decorators.py new file mode 100644 index 0000000..d9bba95 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/exceptions.py b/.venv/lib/python3.10/site-packages/click/exceptions.py new file mode 100644 index 0000000..fe68a36 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/formatting.py b/.venv/lib/python3.10/site-packages/click/formatting.py new file mode 100644 index 0000000..ddd2a2f --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/globals.py b/.venv/lib/python3.10/site-packages/click/globals.py new file mode 100644 index 0000000..480058f --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/parser.py b/.venv/lib/python3.10/site-packages/click/parser.py new file mode 100644 index 0000000..5fa7adf --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/py.typed b/.venv/lib/python3.10/site-packages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/click/shell_completion.py b/.venv/lib/python3.10/site-packages/click/shell_completion.py new file mode 100644 index 0000000..dc9e00b --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/termui.py b/.venv/lib/python3.10/site-packages/click/termui.py new file mode 100644 index 0000000..db7a4b2 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/testing.py b/.venv/lib/python3.10/site-packages/click/testing.py new file mode 100644 index 0000000..e0df0d2 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/types.py b/.venv/lib/python3.10/site-packages/click/types.py new file mode 100644 index 0000000..2b1d179 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/click/utils.py b/.venv/lib/python3.10/site-packages/click/utils.py new file mode 100644 index 0000000..d536434 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/distutils-precedence.pth b/.venv/lib/python3.10/site-packages/distutils-precedence.pth new file mode 100644 index 0000000..6de4198 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/distutils-precedence.pth @@ -0,0 +1 @@ +import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'stdlib') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/LICENSE.rst b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/LICENSE.rst new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.2.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.10/site-packages/flask-3.0.2.dist-info/METADATA b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/METADATA new file mode 100644 index 0000000..71551b9 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/METADATA @@ -0,0 +1,116 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 3.0.2 +Summary: A simple framework for building complex web applications. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +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 +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: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Source Code, 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 using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ 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 + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Chat: https://discord.gg/pallets + diff --git a/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/RECORD b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/RECORD new file mode 100644 index 0000000..5e62597 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/RECORD @@ -0,0 +1,58 @@ +../../../bin/flask,sha256=R2JkQ2lZ6TT9kQEC36BR22gtrgCikahNF1h-jtuJepQ,237 +flask-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask-3.0.2.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +flask-3.0.2.dist-info/METADATA,sha256=5SsBudAoun3E_3ZSRXJLB2V3NAdALovsQMKUvzqcJfM,3588 +flask-3.0.2.dist-info/RECORD,, +flask-3.0.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask-3.0.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +flask-3.0.2.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40 +flask/__init__.py,sha256=6xMqdVA0FIQ2U1KVaGX3lzNCdXPzoHPaa0hvQCNcfSk,2625 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-310.pyc,, +flask/__pycache__/__main__.cpython-310.pyc,, +flask/__pycache__/app.cpython-310.pyc,, +flask/__pycache__/blueprints.cpython-310.pyc,, +flask/__pycache__/cli.cpython-310.pyc,, +flask/__pycache__/config.cpython-310.pyc,, +flask/__pycache__/ctx.cpython-310.pyc,, +flask/__pycache__/debughelpers.cpython-310.pyc,, +flask/__pycache__/globals.cpython-310.pyc,, +flask/__pycache__/helpers.cpython-310.pyc,, +flask/__pycache__/logging.cpython-310.pyc,, +flask/__pycache__/sessions.cpython-310.pyc,, +flask/__pycache__/signals.cpython-310.pyc,, +flask/__pycache__/templating.cpython-310.pyc,, +flask/__pycache__/testing.cpython-310.pyc,, +flask/__pycache__/typing.cpython-310.pyc,, +flask/__pycache__/views.cpython-310.pyc,, +flask/__pycache__/wrappers.cpython-310.pyc,, +flask/app.py,sha256=TQfhvSlv1QpaPHeeRz_Ke7JmiSFMMHT-rJR4tqsEHdc,59706 +flask/blueprints.py,sha256=H7u4HzNn--riGMTt5GkxUHpYRzCav-WDGSKNnBSEMcU,3160 +flask/cli.py,sha256=eegT_64cSOqaKOwI_Am3XwaCSJPZ9UEJ6EmSL0qg8xg,35833 +flask/config.py,sha256=QiL9KkQT8RWc0HU2AE26Yw5mdOkNsKv8TEFEbXkqhJk,13328 +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-310.pyc,, +flask/json/__pycache__/provider.cpython-310.pyc,, +flask/json/__pycache__/tag.cpython-310.pyc,, +flask/json/provider.py,sha256=q6iB83lSiopy80DZPrU-9mGcWwrD0mvLjiv9fHrRZgc,7646 +flask/json/tag.py,sha256=aXslvQyO4QpxviWJqxhyOj0CCQKlYXq1r0H9DKqiEY8,9280 +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-310.pyc,, +flask/sansio/__pycache__/blueprints.cpython-310.pyc,, +flask/sansio/__pycache__/scaffold.cpython-310.pyc,, +flask/sansio/app.py,sha256=ZF0Yy610NKSpdJ1d6qtG4L2RkCmzngu0G9FFXZf4O_M,38209 +flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637 +flask/sansio/scaffold.py,sha256=9SSSC6A_zzXhcEVYf9wkrKx2r4uDqfIWsnRNYSvDclU,30879 +flask/sessions.py,sha256=bIpZRwiTfnYJn3ikVnCPcF2kNtyRz0dfpsuMADIpSJc,14518 +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.10/site-packages/flask-3.0.2.dist-info/REQUESTED b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.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.10/site-packages/flask-3.0.2.dist-info/entry_points.txt b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/entry_points.txt new file mode 100644 index 0000000..eec6733 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask-3.0.2.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +flask=flask.cli:main + diff --git a/.venv/lib/python3.10/site-packages/flask/__init__.py b/.venv/lib/python3.10/site-packages/flask/__init__.py new file mode 100644 index 0000000..e86eb43 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/__main__.py b/.venv/lib/python3.10/site-packages/flask/__main__.py new file mode 100644 index 0000000..4e28416 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec78a2791599cf999e15d70bb7e52789a522e4c6 GIT binary patch literal 2288 zcmb`IJ98U16oq$}kL5!WB}$^+(&|Z3wn)i#(!|Ncd6k}w?M!CS>@2w;xhD1zEGStS zxk=Kd${$F|)cH5trgE7kh129*h_p3I8*+5`;Q$L9a%=B;5Fnq%|g%O&}G>I)?v7Ddt^CBM>SOH$nFNk7jGh1^}l)^GAYqmuttg@=+ zl9&l+*{tR=c#h3!u7GQ-rnw59XY-n8#6nnSbv>nifEZx)r+E7c`Asb^ywQE1ey7lX&m9V@Rjh=5up5;81qC1kwT;R zc^vhF0jTcv6_>6W2B|CgcVnJX|7I^vuH4>ON*<}H@Al$I@mJJe8+xhhCCM#ok*vuK zx9sY45{$-!Car0|U&u~*nj&zx1+N=Rn!M0Q$V0%=fGbxwxbKD-=nZ%Zzd^p@VIn-m zT~8?)bjOOLXEyXk98shRazRE(azBu~NAs3b9{FxR5Y(}F(~xoK-VBK4m9~}SUg%y1 zYItiG_E-wHA4`m|DX~GH1}|VwlbpCooFv@8YmU>QHdk(qRNTWU3|v3Hq-{6491~N} zkxvIP*%o@12l4yd^H)8d&=I4fHp#^_H?ZcXnePWtFj=%V^-|?YrQ=wdT6cn2m@YdB zLl4IDcSCC2vD_57kLXNmAWGbHB3O+(*89Qsvv-wNdNw(%EFXCx&vJMuD@v}$GJ0E3 z?I+Pyk4k#_p*LRvf1lIa?=j#SZ@-Zx*L}-3gz?(czvgS}+IngEIfeJ2U-&s^8rSB_ z{I3PS_?!9MP{nKGNAm}>Wk1cTu6w~H)u8K2TIu^=UJSX@yk$3?cQxh&spI1s@g7Rg zcf81VE(0N)E_Wmk;|q8}rrPB<;1obY0Zad`4 z^F8IYCxIOAQPGd~T1`xr;;8)g8w-&krxl!KZzT8y7dQ80)Uvbsf2Ybym!6DpG-;M6 z%IaTCqQ>&y-gIT9>B5;kSvi|~GQCY-N{M>U$$MBhE5BPoK0^CGr*dfrA}>Gs?C@fZM8m7RahRzZ+p098on7S-(^eKOYIVf2t1q@#ri(c`Rm)k)PdU$| e!?WftN5;YmV`vYQQR0T4@%uk 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 Mn4|cf>HhqG0Pr?p>5erz;cRoi-J4LnblI} zmuH5OB`7&mzV=TjU>|$#f5U4}Iri#H^LykjcjdUZhLXtnd~e=+zxR8ibbY;J;rW;U zANg(9vi?n-<)?|xA1uq(-=iTcVMkVM4{e*;PUH-o^4l0T@ohw{xIJuRt|?m4O6(5Z zvfYkWCwpXIHxI0`g+b-HyhF5G$Hjl2VPqAw?+K4xYo3{1P5*@Mj(h_TO{h~4K z3g^J;b$_6f_3UDeCrN6!3DZRHqrYmxSPB^#{)0VR5#&nA#P~eRu;7}OiSQ>XjeQX+ z8JJX^(!P69E;AJ-hSt=b18MT?0P-b<-6v9K&?5s&vgdtmM1zQSt5=JuNv3%3fMzM3YpC+**S`vh=x9|Q}4WY3MCVsN9GoEgql@mYc>$v@WJR{ zZ~t@u!J{wt{I7Pu^>-ic`JeAS*!||qrz1vjtmV-8f;5?ghq)>d!P3cG#`lwm>u25) z7DgU>O3G%c^+HSvE6M+((Jgi|4TC8&GKzF*|5&9bS}Jl(u1j?yB=GSFr+%JGZ5D#U zL>tKkor1FxmzB%rQlUK8Igg@KmMJ-rijO0?G&s_4BGjWKyU!blw z?UTD~n&#@=dbkj!mOI|>YAwZ${~6HzUR$+*kDxkRJD= zaNN&M;l$*(-Y0kZIyCZj#)D_TxbByz>5u2!puOz0xPB-NbQ6mJ;QlNhHla>~Hm%O4 z>oo0-)3uw<*@rcgc<R_`J`F+alVG!>7i1r%s|m|i_Iz5{(Qdl zX3>3;CqxH(N~KDDfHUjv-lNBVG2U)+dSKLF z14_dAL+u)+AEN{G*~hkW4K4(PQ)3(FsPU=^bhdz3l%b2N===jk=W&J-!NHo9zN%U% z839>9CLlV4hDuX2!^<+j6qq$k4wta;0HsI1;Bf}q30g#vWeFOMGzwMBJ^egF*#d+U z`J#;8d`XSA(FnH$BsrFyOabar$Y@m3D#kEL+rf{hhXPs*7(F34q_9ScTFyymrh^5H zK)eCGd3zkC!84F<#W#z2B3{};3Oo|!&)u@Ky*T@Jk8xz{pw>d$=m8BTo_rw#WT*~Q zn3Aarq^4Uy?zN0_pm|}UASAWz2%&Jut?}j>-KxiiY(ShBo!vLj@NvYD5e^v z;?uKBLs5OpQ-%&~_5Gsb`-p0e3g{PI-+zvaOf^$6+J~foIB3b7 z(lBDH^3uD3hIa9Ct&ZLK)kbv{?!8BnCpj*@kgPxymfFFqXq(dv39o)l9Tzu4NgP_; z3RVuIbj%}NT^?4ZGRknzsaSPW^8{BOZ&AdnEBDoda=dn*qN5b+PyhV&o`3(3d-uP1 twEwVhPZUy;WRaWRWlG`xzH-B7^#6t?>$;ZfxOUg>;toJRZG7Kv{0K|k#EJj_ literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac1ef26312c75fe5c27e3c9d137c1d65caf15c35 GIT binary patch literal 29087 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff1ae3408cd313f3eaedfd5e444b687c106af06f GIT binary patch literal 13422 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
AA^-pY

literal 0
HcmV?d00001

diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..269376d0539b11f425296729ac045cdfbaa4e12a
GIT binary patch
literal 6592
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ðNha&3q_%3t$L7^Nn2^
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

literal 0
HcmV?d00001

diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..810d97f263e13c7626375e5ddea86a1813962082
GIT binary patch
literal 2548
zcmZuz&2Jk;6yI5|KWpc!AC&JwqNJA6bx|b_Rulng(pE%mr3Mg2m3O=|wl`Vtx-;XX
zjzR@$CE&u13#a7RGZ+4rxpLyjksg5eX4h#-SjoFHv+uom?>E2qTc?di&4KIJ?w{gL
z)p35u$?2;IlaC#TsGnfK9Zq6rL^_1v*p1zeYoCQq!9KlC5uSy(G%9z>VB_&(Tp3k6
zRpN-^PE9VuN+~`!s(0$JQsx(VmDiqmPf4f2FY!4(|IF*m3HNATG>%DUK`b0C!fc5z
z9Ft?*^EG~+UjUo)+)5p_4NM=%&;?YDX
z4Q~sdjK`)Vg`UXdMMeAD;<3JSFT_}cc%dRyXY<>cRB6h_W0{U+#I&G7%2ZONrC=l4hap;lK^%oPSD)VLQ%3X5Y80+WQ5NcG
zPpr^59Z;RpAlO%f$hWan5UkJ?qR9P72|9sa5U8p0mF8d&1b)p%fw0qbLc=uaM}vtJ
zIFmHpPiQ-gnNsZlf)Ao(;6Jd*-DU}og@oYfHeyq{&k_y0+i19r9ztfb60(YH_Gr&w
zgNcG@v>(NSLY+Jc^~vtGR0=!TU?EGEHH}8&RKf-rl}A#9I-X{m!+QXvF958RMu4ZX
zZb1Nt)NZxkX5lUy
z2$iMRnx!|Mnx(TT&ckl11UIi%BPCbPVQMAx5%R^{%y-Mqjn_-lI7AN5E~KRgzXDQo
z69$LQk#p?)2+wcGA(8KC^1agsqH_0H<&f;SH=U>CDUp{rP!{F|^;Q)c(~dp#P!*gt
ziwD1~4@J03qdxK!&J?*whZ!|!lvwuW>Cte=>X1%
z9<~F~@54#MD;kSE5!2NtuU6|1gx;9hY@x|oew=3zfa;wah`<{#_zr4+SixF$oFANB
z@`Xd3M<7g46}kJIn4;aT=^EF+ZpwK@atS=Mqi?{-R96Qg5s$}mZ5gHtA$GsL>>Rv5
zWU6ZebaPLCHAZ<+YyOGL_GYta7SE(_3M`qLO75pj6}5p4KpRYH3~iI>rYn&TrW{Tr
z&a;GUYBsCIGrPZw*(7FSo^lGXC{Yq6AgAkV{6JX)W6U1otz!>00yEOhW9=KCU3gENQXmOI~fgq*=6>eb%o1(4X($dr*>D!s0n0YSx
zY!d5PS3xJd1D>`WUMjM*UC;>O6RJfwLjxJ8P_yfex?3j|w+4M6v1=hl8Dms%>}8=A
zaKWxFW~+7=_COD^k4$6xtNR<>_1hckpWV58%hVK0RFwL&#s}8tr
zTEMlCrg}28<(-1XezGh!mDQ}3*YG2uDBS8!#jTJE0dU+B0OS_xq&8o>=)s!z&s_0e
DnJLo@

literal 0
HcmV?d00001

diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5590c576171527932e2f3183965736085d681ea7
GIT binary patch
literal 13290
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

literal 0
HcmV?d00001

diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b15ce2dd7ef68ced1110dc885785da882766ade5
GIT binary patch
literal 811
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 E8?C$7bN~PV literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3442c1b1095d684551fb6cacbcd371e726542874 GIT binary patch literal 9848 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 RD|UH_tY(aY?lN}9{{imU`H27k literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22e277b06e5963f27a459f8bd0044936cafc50c2 GIT binary patch literal 5545 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 Im2(IG1-Z%iLjV8( literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df61adc627f267139175a5868eb99e0f3093b139 GIT binary patch literal 5239 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 bg`bee#^mH}qhYp@BlJK0e+}b8<@Dr#Oa7a% literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/app.py b/.venv/lib/python3.10/site-packages/flask/app.py new file mode 100644 index 0000000..12ac50d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/app.py @@ -0,0 +1,1488 @@ +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, + ) + + # 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.10/site-packages/flask/blueprints.py b/.venv/lib/python3.10/site-packages/flask/blueprints.py new file mode 100644 index 0000000..52859b8 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/blueprints.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +import os +import typing as t +from datetime import timedelta + +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 + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +class Blueprint(SansioBlueprint): + 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.10/site-packages/flask/cli.py b/.venv/lib/python3.10/site-packages/flask/cli.py new file mode 100644 index 0000000..d4df280 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/cli.py @@ -0,0 +1,1111 @@ +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.10/site-packages/flask/config.py b/.venv/lib/python3.10/site-packages/flask/config.py new file mode 100644 index 0000000..f2f4147 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/config.py @@ -0,0 +1,372 @@ +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.10/site-packages/flask/ctx.py b/.venv/lib/python3.10/site-packages/flask/ctx.py new file mode 100644 index 0000000..9b164d3 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/debughelpers.py b/.venv/lib/python3.10/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..2c8c4c4 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/globals.py b/.venv/lib/python3.10/site-packages/flask/globals.py new file mode 100644 index 0000000..e2c410c --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/helpers.py b/.venv/lib/python3.10/site-packages/flask/helpers.py new file mode 100644 index 0000000..359a842 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/json/__init__.py b/.venv/lib/python3.10/site-packages/flask/json/__init__.py new file mode 100644 index 0000000..c0941d0 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/json/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/json/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c288eaffd22490a6785c23ec80f46a07949b3d0 GIT binary patch literal 5995 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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.10/site-packages/flask/json/tag.py b/.venv/lib/python3.10/site-packages/flask/json/tag.py new file mode 100644 index 0000000..2bb986b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/json/tag.py @@ -0,0 +1,326 @@ +""" +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.10/site-packages/flask/logging.py b/.venv/lib/python3.10/site-packages/flask/logging.py new file mode 100644 index 0000000..0cb8f43 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/py.typed b/.venv/lib/python3.10/site-packages/flask/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/flask/sansio/README.md b/.venv/lib/python3.10/site-packages/flask/sansio/README.md new file mode 100644 index 0000000..623ac19 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/sansio/__pycache__/app.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/sansio/__pycache__/app.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3d15e504994adb52469e820134a7918d9be0eaf GIT binary patch literal 28612 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 N@kBOVs^q8M{C^zAx{Uw; literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/flask/sansio/__pycache__/scaffold.cpython-310.pyc b/.venv/lib/python3.10/site-packages/flask/sansio/__pycache__/scaffold.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..482c371f7c6e943d9fae6b0d28cb91cd581467e2 GIT binary patch literal 24086 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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 + + # 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 _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.10/site-packages/flask/sansio/blueprints.py b/.venv/lib/python3.10/site-packages/flask/sansio/blueprints.py new file mode 100644 index 0000000..4f912cc --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/sansio/scaffold.py b/.venv/lib/python3.10/site-packages/flask/sansio/scaffold.py new file mode 100644 index 0000000..5355700 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/sansio/scaffold.py @@ -0,0 +1,805 @@ +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 + +import click +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 ..cli import AppGroup +from ..helpers import get_root_path +from ..templating import _default_template_ctx_processor + +# 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 + """ + + 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 + + #: 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: click.Group = AppGroup() + + #: 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.10/site-packages/flask/sessions.py b/.venv/lib/python3.10/site-packages/flask/sessions.py new file mode 100644 index 0000000..bb753eb --- /dev/null +++ b/.venv/lib/python3.10/site-packages/flask/sessions.py @@ -0,0 +1,371 @@ +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() + + +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(hashlib.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.10/site-packages/flask/signals.py b/.venv/lib/python3.10/site-packages/flask/signals.py new file mode 100644 index 0000000..444fda9 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/templating.py b/.venv/lib/python3.10/site-packages/flask/templating.py new file mode 100644 index 0000000..618a3b3 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/testing.py b/.venv/lib/python3.10/site-packages/flask/testing.py new file mode 100644 index 0000000..a27b7c8 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/typing.py b/.venv/lib/python3.10/site-packages/flask/typing.py new file mode 100644 index 0000000..cf6d4ae --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/views.py b/.venv/lib/python3.10/site-packages/flask/views.py new file mode 100644 index 0000000..794fdc0 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/flask/wrappers.py b/.venv/lib/python3.10/site-packages/flask/wrappers.py new file mode 100644 index 0000000..c1eca80 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/itsdangerous-2.1.2.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/LICENSE.rst b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/LICENSE.rst new file mode 100644 index 0000000..7b190ca --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/LICENSE.rst @@ -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.10/site-packages/itsdangerous-2.1.2.dist-info/METADATA b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/METADATA new file mode 100644 index 0000000..1d935ed --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/METADATA @@ -0,0 +1,97 @@ +Metadata-Version: 2.1 +Name: itsdangerous +Version: 2.1.2 +Summary: Safely pass data to untrusted environments and back. +Home-page: https://palletsprojects.com/p/itsdangerous/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ +Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/itsdangerous/ +Project-URL: Issue Tracker, https://github.com/pallets/itsdangerous/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +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 + +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. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U itsdangerous + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +Here's how you could generate a token for transmitting a user's id and +name between web requests. + +.. code-block:: 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 + + +Links +----- + +- Documentation: https://itsdangerous.palletsprojects.com/ +- Changes: https://itsdangerous.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/ItsDangerous/ +- Source Code: https://github.com/pallets/itsdangerous/ +- Issue Tracker: https://github.com/pallets/itsdangerous/issues/ +- Website: https://palletsprojects.com/p/itsdangerous/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/RECORD b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/RECORD new file mode 100644 index 0000000..2a39531 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/RECORD @@ -0,0 +1,23 @@ +itsdangerous-2.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +itsdangerous-2.1.2.dist-info/LICENSE.rst,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475 +itsdangerous-2.1.2.dist-info/METADATA,sha256=ThrHIJQ_6XlfbDMCAVe_hawT7IXiIxnTBIDrwxxtucQ,2928 +itsdangerous-2.1.2.dist-info/RECORD,, +itsdangerous-2.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +itsdangerous-2.1.2.dist-info/top_level.txt,sha256=gKN1OKLk81i7fbWWildJA88EQ9NhnGMSvZqhfz9ICjk,13 +itsdangerous/__init__.py,sha256=n4mkyjlIVn23pgsgCIw0MJKPdcHIetyeRpe5Fwsn8qg,876 +itsdangerous/__pycache__/__init__.cpython-310.pyc,, +itsdangerous/__pycache__/_json.cpython-310.pyc,, +itsdangerous/__pycache__/encoding.cpython-310.pyc,, +itsdangerous/__pycache__/exc.cpython-310.pyc,, +itsdangerous/__pycache__/serializer.cpython-310.pyc,, +itsdangerous/__pycache__/signer.cpython-310.pyc,, +itsdangerous/__pycache__/timed.cpython-310.pyc,, +itsdangerous/__pycache__/url_safe.cpython-310.pyc,, +itsdangerous/_json.py,sha256=wIhs_7-_XZolmyr-JvKNiy_LgAcfevYR0qhCVdlIhg8,450 +itsdangerous/encoding.py,sha256=pgh86snHC76dPLNCnPlrjR5SaYL_M8H-gWRiiLNbhCU,1419 +itsdangerous/exc.py,sha256=VFxmP2lMoSJFqxNMzWonqs35ROII4-fvCBfG0v1Tkbs,3206 +itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +itsdangerous/serializer.py,sha256=zgZ1-U705jHDpt62x_pmLJdryEKDNAbt5UkJtnkcCSw,11144 +itsdangerous/signer.py,sha256=QUH0iX0in-OTptMAXKU5zWMwmOCXn1fsDsubXiGdFN4,9367 +itsdangerous/timed.py,sha256=5CBWLds4Nm8-3bFVC8RxNzFjx6PSwjch8wuZ5cwcHFI,8174 +itsdangerous/url_safe.py,sha256=5bC4jSKOjWNRkWrFseifWVXUnHnPgwOLROjiOwb-eeo,2402 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/top_level.txt new file mode 100644 index 0000000..e163955 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous-2.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +itsdangerous diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__init__.py b/.venv/lib/python3.10/site-packages/itsdangerous/__init__.py new file mode 100644 index 0000000..fdb2dfd --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/__init__.py @@ -0,0 +1,19 @@ +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 + +__version__ = "2.1.2" diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..514f2d5286238a88fe5020c568c02b8ae56a920e GIT binary patch literal 866 zcmaKq&2Q5%7{-&fY11_6=T;DBE1P)KjO^4 z!l_qI9JzAheXXf#Igluie$V6Auk7e8lO*!s`JVmevhI05(d<7pFfZXVKR}qreCa8l z_&#zCxJGJ@>%etVcifN-6_CJj0Nf-^$4%fCX*q5Iha_|y0=G%qaT_=yk>f~qR7_&W z9hs;u={k;qd!*+$0q&E&zi literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/_json.cpython-310.pyc b/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/_json.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e28a6966957a29026840f555043ef56b542564c1 GIT binary patch literal 921 zcmZuvOKTKC5bnp!>|`?m$wBZocpEW0K5ils2`DJ6LKI;yP49N^?re4*cK2-9kXv&0 zHzeT2v;V-K(N|9%z2;=qtjH=hR83b`P4)MEUG?5xpTPPme(G5 z5k;3|M7u8=@s~s~#V?8C7i<(LdQ7t52h@?_1pW5vL2w9W--6R!j}cRJ#C4#U4i}N` z>3GWSKre`Prhy7nco|&KQ6DNIJX5{SbKRRpDposPc31V`)?J^7qq=P5#JxIxGdz3r z!N{i3CY7dcE0r#6U8QBM+NDn2T)NacQ#3X`ofl49_)QOduaWCzEtQXqcCD!5=hRkE6C;9~RcouIhoP|PCwI6 z$TuANL|3*oT1Y!7iWk0bbt8>*wXqqyq4#g-lZ@l3Q+g`fr86O1;X~Dy4OEyNhzzRO z>9cW2#oPjyfLSD$u!Qc@e|U8*hFRicAu3sFA$(tm&C|j@5#nPjm%lSTAyhrVW9y_V zCZz_2m1n~F@O@RldvO>9ACA{B1)e{zHmY_owxHo7nhqbzhEyzqj7dNlODW?iHJHgl kAK(;h*hX&M6xGb!hD?|KUq>H5-C%!)6V}m=Nlf?oFPA0WM*si- literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/encoding.cpython-310.pyc b/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/encoding.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40d4aefda334ea19e47460862888be284a7c5f26 GIT binary patch literal 1870 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 O^^NAnxefQs`Tqe(hvW?a literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/serializer.cpython-310.pyc b/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/serializer.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3880c5da5ed7277ba1df9d86fd7eb4992c7d706 GIT binary patch literal 9693 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/signer.cpython-310.pyc b/.venv/lib/python3.10/site-packages/itsdangerous/__pycache__/signer.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7270be919625dfd3aa311a80c55f76606503e72 GIT binary patch literal 8461 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 W2i>0i)ifL6($p-qt}DM-JpLcM)yDunt{>% zEbPuT=Zqd?QFp#MZ}c#$bgRv(MLr^Yjz_l$kHq}8)2zXGo>yR85jC*5%>}Sjc?~Qz zuvEdahg-{Jap69!iY(o?KrUKkCB9g6do0nPEMHxMaka&ic>8S3MN)7vV-Weo5Pit_ zXKauajDtH`7BXd7IusH{3)j=G;8RnA-)!E3{@vL(FU`Ce?DnSix5-*C@;lbZ`O&&Y zQZjOXvc5w?hf9|q;QH$lcXNIC-o>JyaheyJPLLgQ*&sW?1VBt!UkO^YDIhCuCZea) zA_oX-g-knX&azlYS;*mqX*kR~#b7g8p9X9fQW!5cGyq0Se2XFEMKh@tvP`k7pags5m z;`knUc%!jebVZ}fbYQZ-fa&OE`(XhsjlMCI}*&VC8S%P3w2aTacc z2qUnOb-;Gv8QQKLTCV+{z|F34v08?4oU^Wo<1&ilZo&H*>XkVDqR+C4Cx~NSBylVe z(sCacZPw3pJX2A;)<6qY+OaO33;Cc7ubM-{GQ$G1+Oj%fT_Um!Vwt@dVYX&=1wE4> zZ50I(64;Mt`~D-_wjaAdmB_Upf#omPuRWwx;_PSI2%h)za6i}sVz!NN8}jCqd!OOc z@YfrKTvs$pp*Ej02jkpIecBLKXsfR&!ls}iaEi=R&>5hdn;L6MERuew&L>5#Ql;^% zLlMCS(C@*4oxHp$WCD$pCaX+Ba|Qc&k_p4I-YRPeO_`#bfD=AfR*uKVS61FcL3 z4(N5zC-wcFE04i;>5&HTG;agXu=@U&k3MB4cpumuQTAdg3h;4;AnAg>FYrc(ktIUn>puR zjOBHFKtj{6(T^CLGhaH;NK8E+*X95mrKj;Pk;Lw5xNI_EKC#;z8 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/_json.py b/.venv/lib/python3.10/site-packages/itsdangerous/_json.py new file mode 100644 index 0000000..c70d37a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/_json.py @@ -0,0 +1,16 @@ +import json as _json +import typing as _t + + +class _CompactJSON: + """Wrapper around json module that strips whitespace.""" + + @staticmethod + def loads(payload: _t.Union[str, bytes]) -> _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.10/site-packages/itsdangerous/encoding.py b/.venv/lib/python3.10/site-packages/itsdangerous/encoding.py new file mode 100644 index 0000000..edb04d1 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/encoding.py @@ -0,0 +1,54 @@ +import base64 +import string +import struct +import typing as _t + +from .exc import BadData + +_t_str_bytes = _t.Union[str, bytes] + + +def want_bytes( + s: _t_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: _t_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: _t_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], _t.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.10/site-packages/itsdangerous/exc.py b/.venv/lib/python3.10/site-packages/itsdangerous/exc.py new file mode 100644 index 0000000..c38a6af --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/exc.py @@ -0,0 +1,107 @@ +import typing as _t +from datetime import datetime + +_t_opt_any = _t.Optional[_t.Any] +_t_opt_exc = _t.Optional[Exception] + + +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_opt_any = 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_opt_any = 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_opt_any = None, + date_signed: _t.Optional[datetime] = 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_opt_any = None, + header: _t_opt_any = None, + original_error: _t_opt_exc = None, + ): + super().__init__(message, payload) + + #: If the header is actually available but just malformed it + #: might be stored here. + self.header: _t_opt_any = header + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: _t_opt_exc = 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: _t_opt_exc = None): + super().__init__(message) + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: _t_opt_exc = original_error diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/py.typed b/.venv/lib/python3.10/site-packages/itsdangerous/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/serializer.py b/.venv/lib/python3.10/site-packages/itsdangerous/serializer.py new file mode 100644 index 0000000..9f4a84a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/serializer.py @@ -0,0 +1,295 @@ +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 + +_t_str_bytes = _t.Union[str, bytes] +_t_opt_str_bytes = _t.Optional[_t_str_bytes] +_t_kwargs = _t.Dict[str, _t.Any] +_t_opt_kwargs = _t.Optional[_t_kwargs] +_t_signer = _t.Type[Signer] +_t_fallbacks = _t.List[_t.Union[_t_kwargs, _t.Tuple[_t_signer, _t_kwargs], _t_signer]] +_t_load_unsafe = _t.Tuple[bool, _t.Any] +_t_secret_key = _t.Union[_t.Iterable[_t_str_bytes], _t_str_bytes] + + +def is_text_serializer(serializer: _t.Any) -> bool: + """Checks whether a serializer generates text or binary.""" + return isinstance(serializer.dumps({}), str) + + +class Serializer: + """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: _t.Any = json + + #: The default ``Signer`` class to instantiate when signing data. + #: The default is :class:`itsdangerous.signer.Signer`. + default_signer: _t_signer = Signer + + #: The default fallback signers to try when unsigning fails. + default_fallback_signers: _t_fallbacks = [] + + def __init__( + self, + secret_key: _t_secret_key, + salt: _t_opt_str_bytes = b"itsdangerous", + serializer: _t.Any = None, + serializer_kwargs: _t_opt_kwargs = None, + signer: _t.Optional[_t_signer] = None, + signer_kwargs: _t_opt_kwargs = None, + fallback_signers: _t.Optional[_t_fallbacks] = 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: _t.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: _t.Any = serializer + self.is_text_serializer: bool = is_text_serializer(serializer) + + if signer is None: + signer = self.default_signer + + self.signer: _t_signer = signer + self.signer_kwargs: _t_kwargs = signer_kwargs or {} + + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers or ()) + + self.fallback_signers: _t_fallbacks = fallback_signers + self.serializer_kwargs: _t_kwargs = 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: _t.Optional[_t.Any] = 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: + serializer = self.serializer + is_text = self.is_text_serializer + else: + is_text = is_text_serializer(serializer) + + try: + if is_text: + return serializer.loads(payload.decode("utf-8")) + + return serializer.loads(payload) + 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: _t_opt_str_bytes = 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: _t_opt_str_bytes = None) -> _t.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: _t_opt_str_bytes = None) -> _t_str_bytes: + """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") + + return rv + + def dump(self, obj: _t.Any, f: _t.IO, salt: _t_opt_str_bytes = 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: _t_str_bytes, salt: _t_opt_str_bytes = 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, salt: _t_opt_str_bytes = None) -> _t.Any: + """Like :meth:`loads` but loads from a file.""" + return self.loads(f.read(), salt) + + def loads_unsafe( + self, s: _t_str_bytes, salt: _t_opt_str_bytes = None + ) -> _t_load_unsafe: + """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: _t_str_bytes, + salt: _t_opt_str_bytes, + load_kwargs: _t_opt_kwargs = None, + load_payload_kwargs: _t_opt_kwargs = None, + ) -> _t_load_unsafe: + """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, salt: _t_opt_str_bytes = None) -> _t_load_unsafe: + """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.10/site-packages/itsdangerous/signer.py b/.venv/lib/python3.10/site-packages/itsdangerous/signer.py new file mode 100644 index 0000000..aa12005 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/signer.py @@ -0,0 +1,257 @@ +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 + +_t_str_bytes = _t.Union[str, bytes] +_t_opt_str_bytes = _t.Optional[_t_str_bytes] +_t_secret_key = _t.Union[_t.Iterable[_t_str_bytes], _t_str_bytes] + + +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"" + + +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(hashlib.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: _t_secret_key) -> _t.List[bytes]: + if isinstance(secret_key, (str, bytes)): + return [want_bytes(secret_key)] + + return [want_bytes(s) for s in secret_key] + + +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(hashlib.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: _t_secret_key, + salt: _t_opt_str_bytes = b"itsdangerous.Signer", + sep: _t_str_bytes = b".", + key_derivation: _t.Optional[str] = None, + digest_method: _t.Optional[_t.Any] = None, + algorithm: _t.Optional[SigningAlgorithm] = 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: _t.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: _t_opt_str_bytes = 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: _t_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: _t_str_bytes) -> bytes: + """Signs the given string.""" + value = want_bytes(value) + return value + self.sep + self.get_signature(value) + + def verify_signature(self, value: _t_str_bytes, sig: _t_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: _t_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: _t_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.10/site-packages/itsdangerous/timed.py b/.venv/lib/python3.10/site-packages/itsdangerous/timed.py new file mode 100644 index 0000000..cad8da3 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/timed.py @@ -0,0 +1,234 @@ +import time +import typing +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 Serializer +from .signer import Signer + +_t_str_bytes = _t.Union[str, bytes] +_t_opt_str_bytes = _t.Optional[_t_str_bytes] +_t_opt_int = _t.Optional[int] + +if _t.TYPE_CHECKING: + import typing_extensions as _te + + +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: _t_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. + + @typing.overload + def unsign( # type: ignore + self, + signed_value: _t_str_bytes, + max_age: _t_opt_int = None, + return_timestamp: "_te.Literal[False]" = False, + ) -> bytes: + ... + + @typing.overload + def unsign( + self, + signed_value: _t_str_bytes, + max_age: _t_opt_int = None, + return_timestamp: "_te.Literal[True]" = True, + ) -> _t.Tuple[bytes, datetime]: + ... + + def unsign( + self, + signed_value: _t_str_bytes, + max_age: _t_opt_int = None, + return_timestamp: bool = False, + ) -> _t.Union[_t.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: _t_opt_int = None + ts_dt: _t.Optional[datetime] = 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: _t_str_bytes, max_age: _t_opt_int = 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): + """Uses :class:`TimestampSigner` instead of the default + :class:`.Signer`. + """ + + default_signer: _t.Type[TimestampSigner] = TimestampSigner + + def iter_unsigners( + self, salt: _t_opt_str_bytes = None + ) -> _t.Iterator[TimestampSigner]: + return _t.cast("_t.Iterator[TimestampSigner]", super().iter_unsigners(salt)) + + # TODO: Signature is incompatible because parameters were added + # before salt. + + def loads( # type: ignore + self, + s: _t_str_bytes, + max_age: _t_opt_int = None, + return_timestamp: bool = False, + salt: _t_opt_str_bytes = 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 + self, + s: _t_str_bytes, + max_age: _t_opt_int = None, + salt: _t_opt_str_bytes = None, + ) -> _t.Tuple[bool, _t.Any]: + return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/.venv/lib/python3.10/site-packages/itsdangerous/url_safe.py b/.venv/lib/python3.10/site-packages/itsdangerous/url_safe.py new file mode 100644 index 0000000..d5a9b0c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/itsdangerous/url_safe.py @@ -0,0 +1,80 @@ +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 Serializer +from .timed import TimedSerializer + + +class URLSafeSerializerMixin(Serializer): + """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 = _CompactJSON + + def load_payload( + self, + payload: bytes, + *args: _t.Any, + serializer: _t.Optional[_t.Any] = 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): + """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): + """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.10/site-packages/jinja2/__init__.py b/.venv/lib/python3.10/site-packages/jinja2/__init__.py new file mode 100644 index 0000000..af5d428 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jinja2/__init__.py @@ -0,0 +1,37 @@ +"""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.3" diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/__init__.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33e743d95926556445b17686f623b93f5bc6dbf9 GIT binary patch literal 1602 zcmbW1O>^Tk7{{G9X%feIPm{jaZFgaMXbkL?VW8dZ49s??P?%wK@hG-Pw6!IVBxjR7 zapNoS6*%*4a^=L4D<_^uB`@p|XY!w){(2-mk{?Uf>#hUO@8MtUm$KvhfsM^)3mRX- zU;kWioY)~wT!^=lLb^q^3dq~Q+hp5v5x7W-mP<(~-61=ccYw>JY`L6N(kiK1t^m8l zwOj?Rk(y-}*dw0h8gQM|EqlNX(y&|yZjz?uM$$^#q;0tg+#wyyE#NNcT5bdPNY8Qy zc$e&2?gIBo-*OLlKn9j~f%nLs<$kiC9*_ge1K>k)Xn7C#h#Xno2RN!6Jsuz|4wmZnDDvqvs^L%er_gG4E?W-pD8)zF@sUAkmBmcyVt&+3qxnV znNZ{FJju&r6bA`{ZwNTws2vG=7H!%v4V-dujX zD2HJzqcB{QN0D7x;hm(mQHmgo+Qtg1g!T^FE}KQn7OhrrvpK4QQboZlPt{O7lsd?w zoY=RgRRgUiN(-fp(n0B>^iXy|7G?ERK&p?{0A&wlALRgKQOXTZv^qrN2;~^%1mzUP z2U*m@aLN>ZYGL@Bqb{)n yTAu`(8+MgFm5C1C;zjXU5QbcE6NbZVzNmbj+M@abzg2w=QgpncSNQ+G%GN(NXTEy? literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/_identifier.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/_identifier.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..635ee31f9a77d468e7ab4cf64052821987fa8629 GIT binary patch literal 2077 zcmYk7%Wvb>6~^V678w-Cw*Ny=+)*EkZi=FRK{xFxZ4o%Jnm8FhV0$LWj*_UySY|BR zGm>Rn5-sXQQZyxzdRU?)pzF4aEXJ8}nmJcq^=`x>yKK^rT~)yEp6{OX@!oTJC1~f} zcYhMW$Nk_xvF1CG$bC5Z|Ib5Aeh2n{ieV$NvGyeLek2yr);1not-b$XW9<)-_a6Qm zwaD+E{u&GX>Cd14ZS;4E{locZ=Bp(8D)UNZuV$|nxAEJ=t$drh&3v6_U!T9uvDekt z-Ma$2yS%HiyZT-0u6<{+JNp~;n=bp;;kQlpZTGFk-nwsRq!k!xCDJYsbkZ6KEz%4G zo32WXt}aMFWu#w`t~079sXjsQsXk}aIHrb*P^3nU8ag%OjG9Sm`qV_VB~vRytt_>2 zm?+dLQmaNSomz8h!`V(!+ov|1MuLnC8Cf#mG!!yaGP-2+$QY0brbh6NswV)2Xog{U9>cDHuWM|0Ek`1e^kX<0VNOp~Eovssf4U3Z?CykIL z=MX_5r$}9iQCFre$~~ESDEG3|L%F9=?cXr#?38C#mmKA68c;7gje*F08IX z?n`nDeI-jagW9xqw$1p@E&fyq)Cq^NK9^MGNp-6(=4N@LjD=~CGrR4kI26ve@^~_ zW<5r8ndWJlXK1cqQlvTVc<$38%_WO*Y0l#X#^WU(uOMhVUPGw!cniVi@g9Q56A8u> z3QrvK#5q)%D`m!&D!)8o{PG3A>?3%*e8S78yxiwymsdQ-tEaqL=30(%P2sf^ucdj- z;B}4hy2a~Vgeh+q8E;>3<0a!pg&U|DJ~tNJMA@A2j>LFJ<{hkN%iKo8w#%=PyiV}z zD+HT6O~xIUck7IIN8HUb?w)Y>1wxyv4C4aKlG|S#26Q%paxhOfJiMlNs873O1qA4-aOp2z< zL`xE_hG-j1w1>h-3gbu^iZG^37&BpZh1qAq^n^JQ=2)0>VJ?If7na3@QVT>Q4&mn59UZH zGRS}|$b|_76hRH>pcy7RAnZ#)7x@8%iZ;|rpq_-;Q>Gz%&#%fPwA|6%*qkP|ZUKvlOV^aJ%jh zgxhr&f!aTT=(m6o3Y5Gagcl0z;NisH4217_fEPKyy2Eg};g&6;U@!LOosV|5b~m3u?5-ai#P+t0$lj0f z-}=Ad`#(lM+1ZLkx7PPQd%7R}c=I6oY;SjK;~D!r_F?q#v)J~t=#$M4qq|=me6q9s ztH;0id31mCAjWprKl*I_zY!{YMxcMSk?~!P=uA{tHw>_aOiP literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/async_utils.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/async_utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4a452edcdde3ddf1be24d87fcd08d3eb51f260a GIT binary patch literal 2691 zcma)7&u<$=6rP#gwbyGqKb$lq4T!22>eAY6DitKEiU0+QASz8rC0EsI4)=+D_hGN zIRmm=b14z*Ajh+ZwB~V_=XOagFAAb4M#QKX6XT*JCOCae*WKDA_XKO4f-%LjGlXYX z8O(Wj+PuJvyLRoJ+(>RTm(PvyQ+%A4Kr_ufKFag3X9o9xKAo`*kH2r!U zDe+Kgx?D%Y;~xXTIvU9s2zz9ea?07RyG?ued23;4g9A1h7!xp(Utv<@fbLs|6wNv5 zkSDB16=|>zku#hst6_7d9Ei!{_OAVeM&6LtNwqw)%~VEZmHU_;6^w{P_< zo_)$dB0YxKKehJA9^GSm7WnjdeiwFtt-a6WH!9z=QRao7?ZbfM7ZLV`9wacY#Bo!*Vd4kLW>kMhr3-tX z5s3i4SgNkaEm3U+@_r|&u7#@FmF*VqUfd8X)k;@H-D)#jskS%OdK_J;T)tFILM1M? zgZlkoO(fMu7&U^qs&VaiRM<=^?M*oXt_|jxu@c>yOW$_`83vK6Tx-VlpqX5+a8ZwC zpkmoq9iQ{O|a z;%OKOo_La$E$#V!E9RZ1@O_}E9|bLx3cmlK6ExEm5*Roeu0?_yUu7nzV870G+B{H# z*I{w;L+08r-iMKV4AVaC5g-5qG88b2ocsvow++;hr+`2tBt7~Y{Rwyt#2Q$YAt$Y;A7Sx(CGH4(WI*aw$7V<2f5>a$5 zn-!?dM(7CJy8QnWdE{rQT$IRK?XJqW<;N=xiQF|=($;*mnP$mRopw`bD-lX!3be<= z)m0%yR2LGFlUT=k!tgC+vVTM;Ncm}e=bHWjAn37v_G`fcD4jkflg67@6rsj>DHP50_T_`=t-W#$>9D0 zO6H5jArFXtf{6zB&&e_f+JWxa5fX2UHwpwT|Adiz2Gb6-HDs5fU8n=a4lE9A!!l9! zfddkivqlU33ZH=hP{6-L}V5KSUF5fF>w5>MVLYJUTw_0)J zw`JH0RoE3tzxH%CjFPsfE1eIM;CMUWeI8tY_ zB~U;MQ$pe)UYu8zAEGdh?!w8ir`O_<*pc%?hw2@mI);f3Rgk12-aVad(Me=7IlE0&iOvTCZz9g z4V~f$M@whdg9Q26hYcFYWsKE^eXX~^gf8)*<_2VsJZlncV}7moO?S>=+Z z58pWcwPu(o;7t4a5;{b_vPY*0)D5N|{_%bPCg_`&sR>I~VaMxU3xk`#@B5v$Byy>2 z8$jh8ZpE^ZS5P}EFTz7-fXHFAmNugtc0vW0Wnwyz={njmcbe&7X$Q(K0r!^!X=)=a zN-K<%c2=8lpweb$B}!@=qtP}G>q?%%4}XZ$1^ldI*sF6VWn~C%V$}Axu+1EOAku!R pxYyE4={lx0!5-ogmlp8Pl#6RkUpQ;AJfrLtW8TYDa@okse*tSebshi! literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/bccache.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/bccache.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa2a497c4fa438815cb8e5f44627d4385ca835b3 GIT binary patch literal 13948 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/compiler.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/compiler.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9545108ad34e481dfa7090e5bb4166e226a0c3b GIT binary patch literal 54551 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 l6o_~{l_vXmEUr@g&@7^N0o{hZu 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 Szu`I=QNFcXy;-j7tN#FZW-y2V literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/debug.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/debug.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0fbec31f77af20c172edf6dbdaca9f8517316ef9 GIT binary patch literal 3994 zcmZ`+-ESO85ufS#*xB`Z{h8Rg12iDMEG0JNK+%OL0&?aX-$ATIu?|gUr+e*L&(3Um zdhOVnm5_YAAo0q}fwX?)ng4=6p~V|de&b$|ApELlcjFvktnRJuuCD5?uKHEESX^vb z`2HGwCO+M?tbfqp`bVqZM=Sq^j$7Q$tb_X3K42KL%o(@`u1#|eXz#!S?Q$>k2aSV< zq5UivG!L4FZh&qbv}{YT{({^AXOOiAiwBEXy~&%H?TDpY7H^5=p34__`xEbAg)fR_ z-Z5())|SK)Ulyz2@p>)3!dE|W57zh^*4M=n`WroFB(VO?*JDUq=QqH)!R^P^*2Wd? zW9@C(I(SrYv41ucpcnULoQQ6m9Mi;=4HnFWga zn>fm?*d-e?Lwl72+EISRRO5olyA|sP-#;?VxOqB@LkqDEKlpsKMy5H)Tt@w@ z+bzShf0UNtU{tEGi?hZVX`5<~^YHoe`qwi_MGh?B;=O2Cve+tm{G z_s*LSM!AvsP_IT&Kh67bG`o2eZEb3&JS%kosZpBu3T-RxCUL3s;t%6e?9LuZI&f^= zN)Z#Kit|KB@^;;V!n~w-;*vr@cj!>j{202^i;u;%anQs2<#-3}XK60-LN`=5$|<}8 z5IvX?OFa{Y(kF?{UUZlh-8d_?b10PFM2BTKQ8_Gfju?%ml9~`OCH;6f6gk&{6emKK zf^RkJ^VyMZ(p^vDY$P;OUG3pM$uYD~T}s|0t&RHJUAckLUo81`{QPTg=cpKnok1** zN9E38s&-D~aKKOQoQm$w_KC<(cCxg)GdxpAMgHFQx4*Sh!t3u0AwND8<&Lrb-5oBv zqr>gtnck=$?wWlfbC?d4mG{wg7TR{(US_`S+bxGV%eMc@_gogZZO6Bn-C+U4I(S;l zXTd++RhkDcli$R4`DN<9LfsAO=w^wFZuZfWEu$IKx`{xoY;FTbRurhd-Dejzu*IDK zUATS8fCnrkv;h`X$Ps^X#-4IHp^vv|ty|pR0CMrhg){bf034~M?HXBL-ya86z?;WR z-s7!tBkxqfq`?<1ZMnfwqZu>tbo_pEuPzm0tnZE*#r>iY)lpaxL}l z+3#(O{!}pe!llKRZ(02>`qne+v2|)~t;DyPWql+IJ|d6`b8-4Q)WV|M7l}e7PEn_< zVJB6zGnww^5M`q-l#4?S$nJDXh0KDq}J=+P4HTmyNteXeX|Ai+U z01~CRBjXeiNC!%!08|*=gmt9t4O32WuSQeV{ha7Is*ot4fZ1keRY}+{+ceQ8)J1Nub4p{H-X*Eh3s4-(!=xDHO0QsWd|Kq$*?g)+2dnk#HfRHh zWqK}jfKe}t4@+}+dR^Vb6#TPP$YHb(rY(&Ic*N_$>{)e(B&4!b(>y`jv%FAo*KF!Z zA+WKQkccd!fxJWaB$$+o)KNx2I(ZAWBBxPo;drx*<(fkVG)+MYQ;zb4D3eg??i(a@ z9o;X`%6)XfQrqd+E@KV@$ov0h{;KW1a{Yj{>;TE2Wv>F_J2qpk{l91Z2EBj)%%-pTM*T|v8&Ebdnc(jrDr*94M0IEb#i_Pju57AkC+yN1Gm{4>7dYT^ zE-lo6?|;n3F6v8n;&RlB@@ti+yb&_zi_P;T%=+}7#3e&T?2j8`S2d~zvPrt)hJ^&xMYTY+TH=0lNt6rJ*sViY!WC1%XZ?J)=io9$K7=`-{j?Zm9FS(< zB|eGMjIcAridn8v_j8y~g8{j#fzUn8vPgz7ulx?WE&J*fK8eI@ZMEdP_<`#n3{iHX z3M)_|cqkwSrF@^ZG-%x`hgqt$1BlnHCsf6l|6%04TE>UO<0R^(c6qE~y=1Nw6^KWf za>Ry9QK3Ck|Cp2LCI>tnAOhuoh@YKPB0djvP;H0?xZFGSZn9H_t&9?2Mf5%}D5wEWT OH2O7-wf?jHv;P8`DR%k* literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/defaults.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/defaults.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff6d1daf9002208396145550809dc5c6e57c54d9 GIT binary patch literal 1338 zcmY*Z%W~T`6eTH%dRuSDPEt3mpjZSw#i2hKgn#mCObzn@zM~wvcRYg7O~T+LrJ(syu@z%=>Fh6_}d& z0Qy5zH@`p)P&H$22Y-nl;R4R%A}*oUd)533ZK8WfhPDNL8*Mr=s-gSubLQ9JaTjla zeSEIOJ3SCPO{Dh2TR6Qmyp_SWWu86i4-9=g0hlrLi6Ma6TTWd}05xaW$HZpXasz@r z%L(bi6N;CC0}FuiL)*hNw5K>y-t9%o-VKcJBIQPmyOFYc!&`&?P`4&V*U(S&p<#{2 z`ceNE-iYbm>B$;-#N|S?!>~4R80_o*w*SW8|K`#D8BBvymx{2&O$;chdK2%e__Vb&#H(snMYPXjM> zAOo6Br;cM$Mxw%kxK4yMg59XR!ptT!%%bLMivM85w&?T%Lq?(sBMW~DsncAHukB^j znA5=5(83F;bq-6+3H+$GMqXZnKN?lRkLEo6-q#p$JP#vYJ=Bl7X9LLG>7d{1>y!2# zSJ^Uj{27-S&z?IjWQ&rNI7uZDuP&Bn7^aL8co7mWCyVh_^UQ)dE+rxZL=`40OfFU$ zzm9aP_mkc`?hjw^+TC^*#D;wekyEZP%;yLr&X(;k&yF3NA#4DC%`+mS|K~l>i;*Y?K5ZH+o zhc)5lfrxXonv#+bw2pOsWEtabAL{CbwW=>thBdMw1hph@!|sVb8FhO)*%W;GP}Ezh z>o5P5$bpax^YK;ZBJgm>v&rRxc4iLiT#?X2S5L0-+m3dH{i}}ayzPWbb`kjBX-^M2 z6zcs6yrN5chG}Q+_;dT)4#Ma5!evwompu2(3(&&FKZtirUxFz}C8Z=MO;vJoI+d1_ aR+sBBE`e1tikvj{qf$(;BCEjfeE1J&Kz|tk literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/environment.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/environment.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd2407eac838cd5ddbcbac460e112abc03524f96 GIT binary patch literal 53388 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 %R%?#!yA!4T&wf7I0{Cy_zhI_w> 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/ext.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/ext.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bb2f263035bc8c6ac47de4f4e7a5891b44296bf GIT binary patch literal 25843 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

4Hgc^B3OxQ+tUIs~Zq6HZ_epTlFtI0Bu( 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 CorOFA literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/loaders.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/loaders.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0bedcf5df2ac991f48cfea131b34f4ab66906740 GIT binary patch literal 20495 zcmb_^TW}=TdEWG8t{7kkm%VaHww5#jBujvo*r6bDwW}ppT4@Qb$(3k9QVj;v4Pa&m z)3c|0b{C_8B5Rp&SruEcEmu;dq7A5gqa9buPEv8=ijzDfdB{tu@|3Q;$x05Ne_H>a-m`1D+<)iA=qHbh%Q%7? zMlR>()^e`lnjK@!lwWJjl3#nxmf!qZUVaN}MfokQmE^a)R>rT@sq9RwO&F}h?o@Xs z*Cr*M@0dGNYg3XgbWZHl)@n!>-BM?IXJ&0i(&f(V&fMCZk@Je}lj;}ow9+}Xb9(Kx zJe@%L%-R{GtKM065_!&fXV2y~ZFkB&@wUD8*ynR@&7FQb=T1K`*UsZ=#+}90tatu_ zwe~o!=iHOHJ}K8v;QEw%8rP@g`bk`$anIuVtXw;|KIcA$>&N8!Q@B3wK91|h<@y4y zpKzbV^^;x=^*@Dc$NdzpKPAtfcFi|)ix&o8x^nZn)9AWRYp2)ocD!!b2wQ$Pa5jDA zbo_?f>TWrqhlh>O!(HX?IBsim(^JUmxQ(z;3H-ildcjiVM_jbkMI*8r8%_M!!FJ<$ z{7#~7UxoD@-|cri+^D=Rsav}}??+hD9B$Qa#cizm;WfYCb#brS>V}@`Habn;WwD9Z zx_4X3@3NP;EG0#vQqsYwpuDiJx=q%ad@Lkv99MA!8#ry{_Kaa}A0%*Kyqf#w{GJ&a zZL@6+&AYkaNlDx4tp3&ahB`<7wyB;93&Y$4ui zyA+vz5ZUZiWCdO?Dl|Hw{Pr5kZ7Eg64B=+4=V1{nH6fS1mWL&d^78wBPMyKszrMM= z?eBQYI}LTaA1rUR!sWZFx8vS@_MW$~ymZ&=-d*mrHkNz4;kMs>aq0QzmV;L4J=<$E zZ#TBQV7cAuwi_=jlgd05EcJGyS?OUtS$=o>3oBa*_DBNyo3i9t_ zkz20ktZ#W?UGKtmC-h~})9noMX!e5;+cw$FJ6>}eBp2*}*lvNOuujRYa(c?Yiz?B8 z)FL$}tFi9vcvwjnbl3=;Cb}00N$Nh%2hKWESuWo}znDX+T9Mwbq@=p;_#17I_)#!Jg5=Rfo`?q`?mw9-y2~`zTOy{t&VOe*bUHQr|I`QF3S41 zolfhvhvKbZWkol}O(mR6Qy_UC_>+^Z#zp7wj*?EM<$O@9Y-?Sx?YFuY(d$+a1{XQ% zov^jzWo_w&dwutYEcHUx&f-XiSh?$MI`w)B{GeW62)xebMcMGk#;2nnKGc19MY3d# zF&FE}h$60OWSuXj^LI?uGO|}34oXT&Gb1IA^rf}wbp0?M{{o92Q!Bfr`PJd6T}TLQ z@kq@wkIpOUl?|6C*RM%3wRfJQX=n6T3V8FwNsCj^F}L!(2NTOom2iQna+KA3!v{ zXHv+7_E3Ho&Bi}Lk)ZMQLa30L}%OUK*+?KD4Am|5;zstLu}a| zn2pCBJ)pn@LX5>Tq&Wm@3j5rwv49exw!XfgXZoU(^z0&bZRi6qc#G@U z`zjG$>0+jw;gAq>Kwc1t%|>@V#C~p~2I+6oznForBjjfB3PYHMj=w26b%!}j>F5sF zp|hbYiF50WX;+e}Nl1{-p#lh6lG>BeIKj5?m$(|4qC=H1t24r!V!otDa}PBO-*h!2 z!U8DoqT}=T9)x<@mG$*izw529A8H;VpwETd*mZ7-c$H=5GKQ+r^fn-3HFn^%$o@>& zsCPf~x&a`b6W4KQ{vdur%r`h_yrA*wYF@vdEaJMe+3z+96*XjO^kc!p1~mZ^Iid~F z3ZZ`gpgzsE39f|JtIMIyAOsl3hBeU9BzBCe7LSGWCEGY0MJ8GI0ZjP%Vx zf%Rk)w9ya85jvDC^ry3%@rl*Nl6ndh5KV3DLhXaLTbG&B8+fDNyzPaN&HGWY>F@L) zS)xh+&>ugVO6I*TNHZ!E+}1^Fu4s}L7BP<|)B;a`lZ_QL`-w`4P>V_lcaN-%W-}`2 z>JRS+o0HZ?4S|D`Jy|krW5zDnC8K5(j1si8nS24dS;54UM}rfidjuulH&z#C6pKcc zdTbM@*Q08^ey88)X#N%z>vh*}g3&$Bd=^A-WQ0-v76o`z`f`uU+2};2tC($ym&o4m z{f?eQ`v&%_dIkj*IaW0FdOu{I*P+vbCL-%fcUS#9A7|_`-R;d@y&;ESP!wr?~rpX_-Hpv(2BH`PxsUWD|wPK2)DC;|RFJN7c}>S+-yS zvOT*E^%K^j5>n;tDpNn9s1~4jR;YwRiKN<@hblVZR;g^dMU<(ch5~*k6U8-FTeanB zO7fiW3Zk~s24%0++!A*9Y*f1jVtP|lCQa;(^OoN8>1K|tJ`LD?NVq=Kv;^xB;%HnG zqljBz0-`^F^Acl0Cc>U{7pxZoVk7W7{m@%--bn5;D|icpahfrP5fmNGz7i`_vYFHN zLr_oh1^j(Z* zL~1vESPNUQ6>^Me`T1 zE8PS~_wPY;+zwWpYjOc9+}ZFuupP+lgg`mIY?dK22z+Bu34(cH>7`T>Tyb3@QjBDM zeWU^CDl%a($0g>pd_UZL_N8m&z+8Q{5tWirMH3^1MfF=9llnve*kD@fzl=l($xBn? z15-^%+Cpk-XlxmK2JO~wI_f1tpj;OF1a0Kt0k-79-Wb{UuqQ;OflO`y2F8w*H zWgDk*gJ%!#sinkjvGg*Pv`%mdiKOIWF{-ozkV@F-Ha*2UqLRQz@MX1vOZ6I0*LeCo zPK&mdTjO^R_YHVh+e-cvMFicRDin+wY=jkKaP~ucr~z}TppWV1lo&j?M#1mlgf)Q% zPBhl0v3PdR4rwa3w~V3nL*tFyujby(h2Y`)g@?HV*dmQwH-D!X!W=C6d+8yydw3px z#r$4%FF(xhR}OM}g|~7pY|?h_frb2~=X1f&-vb8Y_iH$$z6sX%E+`**7713EtT;gDu=1PeF~${_}`Z?gD9T z#XX@ui&IqU!tTx*fVwX5Zl*tR&**lH&8S5FMti-CLl5gK%phZX3aNjCBcS!UWL3-= zt7_U9UCFAM732J)sx@cM6bFwTA;WB}W1E-sNZb2WR{BGn!rTLKR0!Q&gOfsB6rd&` z{9iFakrwFj)6flUY6rstuAbj3A{S^8D86`LYASSde;20g{Su$Ff%W$*I^{yM5N#so zTFl|vaBp0JreNt3d^R-h8tRMCB_@U?ac`WxGjpd9R)q<#rGBMUYwI3-|S>8TmsC@K$rrlto6lIs$ms?c*6%d$#Q zev@t?y*edUSBF@NiZ}^17aHzLD~E0VZJu7@>C-%Y2B#?hl`h1NW^*zd zrJJC>8?Z`8r8m7heaH?^NK?JRGL#DH5>KQtb(tqYv&X?zQp-QY5&R9D2v^O=O~d}_ zg&3Tg0!}MGF((rUi;;eC=5fVxO&nvN)Ms)Rw~v6;S%Os;J`=)87eEwXwBk+xjOGbN z-6`IM=L1ji)n1Tt0!UL&3Vk5-q%ddIvjvh)yEF8pxMh&kTr_!8JBVUD+JVSqGD8>| zC>+A0jl>WZyO(0IA47)trkGDwoa@?bPf|&2gmDG{0QxpYfK3Vz5`dEe!B~Mi)B=fd z#d$S_%Ct?#a9O(SmkAQ2w7%Y>PY!S=1$$D@NcWLN`Qozaw~%jqorP|y=8A}OYG3dj2VLY(cjte zyNjZD#P%o}898UMHI-g*m_->US^k_rCRMO?mNsEV%j?tXw19$Gg%p^9=#Ke`E z8sg52YdtocXw(dAs7A%HuA;yWKsqC<2;B%RB(*11({#Dg^Li`mf9r+k*2P2*7}uoo zrJbuX8tMK~x@Cp1p2CLVxY0FF7t~7LIS%zJ zxI;8fRvUC+NzK7sAC2j#`0s>LFyNbKE+|8qw zDHmY1e!>Mn4Qs=EINhFsG7=8+?OEOr=faaiyM5{b+5pfXhCDrF+=DqXoYE)c}a;lE0A3S>nz7Eatxr-h8UTCQk zJi%QqT3@`#OM`is0w8Wcf*+I7CchY5O}1Q`J>yi^Q4QSIYO`~5l=C^jGEhg!x`L&} zCo>qUzJWd?j%5TE6<`Pf$5RSV)E%CL;;2eSWj!*)Swwa}Y;_2Nx^A5VjS6}kFs8+c zQk@DbOd9H@lm&0p#iNNd=>b#4xnRPEwt;m3gTG; zZ1YuX3&8v&n;<+RLy7XO0LiHG)kdf9X`jYailXYu_rt~5R4D_Lp>mXPabPHFm&wUw zV@m$0(7V0GI`b@zkQV+N(hvnuoxs)$zJLl&6{=RjI8QAEDk4plRWVu8Y*~O2vkHUd zlyT0m%>s;=6>|RUWXpSZeeji;~klux zb3A>InGH`5?N@n+;}fOeiyRnrfLumAWBcTK3+E`^U+vh^kByAy}TKJZbmhidr->}|=w`$LZr6U$i`+3kc6ams2 zbjQ*=xlL`$f>@v}OEk%u?ln+Uu3dpxGJ}O|AVjZ^ew=`(Ea_oQKXD5OI&JfA**?M1@( zipSg4Uc{V;qV>zPtJP>%({>a{+EfO*xdZd7sOXMKD+=^Os>Z8}`4Nf|I&yJa)Lvw{ z!Sp;%a6z`1&d9m^@|FiS+*6l!x#;8}2ztwz=9x#8M}y_@g&o&TGs;fuhzfN9aD!{N z=%NDGPefztpoK@3mRg$R1&g`_tPO#^FbA`R5$)thkMNNZ!lxtqVT0X&hbOAKs(}*( zk(OrDyhBZ2eV4b3@On4GP{}S)PxJn7^1glB+YMk|#fAw3Dj*_D6ekSg07ij$*U(-N zzzrNg=4@`#;Lv6rx0$cd69=A5s-Df?;4|4l+&Dc>CbyXlMqe>cnWwO0Oz6hu2h}2U zW$dc+MH;JM1+Z)8Ir9m`8kQgm2IoI&%CVL`w(}}Zuv`rHNDnn^T;b9F&BR|FgE~+>REy1iN0471p>~L1 zpk^0`;$6CQDZziQK#foOw(zZa;41I_(ssDhnO||{@D zAirf$?^}A5+{z;cKS2Vemv!9UrQhXd=TK|8!TiWjj{^Zo8BE_k>!d(bpW;cT?{}C= zP9iHfl|Tx+nxjxxLBCuKsvjhepCDWKh)#>ev|c*MyxafqR@ zq?qT(LQ^DO#u5A@oQ`8STLu^gJ=IKYz%u2#Oa^s;y^iF%GLG31>LJ?4N@<}M`vQj zIMx(zKrGEC59N1^O^>hA!dUY$YrciKNrM+TymhgHWowqKCR~>it+**%99$b?Vb(Z| zQ5rwGChNCU-$Rw-af~bn*@A!|My&g^9U}SxE^FoNAVN{=Dvvrp`c4Ewu$>4xLMv|xlY(>p~4D|;{C-Q^o!yJhG z;xD-Iu^)1kiNWdd75GFlgv_4u<0_7TGDPCt!0f5fipGJ6=vdn|hgL|x_-Q_I@lwW{ zxgm~3LzFHGqrQoHgry}8WGa~=7od>dJv@x3@bEuz7&P8htP+$cfI;a0a2}6s{E_g; z#mQq)onSdZaDwjy&=E~(d?yT5m@Jzd=|;xXe;*J2G5c~633231+hTdJjRk?BgrbNz zs#N|ebLKp4PJN(QvWa8t!x3G^5&UPIMmcQRbWaN$lc*!%m~hq*)Wxs4m#c2?9I$1;_(mhHYWw)tNX3$vaUl;0-o9ifX8RI?j(YQq#Hw zdNBj1(yTitugT0vA7*3Nc+x!u*f{4Fz?siR)zJXG#uFdOmtA5;MD}niz~%<_%5`T1G9?j|5i^0+C1GW6^^`kkjadEPP9vCkN$c z9(ehAfL4CSw3mhXo!y=`OD;*C#fwJ@zVHbOzA&FfLZ)DNS7w)eUSF3UERP^)So1k% zik>tA-eDI~b1G(A#^&lSVX}CcRrkWjR)?3V{B9hMEjp^kj^%WoW0q)PizFYW$<(gm z5E!b#wV2w0XA_O5a3H^R*@LY!b~A(5$`UV-!S(W1^|P}5F3srI|lD=!gR)Hj?msTcb|drE-%JA z*vSz@lo#V&{@ZyP?-1Xi*u-K%oxqQh&hInz_i&0zU-EW!kOx^SGRZL6N%dPi&GWR& z)35V14pMdKswU3AK-+p$?2sJR%v$wz|xx!7-M)F}F(q;b~E=GolSP$4~Z5bva!49lAc*opzQai04 z=$M^$Y@ibRDgzz0KFaWOCcx-%JXi`f%yKqftz`|#tF_jlS8LhE3~NWc zoDM8O;0iFqTvQ#6-EaIMCP<8+n&rqV19Y^@yP}ZBqienHwE5DQ=m=du!vi8L>7Z(D zw&XRX>rfjq9ZbK2N?+p!qcH$5DD&xLkK3dOq>qjFq%H_OxZC*-kz9^xIitN___{n# z^r>qQqoYCG3-il#PcMi5GE7b?3j>~y1^g!{sN=dvi>6H`vBWZc=yGhzaQpx-bcDgpCoE)9tOe%{MI6hdEOq)-Hk-dZj7!(~5b9>gH9LpkjvEKrsFm#Ni zxr;xG;P-2}JJ!7%UicJaSi+vAlTWdy!k*(G*h6wC+wn38W?v+`qV%ai`jBD4VfmDVA-=CZL(kB#k!kg-sdLy@(iSQ`tcEW>q#2-qRKHV0amAf#3YH74R@9c2_3Br5cK z)Z8_{-Nc;)@@+AT$dN;9Le6}J{U-0$QHHP$J~rOtG4Y{Wo%?XP(Pdki$Pfu4a^wGx z$oLafe}+9y)Xy`MnJG_1MCDi!F{xOxiDT>o-kQ6NLtx*yhyW|Lq7(I7aRi$FE0Dpb z84l?nj0my0jSkEs{HqYK3jWgtOk1OIPxrjWZ5W1xP2g?HRjB$7nmX)f$(BS?vRD2Y z@_m7$4&Cc^md5>S~DDM{~# zS4FgA5&n@P?#aJK;6ETH$L``~p0^Q)vo-}aIS-MCXi6!Af01a{a7?4Ue0wHVlWn&K zHJQSV|0Xf(=Cyd!Q+Y$Q+{P~)5^vlf;KOO$pYYor?2r0=vXSu0SoXXY{|Q4sKw#i; z&XG}SJ|vGudom)6lD0;Liq`HvfjmmP9_yMck_w`9Sh0#dIxr!i*q-)U_ForEac@#X zWw5SA%{3jOOq8=arjA*-Q^3LBfcw#f1DJ2@yXFt<_e{J80GEaM$H83SU$$wn0*g1o zJW}W4cRCoupS;sy)(c^AzcfUAKRo1gtd$V8U2az%=3a(39l=a^3jpV864G?GuK%(k zd2cSAlzL>`9|PH-^7LI0^#xpL-g=#>FQu2+)>y^8Efi8;Mq;oyx`L@J9C0Yq)4&P5 zG}b7$J-5~@4v|NRgPczBM0d6j91j0(QSb2}vU+|GFE9KHl!5zO!hf=E{Vwjdxnnt= zDY$Pwwqx>F4VMstZnj+6-V*F2@0_S#L?r^g`6@LL5?(wklAnN`;LmN8e}7l~8T0&0 zoT7s6p>!!>`O|!0;enpcKWAoPEpH(8b#` zGKs0=qGv^u**?hZ06ILCqSHVVaG*u`5dV`>*WPAJkuIZx1POaldE2}1wh+=AVp2uQ z%A}?<8`TI068fpr<(^FQDRc1nSYHq4JknjZd=*E$=Fm5X|4_|{I?Hq*gr=O z^&fcp_dFfy&n#QfGcGX-bP(K2x-?}DoFiR2lsPjR=$BlN=+zX)sb2kkTqJrm^h-G4 z_^%s7`vAV~6o#i$aoM}KBe0Z70-hG%XW4{W~2BT-WM-4~&K7sb#b zaa_Zq7+Q+oF4E8v;_c4;GD{wqh%kW-8}T$(v^tDk3@c_i=); zS>}tI0&K*AH(CA={+)?`Gi{uMH-C6=g>9r_ zoHsZS&J}fLyK0&js54VPJ~L;S7LTJK2ygz9uor($-uQ^7(tyk*#$&3xY*l*w7E^zQ zQ&hmeIlz#q$MzSzJ>>0)kyq9AJ93PW*+y)qY;8r(iY<@-LJbRY^t zgjW;cOVY1BPu}|4&DZKzzwp}CFI`{#{K)3u7SNMwFX_tJ#5eqn~#u;mBy4J0|mHRuj`P!M< Mv$fCGo}07(4~4=lS^xk5 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/meta.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/meta.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b8a93529a21ef0d0cb93c9aaa1bb5940e8439f6 GIT binary patch literal 3818 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 GfAnvMfb;JF literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/nodes.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/nodes.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3806996032850f87e3cc8579ff44d007ce2cf3f8 GIT binary patch literal 40304 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/optimizer.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/optimizer.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9c22de4a1823a7b109e86e28972ab592086ab44 GIT binary patch literal 1958 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/runtime.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/runtime.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad001129cf22e4481db70bbf25a04360fb7bd33e GIT binary patch literal 32147 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/sandbox.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/sandbox.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15f4c4f68197f2cc704aa601f448bb98589c28eb GIT binary patch literal 11970 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 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/tests.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/tests.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2776e36f27cd1ab6b82c75f066e34676249ea020 GIT binary patch literal 6692 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 ZN#{0>R^1-Q#a|qr`u^zD=;Py~{|{{7>7oDt literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/jinja2/__pycache__/visitor.cpython-310.pyc b/.venv/lib/python3.10/site-packages/jinja2/__pycache__/visitor.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dde3f8d513c51db34cb05b3d3b0a12c81c807c23 GIT binary patch literal 3977 zcma)9U2o%98MYlecHNJi4y)PDXlHeRm1Y8L1IykZEoiD?Sw^62HLV5_c5&RClf`~%-|wRdpK4LtAbq)FNt2}^!spL6`4_w#v9^3BcA z!u7Z4-|AnRmi141S-xDnJi=|-5YlQ}(w0tYw;frNZdx0KeePM z>%X&PUHQksWv#u25nl!v2`-&>h_^Kv;w@AmX4j>2U^Uh!&-V78h+eKmq2p7fO_KFR zF;HUf;80|_RAyH^8IDplR9T^uHK_!aE7 zT3^|a4ZCz((A1@&FCcFt|rr4O@%a`RbY zlHzfkrtwj#N|#J6-B|ZcSwA_eezhvbI_o;nKEEigWYcH34ZTR~!1~f|eQ7n^(lsjW zX%C~iPQoWad1CRO{pKJas^&1(Cu7s>Cq?sAkB0K}gEMv1+&xvE(wwIl2l-805l`piHCfC<-a|{COeVa$# zoS`GEU1X@u8KP3`xwE`@lr!n8`Y}q5WsM~AMn&hggE!8v%MHx0$xY;St6Zl_;Rxh9 zzK@XnB2G^X*IayLP@~;KnDeZNU!Y)>qWTjQLoo}h=#4WjLBmC@P}1k2z(oaup>Za6 zg*Zfk-~3=0pNpzy#A%$4l@Vuyq&pC23G^Q+R)bDKb;(61bXZSEpa}-K+zolvJ~~6H zUOY|qGTNw?agbEOc5 zjt#6zGE=A+fu^KZ%}O{jxm)ahHX`ha(_cMX#)dCe0Dzi|I{Yzivjb6BQ-Et>Pwh+l z*!iRNCr3J$HPm8l^4F&fAg|3}1(^d_#f63FRZfUxISgzh8M+jOV*U}uEQ9j6K;(_$ zZD!6_USCC5B<4!f%^;BevR_y$aVAqG^JHa(yYG z?_z*)Xvdqp(^_=m?$VkCHm(Ggf=Z~u$odEmQ|qNQwO`p6?$nj`*w$}P-KpKTr_P`4 zr&eN3Yk#r-U>{)JF@k?{yx~kLkVmO=*|*@uJ5XG1u9Qf_Tk`D+w@bUXfbPmsk3;lL zXfRYUp%XZF>>X#az3eEjx#1W&$Bumq4^#W4^~(CO^~DxkBjerc#@p6&xQrTdCO;sG zqO#?(P%lPl(oKr1s-C0Oa)B(|EpLH9bkrRrsf;KFM&E-0Z}2!=th?sAra~u@H58u> z=br8UcXD^x?UjhO8X;GWehaJhEr`;OBAIuii0Os1ptouAHVLwcw^-Vii;St}YnUY+ zhK2$#-0gMYzrUtwyo-C~TEp8T+~z67O~O&$ab3DBJ>`O2a2x=6_)IRfm09mNQ0`p| zYd}FvFd-7MUcNGRfjML z6G&G|D?P+ybNaZh6u>gaE&7annX}z&gNi?TIv?^@BdtIcVadErliHD4U#gU;!#5R&G}c}Vt{&?y*HC#8AC<~5Q)ktqDZOeapdl)$C0JlY zAT;_RZu1c0mL1xz9YF3tI`|DCH|(w1$cDY)IKRcY`2MxV0w*mU6joBa!bOC82rJTj zBdip7mr`xOO?~1b7Z_nrezS*eTR;T5esMCS2pXJ1gu$PIs_^J|ibkqVfLx(O$+OcG z^EFymWxyM>ZY)THh^bZR?@84GRqfJejar4L0%q&4L%ad)9esK&u4TyW9g+S6e8?=f z)~50zKQqxKJ8v3v4D9>Tj~CsDu`mbwEF_=-^0X*xOr~^`}e|!cQlPQ zHdtv{$Dsu0N!D9>R33&mDmM>*x&KM@_@|#d{@Ih(r{#9FF5(I`gtnzqs502sd69SX pl>e|WiLm 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 + 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.10/site-packages/jinja2/bccache.py b/.venv/lib/python3.10/site-packages/jinja2/bccache.py new file mode 100644 index 0000000..d0ddf56 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jinja2/bccache.py @@ -0,0 +1,406 @@ +"""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.10/site-packages/jinja2/compiler.py b/.venv/lib/python3.10/site-packages/jinja2/compiler.py new file mode 100644 index 0000000..ff95c80 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jinja2/compiler.py @@ -0,0 +1,1956 @@ +"""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: + 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 exported, async_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.10/site-packages/jinja2/constants.py b/.venv/lib/python3.10/site-packages/jinja2/constants.py new file mode 100644 index 0000000..41a1c23 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/jinja2/debug.py b/.venv/lib/python3.10/site-packages/jinja2/debug.py new file mode 100644 index 0000000..7ed7e92 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/jinja2/defaults.py b/.venv/lib/python3.10/site-packages/jinja2/defaults.py new file mode 100644 index 0000000..638cad3 --- /dev/null +++ b/.venv/lib/python3.10/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.10/site-packages/jinja2/environment.py b/.venv/lib/python3.10/site-packages/jinja2/environment.py new file mode 100644 index 0000000..185d332 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jinja2/environment.py @@ -0,0 +1,1667 @@ +"""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 +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS +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, 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.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: + 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) # type: ignore + + 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 = "