From 5c9893a7116b6772eb013649615ecc12d2cef652 Mon Sep 17 00:00:00 2001 From: Girish Sirpali Date: Fri, 3 Jan 2025 16:35:28 +1000 Subject: [PATCH 1/5] Updated the folder with the latest changes --- static/css/Homepage.css | 1 - 1 file changed, 1 deletion(-) diff --git a/static/css/Homepage.css b/static/css/Homepage.css index 3caaa9c9..3eafa004 100644 --- a/static/css/Homepage.css +++ b/static/css/Homepage.css @@ -1,4 +1,3 @@ - /* ----------------- */ /* Main Section */ /* ----------------- */ From bb652bcb1b4abf91499adcbbc61e431741355d4d Mon Sep 17 00:00:00 2001 From: Girish Sirpali Date: Sun, 6 Apr 2025 09:09:37 +0530 Subject: [PATCH 2/5] UI Design --- static/css/Homepage.css | 1 - static/css/about.css | 1 - 2 files changed, 2 deletions(-) diff --git a/static/css/Homepage.css b/static/css/Homepage.css index 3caaa9c9..3eafa004 100644 --- a/static/css/Homepage.css +++ b/static/css/Homepage.css @@ -1,4 +1,3 @@ - /* ----------------- */ /* Main Section */ /* ----------------- */ diff --git a/static/css/about.css b/static/css/about.css index e6a67d54..db07cc2b 100644 --- a/static/css/about.css +++ b/static/css/about.css @@ -1,4 +1,3 @@ - header + .about-us { margin-top: 100px; /* Adds space between the header and the info section */ } From 44286ce07b65843ebbb42ea3dbc86f58910f4e79 Mon Sep 17 00:00:00 2001 From: Girish Sirpali Date: Sun, 6 Apr 2025 09:38:14 +0530 Subject: [PATCH 3/5] Add my website files --- .../MarkupSafe-3.0.2.dist-info/INSTALLER | 1 + .../MarkupSafe-3.0.2.dist-info/LICENSE.txt | 28 + .../MarkupSafe-3.0.2.dist-info/METADATA | 92 + .../MarkupSafe-3.0.2.dist-info/RECORD | 14 + .../MarkupSafe-3.0.2.dist-info/WHEEL | 5 + .../MarkupSafe-3.0.2.dist-info/top_level.txt | 1 + .../site-packages/_distutils_hack/__init__.py | 128 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 5094 bytes .../__pycache__/override.cpython-39.pyc | Bin 0 -> 225 bytes .../site-packages/_distutils_hack/override.py | 1 + .../blinker-1.9.0.dist-info/INSTALLER | 1 + .../blinker-1.9.0.dist-info/LICENSE.txt | 20 + .../blinker-1.9.0.dist-info/METADATA | 60 + .../blinker-1.9.0.dist-info/RECORD | 12 + .../blinker-1.9.0.dist-info/WHEEL | 4 + .../Lib/site-packages/blinker/__init__.py | 17 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 464 bytes .../__pycache__/_utilities.cpython-39.pyc | Bin 0 -> 2093 bytes .../blinker/__pycache__/base.cpython-39.pyc | Bin 0 -> 17245 bytes .../Lib/site-packages/blinker/_utilities.py | 64 + UIKatabatic/Lib/site-packages/blinker/base.py | 512 + .../Lib/site-packages/blinker/py.typed | 0 .../click-8.1.8.dist-info/INSTALLER | 1 + .../click-8.1.8.dist-info/LICENSE.txt | 28 + .../click-8.1.8.dist-info/METADATA | 74 + .../click-8.1.8.dist-info/RECORD | 38 + .../site-packages/click-8.1.8.dist-info/WHEEL | 4 + .../Lib/site-packages/click/__init__.py | 75 + .../click/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2641 bytes .../click/__pycache__/_compat.cpython-39.pyc | Bin 0 -> 15983 bytes .../__pycache__/_termui_impl.cpython-39.pyc | Bin 0 -> 16454 bytes .../__pycache__/_textwrap.cpython-39.pyc | Bin 0 -> 1524 bytes .../__pycache__/_winconsole.cpython-39.pyc | Bin 0 -> 7775 bytes .../click/__pycache__/core.cpython-39.pyc | Bin 0 -> 90922 bytes .../__pycache__/decorators.cpython-39.pyc | Bin 0 -> 17504 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 10282 bytes .../__pycache__/formatting.cpython-39.pyc | Bin 0 -> 9403 bytes .../click/__pycache__/globals.cpython-39.pyc | Bin 0 -> 2415 bytes .../click/__pycache__/parser.cpython-39.pyc | Bin 0 -> 13560 bytes .../shell_completion.cpython-39.pyc | Bin 0 -> 17071 bytes .../click/__pycache__/termui.cpython-39.pyc | Bin 0 -> 25860 bytes .../click/__pycache__/testing.cpython-39.pyc | Bin 0 -> 15228 bytes .../click/__pycache__/types.cpython-39.pyc | Bin 0 -> 33441 bytes .../click/__pycache__/utils.cpython-39.pyc | Bin 0 -> 18778 bytes .../Lib/site-packages/click/_compat.py | 623 + .../Lib/site-packages/click/_termui_impl.py | 788 + .../Lib/site-packages/click/_textwrap.py | 49 + .../Lib/site-packages/click/_winconsole.py | 279 + UIKatabatic/Lib/site-packages/click/core.py | 3047 ++++ .../Lib/site-packages/click/decorators.py | 562 + .../Lib/site-packages/click/exceptions.py | 296 + .../Lib/site-packages/click/formatting.py | 301 + .../Lib/site-packages/click/globals.py | 67 + UIKatabatic/Lib/site-packages/click/parser.py | 531 + UIKatabatic/Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 603 + UIKatabatic/Lib/site-packages/click/termui.py | 784 + .../Lib/site-packages/click/testing.py | 483 + UIKatabatic/Lib/site-packages/click/types.py | 1093 ++ UIKatabatic/Lib/site-packages/click/utils.py | 624 + .../colorama-0.4.6.dist-info/INSTALLER | 1 + .../colorama-0.4.6.dist-info/METADATA | 441 + .../colorama-0.4.6.dist-info/RECORD | 31 + .../colorama-0.4.6.dist-info/WHEEL | 5 + .../licenses/LICENSE.txt | 27 + .../Lib/site-packages/colorama/__init__.py | 7 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 453 bytes .../colorama/__pycache__/ansi.cpython-39.pyc | Bin 0 -> 3203 bytes .../__pycache__/ansitowin32.cpython-39.pyc | Bin 0 -> 8281 bytes .../__pycache__/initialise.cpython-39.pyc | Bin 0 -> 2254 bytes .../colorama/__pycache__/win32.cpython-39.pyc | Bin 0 -> 4436 bytes .../__pycache__/winterm.cpython-39.pyc | Bin 0 -> 5239 bytes .../Lib/site-packages/colorama/ansi.py | 102 + .../Lib/site-packages/colorama/ansitowin32.py | 277 + .../Lib/site-packages/colorama/initialise.py | 121 + .../site-packages/colorama/tests/__init__.py | 1 + .../tests/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 173 bytes .../__pycache__/ansi_test.cpython-39.pyc | Bin 0 -> 2533 bytes .../ansitowin32_test.cpython-39.pyc | Bin 0 -> 11536 bytes .../initialise_test.cpython-39.pyc | Bin 0 -> 7065 bytes .../__pycache__/isatty_test.cpython-39.pyc | Bin 0 -> 2786 bytes .../tests/__pycache__/utils.cpython-39.pyc | Bin 0 -> 1641 bytes .../__pycache__/winterm_test.cpython-39.pyc | Bin 0 -> 3308 bytes .../site-packages/colorama/tests/ansi_test.py | 76 + .../colorama/tests/ansitowin32_test.py | 294 + .../colorama/tests/initialise_test.py | 189 + .../colorama/tests/isatty_test.py | 57 + .../Lib/site-packages/colorama/tests/utils.py | 49 + .../colorama/tests/winterm_test.py | 131 + .../Lib/site-packages/colorama/win32.py | 180 + .../Lib/site-packages/colorama/winterm.py | 195 + .../site-packages/distutils-precedence.pth | 1 + .../flask-3.1.0.dist-info/INSTALLER | 1 + .../flask-3.1.0.dist-info/LICENSE.txt | 28 + .../flask-3.1.0.dist-info/METADATA | 81 + .../flask-3.1.0.dist-info/RECORD | 58 + .../flask-3.1.0.dist-info/REQUESTED | 0 .../site-packages/flask-3.1.0.dist-info/WHEEL | 4 + .../flask-3.1.0.dist-info/entry_points.txt | 3 + .../Lib/site-packages/flask/__init__.py | 60 + .../Lib/site-packages/flask/__main__.py | 3 + .../flask/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2269 bytes .../flask/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 204 bytes .../flask/__pycache__/app.cpython-39.pyc | Bin 0 -> 50308 bytes .../__pycache__/blueprints.cpython-39.pyc | Bin 0 -> 4019 bytes .../flask/__pycache__/cli.cpython-39.pyc | Bin 0 -> 29159 bytes .../flask/__pycache__/config.cpython-39.pyc | Bin 0 -> 13146 bytes .../flask/__pycache__/ctx.cpython-39.pyc | Bin 0 -> 14658 bytes .../__pycache__/debughelpers.cpython-39.pyc | Bin 0 -> 6490 bytes .../flask/__pycache__/globals.cpython-39.pyc | Bin 0 -> 1572 bytes .../flask/__pycache__/helpers.cpython-39.pyc | Bin 0 -> 21716 bytes .../flask/__pycache__/logging.cpython-39.pyc | Bin 0 -> 2499 bytes .../flask/__pycache__/sessions.cpython-39.pyc | Bin 0 -> 14082 bytes .../flask/__pycache__/signals.cpython-39.pyc | Bin 0 -> 802 bytes .../__pycache__/templating.cpython-39.pyc | Bin 0 -> 6981 bytes .../flask/__pycache__/testing.cpython-39.pyc | Bin 0 -> 9513 bytes .../flask/__pycache__/typing.cpython-39.pyc | Bin 0 -> 1802 bytes .../flask/__pycache__/views.cpython-39.pyc | Bin 0 -> 5450 bytes .../flask/__pycache__/wrappers.cpython-39.pyc | Bin 0 -> 8450 bytes UIKatabatic/Lib/site-packages/flask/app.py | 1536 ++ .../Lib/site-packages/flask/blueprints.py | 128 + UIKatabatic/Lib/site-packages/flask/cli.py | 1133 ++ UIKatabatic/Lib/site-packages/flask/config.py | 367 + UIKatabatic/Lib/site-packages/flask/ctx.py | 449 + .../Lib/site-packages/flask/debughelpers.py | 178 + .../Lib/site-packages/flask/globals.py | 51 + .../Lib/site-packages/flask/helpers.py | 634 + .../Lib/site-packages/flask/json/__init__.py | 170 + .../json/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 5958 bytes .../json/__pycache__/provider.cpython-39.pyc | Bin 0 -> 7558 bytes .../flask/json/__pycache__/tag.cpython-39.pyc | Bin 0 -> 11944 bytes .../Lib/site-packages/flask/json/provider.py | 215 + .../Lib/site-packages/flask/json/tag.py | 327 + .../Lib/site-packages/flask/logging.py | 79 + UIKatabatic/Lib/site-packages/flask/py.typed | 0 .../Lib/site-packages/flask/sansio/README.md | 6 + .../sansio/__pycache__/app.cpython-39.pyc | Bin 0 -> 28255 bytes .../__pycache__/blueprints.cpython-39.pyc | Bin 0 -> 22805 bytes .../__pycache__/scaffold.cpython-39.pyc | Bin 0 -> 23644 bytes .../Lib/site-packages/flask/sansio/app.py | 964 ++ .../site-packages/flask/sansio/blueprints.py | 632 + .../site-packages/flask/sansio/scaffold.py | 792 + .../Lib/site-packages/flask/sessions.py | 398 + .../Lib/site-packages/flask/signals.py | 17 + .../Lib/site-packages/flask/templating.py | 219 + .../Lib/site-packages/flask/testing.py | 297 + UIKatabatic/Lib/site-packages/flask/typing.py | 90 + UIKatabatic/Lib/site-packages/flask/views.py | 191 + .../Lib/site-packages/flask/wrappers.py | 257 + .../INSTALLER | 1 + .../LICENSE | 202 + .../METADATA | 133 + .../importlib_metadata-8.6.1.dist-info/RECORD | 31 + .../importlib_metadata-8.6.1.dist-info/WHEEL | 5 + .../top_level.txt | 1 + .../importlib_metadata/__init__.py | 1132 ++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 41884 bytes .../__pycache__/_adapters.cpython-39.pyc | Bin 0 -> 4623 bytes .../__pycache__/_collections.cpython-39.pyc | Bin 0 -> 1547 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 1881 bytes .../__pycache__/_functools.cpython-39.pyc | Bin 0 -> 3137 bytes .../__pycache__/_itertools.cpython-39.pyc | Bin 0 -> 5014 bytes .../__pycache__/_meta.cpython-39.pyc | Bin 0 -> 3225 bytes .../__pycache__/_text.cpython-39.pyc | Bin 0 -> 3080 bytes .../__pycache__/diagnose.cpython-39.pyc | Bin 0 -> 831 bytes .../importlib_metadata/_adapters.py | 135 + .../importlib_metadata/_collections.py | 30 + .../importlib_metadata/_compat.py | 56 + .../importlib_metadata/_functools.py | 104 + .../importlib_metadata/_itertools.py | 171 + .../site-packages/importlib_metadata/_meta.py | 75 + .../site-packages/importlib_metadata/_text.py | 99 + .../importlib_metadata/compat/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 184 bytes .../compat/__pycache__/py311.cpython-39.pyc | Bin 0 -> 1020 bytes .../compat/__pycache__/py39.cpython-39.pyc | Bin 0 -> 1183 bytes .../importlib_metadata/compat/py311.py | 22 + .../importlib_metadata/compat/py39.py | 36 + .../importlib_metadata/diagnose.py | 21 + .../site-packages/importlib_metadata/py.typed | 0 .../itsdangerous-2.2.0.dist-info/INSTALLER | 1 + .../itsdangerous-2.2.0.dist-info/LICENSE.txt | 28 + .../itsdangerous-2.2.0.dist-info/METADATA | 60 + .../itsdangerous-2.2.0.dist-info/RECORD | 22 + .../itsdangerous-2.2.0.dist-info/WHEEL | 4 + .../site-packages/itsdangerous/__init__.py | 38 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1443 bytes .../__pycache__/_json.cpython-39.pyc | Bin 0 -> 938 bytes .../__pycache__/encoding.cpython-39.pyc | Bin 0 -> 1881 bytes .../__pycache__/exc.cpython-39.pyc | Bin 0 -> 3325 bytes .../__pycache__/serializer.cpython-39.pyc | Bin 0 -> 11352 bytes .../__pycache__/signer.cpython-39.pyc | Bin 0 -> 8806 bytes .../__pycache__/timed.cpython-39.pyc | Bin 0 -> 6391 bytes .../__pycache__/url_safe.cpython-39.pyc | Bin 0 -> 2835 bytes .../Lib/site-packages/itsdangerous/_json.py | 18 + .../site-packages/itsdangerous/encoding.py | 54 + .../Lib/site-packages/itsdangerous/exc.py | 106 + .../Lib/site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 406 + .../Lib/site-packages/itsdangerous/signer.py | 266 + .../Lib/site-packages/itsdangerous/timed.py | 228 + .../site-packages/itsdangerous/url_safe.py | 83 + .../jinja2-3.1.6.dist-info/INSTALLER | 1 + .../jinja2-3.1.6.dist-info/METADATA | 84 + .../jinja2-3.1.6.dist-info/RECORD | 57 + .../jinja2-3.1.6.dist-info/WHEEL | 4 + .../jinja2-3.1.6.dist-info/entry_points.txt | 3 + .../licenses/LICENSE.txt | 28 + .../Lib/site-packages/jinja2/__init__.py | 38 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1593 bytes .../__pycache__/_identifier.cpython-39.pyc | Bin 0 -> 2068 bytes .../__pycache__/async_utils.cpython-39.pyc | Bin 0 -> 3400 bytes .../jinja2/__pycache__/bccache.cpython-39.pyc | Bin 0 -> 13895 bytes .../__pycache__/compiler.cpython-39.pyc | Bin 0 -> 54863 bytes .../__pycache__/constants.cpython-39.pyc | Bin 0 -> 1529 bytes .../jinja2/__pycache__/debug.cpython-39.pyc | Bin 0 -> 3967 bytes .../__pycache__/defaults.cpython-39.pyc | Bin 0 -> 1329 bytes .../__pycache__/environment.cpython-39.pyc | Bin 0 -> 53173 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 5570 bytes .../jinja2/__pycache__/ext.cpython-39.pyc | Bin 0 -> 25686 bytes .../jinja2/__pycache__/filters.cpython-39.pyc | Bin 0 -> 51351 bytes .../__pycache__/idtracking.cpython-39.pyc | Bin 0 -> 11081 bytes .../jinja2/__pycache__/lexer.cpython-39.pyc | Bin 0 -> 20261 bytes .../jinja2/__pycache__/loaders.cpython-39.pyc | Bin 0 -> 21164 bytes .../jinja2/__pycache__/meta.cpython-39.pyc | Bin 0 -> 3787 bytes .../__pycache__/nativetypes.cpython-39.pyc | Bin 0 -> 4951 bytes .../jinja2/__pycache__/nodes.cpython-39.pyc | Bin 0 -> 40864 bytes .../__pycache__/optimizer.cpython-39.pyc | Bin 0 -> 1918 bytes .../jinja2/__pycache__/parser.cpython-39.pyc | Bin 0 -> 28014 bytes .../jinja2/__pycache__/runtime.cpython-39.pyc | Bin 0 -> 32361 bytes .../jinja2/__pycache__/sandbox.cpython-39.pyc | Bin 0 -> 12171 bytes .../jinja2/__pycache__/tests.cpython-39.pyc | Bin 0 -> 6567 bytes .../jinja2/__pycache__/utils.cpython-39.pyc | Bin 0 -> 24847 bytes .../jinja2/__pycache__/visitor.cpython-39.pyc | Bin 0 -> 3910 bytes .../Lib/site-packages/jinja2/_identifier.py | 6 + .../Lib/site-packages/jinja2/async_utils.py | 99 + .../Lib/site-packages/jinja2/bccache.py | 408 + .../Lib/site-packages/jinja2/compiler.py | 1998 +++ .../Lib/site-packages/jinja2/constants.py | 20 + UIKatabatic/Lib/site-packages/jinja2/debug.py | 191 + .../Lib/site-packages/jinja2/defaults.py | 48 + .../Lib/site-packages/jinja2/environment.py | 1672 ++ .../Lib/site-packages/jinja2/exceptions.py | 166 + UIKatabatic/Lib/site-packages/jinja2/ext.py | 870 ++ .../Lib/site-packages/jinja2/filters.py | 1873 +++ .../Lib/site-packages/jinja2/idtracking.py | 318 + UIKatabatic/Lib/site-packages/jinja2/lexer.py | 868 ++ .../Lib/site-packages/jinja2/loaders.py | 693 + UIKatabatic/Lib/site-packages/jinja2/meta.py | 112 + .../Lib/site-packages/jinja2/nativetypes.py | 130 + UIKatabatic/Lib/site-packages/jinja2/nodes.py | 1206 ++ .../Lib/site-packages/jinja2/optimizer.py | 48 + .../Lib/site-packages/jinja2/parser.py | 1049 ++ UIKatabatic/Lib/site-packages/jinja2/py.typed | 0 .../Lib/site-packages/jinja2/runtime.py | 1062 ++ .../Lib/site-packages/jinja2/sandbox.py | 436 + UIKatabatic/Lib/site-packages/jinja2/tests.py | 256 + UIKatabatic/Lib/site-packages/jinja2/utils.py | 766 + .../Lib/site-packages/jinja2/visitor.py | 92 + .../Lib/site-packages/markupsafe/__init__.py | 395 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 15539 bytes .../__pycache__/_native.cpython-39.pyc | Bin 0 -> 411 bytes .../Lib/site-packages/markupsafe/_native.py | 8 + .../Lib/site-packages/markupsafe/_speedups.c | 204 + .../markupsafe/_speedups.cp39-win_amd64.pyd | Bin 0 -> 13312 bytes .../site-packages/markupsafe/_speedups.pyi | 1 + .../Lib/site-packages/markupsafe/py.typed | 0 .../pip-22.0.4.dist-info/INSTALLER | 1 + .../pip-22.0.4.dist-info/LICENSE.txt | 20 + .../pip-22.0.4.dist-info/METADATA | 92 + .../site-packages/pip-22.0.4.dist-info/RECORD | 1053 ++ .../pip-22.0.4.dist-info/REQUESTED | 0 .../site-packages/pip-22.0.4.dist-info/WHEEL | 5 + .../pip-22.0.4.dist-info/entry_points.txt | 5 + .../pip-22.0.4.dist-info/top_level.txt | 1 + UIKatabatic/Lib/site-packages/pip/__init__.py | 13 + UIKatabatic/Lib/site-packages/pip/__main__.py | 31 + .../pip/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 618 bytes .../pip/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 574 bytes .../site-packages/pip/_internal/__init__.py | 19 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 739 bytes .../__pycache__/build_env.cpython-39.pyc | Bin 0 -> 9492 bytes .../__pycache__/cache.cpython-39.pyc | Bin 0 -> 8296 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 11144 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 23341 bytes .../_internal/__pycache__/main.cpython-39.pyc | Bin 0 -> 604 bytes .../__pycache__/pyproject.cpython-39.pyc | Bin 0 -> 3529 bytes .../self_outdated_check.cpython-39.pyc | Bin 0 -> 4569 bytes .../__pycache__/wheel_builder.cpython-39.pyc | Bin 0 -> 9148 bytes .../site-packages/pip/_internal/build_env.py | 296 + .../Lib/site-packages/pip/_internal/cache.py | 264 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 259 bytes .../__pycache__/autocompletion.cpython-39.pyc | Bin 0 -> 5242 bytes .../__pycache__/base_command.cpython-39.pyc | Bin 0 -> 6361 bytes .../cli/__pycache__/cmdoptions.cpython-39.pyc | Bin 0 -> 22685 bytes .../command_context.cpython-39.pyc | Bin 0 -> 1274 bytes .../cli/__pycache__/main.cpython-39.pyc | Bin 0 -> 1349 bytes .../__pycache__/main_parser.cpython-39.pyc | Bin 0 -> 2146 bytes .../cli/__pycache__/parser.cpython-39.pyc | Bin 0 -> 9930 bytes .../__pycache__/progress_bars.cpython-39.pyc | Bin 0 -> 9219 bytes .../__pycache__/req_command.cpython-39.pyc | Bin 0 -> 13428 bytes .../cli/__pycache__/spinners.cpython-39.pyc | Bin 0 -> 4929 bytes .../__pycache__/status_codes.cpython-39.pyc | Bin 0 -> 338 bytes .../pip/_internal/cli/autocompletion.py | 171 + .../pip/_internal/cli/base_command.py | 223 + .../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-39.pyc | Bin 0 -> 3036 bytes .../commands/__pycache__/cache.cpython-39.pyc | Bin 0 -> 6163 bytes .../commands/__pycache__/check.cpython-39.pyc | Bin 0 -> 1552 bytes .../__pycache__/completion.cpython-39.pyc | Bin 0 -> 3125 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 8306 bytes .../commands/__pycache__/debug.cpython-39.pyc | Bin 0 -> 6641 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 3969 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 2622 bytes .../commands/__pycache__/hash.cpython-39.pyc | Bin 0 -> 2118 bytes .../commands/__pycache__/help.cpython-39.pyc | Bin 0 -> 1290 bytes .../commands/__pycache__/index.cpython-39.pyc | Bin 0 -> 4580 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 17681 bytes .../commands/__pycache__/list.cpython-39.pyc | Bin 0 -> 10140 bytes .../__pycache__/search.cpython-39.pyc | Bin 0 -> 5308 bytes .../commands/__pycache__/show.cpython-39.pyc | Bin 0 -> 6078 bytes .../__pycache__/uninstall.cpython-39.pyc | Bin 0 -> 3086 bytes .../commands/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4836 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 | 361 + .../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-39.pyc | Bin 0 -> 782 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1857 bytes .../__pycache__/installed.cpython-39.pyc | Bin 0 -> 1215 bytes .../__pycache__/sdist.cpython-39.pyc | Bin 0 -> 4538 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1582 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 + .../index/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 213 bytes .../__pycache__/collector.cpython-39.pyc | Bin 0 -> 18018 bytes .../__pycache__/package_finder.cpython-39.pyc | Bin 0 -> 28068 bytes .../index/__pycache__/sources.cpython-39.pyc | Bin 0 -> 7178 bytes .../pip/_internal/index/collector.py | 610 + .../pip/_internal/index/package_finder.py | 1004 ++ .../pip/_internal/index/sources.py | 224 + .../pip/_internal/locations/__init__.py | 520 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 12501 bytes .../__pycache__/_distutils.cpython-39.pyc | Bin 0 -> 4652 bytes .../__pycache__/_sysconfig.cpython-39.pyc | Bin 0 -> 6243 bytes .../locations/__pycache__/base.cpython-39.pyc | Bin 0 -> 1521 bytes .../pip/_internal/locations/_distutils.py | 169 + .../pip/_internal/locations/_sysconfig.py | 219 + .../pip/_internal/locations/base.py | 52 + .../Lib/site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 62 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2316 bytes .../metadata/__pycache__/base.cpython-39.pyc | Bin 0 -> 21108 bytes .../__pycache__/pkg_resources.cpython-39.pyc | Bin 0 -> 9914 bytes .../pip/_internal/metadata/base.py | 546 + .../pip/_internal/metadata/pkg_resources.py | 256 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 247 bytes .../__pycache__/candidate.cpython-39.pyc | Bin 0 -> 1430 bytes .../__pycache__/direct_url.cpython-39.pyc | Bin 0 -> 7220 bytes .../__pycache__/format_control.cpython-39.pyc | Bin 0 -> 2701 bytes .../models/__pycache__/index.cpython-39.pyc | Bin 0 -> 1217 bytes .../models/__pycache__/link.cpython-39.pyc | Bin 0 -> 10241 bytes .../models/__pycache__/scheme.cpython-39.pyc | Bin 0 -> 993 bytes .../__pycache__/search_scope.cpython-39.pyc | Bin 0 -> 3462 bytes .../selection_prefs.cpython-39.pyc | Bin 0 -> 1649 bytes .../__pycache__/target_python.cpython-39.pyc | Bin 0 -> 3395 bytes .../models/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4319 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-39.pyc | Bin 0 -> 235 bytes .../network/__pycache__/auth.cpython-39.pyc | Bin 0 -> 7467 bytes .../network/__pycache__/cache.cpython-39.pyc | Bin 0 -> 2907 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 5499 bytes .../__pycache__/lazy_wheel.cpython-39.pyc | Bin 0 -> 8367 bytes .../__pycache__/session.cpython-39.pyc | Bin 0 -> 10737 bytes .../network/__pycache__/utils.cpython-39.pyc | Bin 0 -> 1413 bytes .../network/__pycache__/xmlrpc.cpython-39.pyc | Bin 0 -> 2034 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-39.pyc | Bin 0 -> 183 bytes .../__pycache__/check.cpython-39.pyc | Bin 0 -> 3987 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 6129 bytes .../__pycache__/prepare.cpython-39.pyc | Bin 0 -> 14745 bytes .../_internal/operations/build/__init__.py | 0 .../build/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 189 bytes .../build/__pycache__/metadata.cpython-39.pyc | Bin 0 -> 1400 bytes .../metadata_editable.cpython-39.pyc | Bin 0 -> 1434 bytes .../metadata_legacy.cpython-39.pyc | Bin 0 -> 2310 bytes .../build/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1184 bytes .../__pycache__/wheel_editable.cpython-39.pyc | Bin 0 -> 1400 bytes .../__pycache__/wheel_legacy.cpython-39.pyc | Bin 0 -> 2707 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-39.pyc | Bin 0 -> 247 bytes .../editable_legacy.cpython-39.pyc | Bin 0 -> 1468 bytes .../install/__pycache__/legacy.cpython-39.pyc | Bin 0 -> 3267 bytes .../install/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 20949 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-39.pyc | Bin 0 -> 2542 bytes .../__pycache__/constructors.cpython-39.pyc | Bin 0 -> 12087 bytes .../req/__pycache__/req_file.cpython-39.pyc | Bin 0 -> 13360 bytes .../__pycache__/req_install.cpython-39.pyc | Bin 0 -> 22103 bytes .../req/__pycache__/req_set.cpython-39.pyc | Bin 0 -> 5880 bytes .../__pycache__/req_tracker.cpython-39.pyc | Bin 0 -> 4240 bytes .../__pycache__/req_uninstall.cpython-39.pyc | Bin 0 -> 18821 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-39.pyc | Bin 0 -> 183 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1040 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 190 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 12178 bytes .../_internal/resolution/legacy/resolver.py | 467 + .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 194 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 6591 bytes .../__pycache__/candidates.cpython-39.pyc | Bin 0 -> 18514 bytes .../__pycache__/factory.cpython-39.pyc | Bin 0 -> 19082 bytes .../found_candidates.cpython-39.pyc | Bin 0 -> 4825 bytes .../__pycache__/provider.cpython-39.pyc | Bin 0 -> 7620 bytes .../__pycache__/reporter.cpython-39.pyc | Bin 0 -> 3255 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 7564 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 8163 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 | 298 + .../pip/_internal/self_outdated_check.py | 189 + .../pip/_internal/utils/__init__.py | 0 .../utils/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 178 bytes .../utils/__pycache__/_log.cpython-39.pyc | Bin 0 -> 1503 bytes .../utils/__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 1609 bytes .../utils/__pycache__/compat.cpython-39.pyc | Bin 0 -> 1497 bytes .../compatibility_tags.cpython-39.pyc | Bin 0 -> 4049 bytes .../utils/__pycache__/datetime.cpython-39.pyc | Bin 0 -> 497 bytes .../__pycache__/deprecation.cpython-39.pyc | Bin 0 -> 3235 bytes .../direct_url_helpers.cpython-39.pyc | Bin 0 -> 2068 bytes .../__pycache__/distutils_args.cpython-39.pyc | Bin 0 -> 1083 bytes .../utils/__pycache__/egg_link.cpython-39.pyc | Bin 0 -> 2124 bytes .../utils/__pycache__/encoding.cpython-39.pyc | Bin 0 -> 1287 bytes .../__pycache__/entrypoints.cpython-39.pyc | Bin 0 -> 1288 bytes .../__pycache__/filesystem.cpython-39.pyc | Bin 0 -> 5124 bytes .../__pycache__/filetypes.cpython-39.pyc | Bin 0 -> 928 bytes .../utils/__pycache__/glibc.cpython-39.pyc | Bin 0 -> 1659 bytes .../utils/__pycache__/hashes.cpython-39.pyc | Bin 0 -> 5173 bytes .../inject_securetransport.cpython-39.pyc | Bin 0 -> 967 bytes .../utils/__pycache__/logging.cpython-39.pyc | Bin 0 -> 9579 bytes .../utils/__pycache__/misc.cpython-39.pyc | Bin 0 -> 18784 bytes .../utils/__pycache__/models.cpython-39.pyc | Bin 0 -> 2046 bytes .../__pycache__/packaging.cpython-39.pyc | Bin 0 -> 2066 bytes .../setuptools_build.cpython-39.pyc | Bin 0 -> 4554 bytes .../__pycache__/subprocess.cpython-39.pyc | Bin 0 -> 5694 bytes .../utils/__pycache__/temp_dir.cpython-39.pyc | Bin 0 -> 7245 bytes .../__pycache__/unpacking.cpython-39.pyc | Bin 0 -> 6709 bytes .../utils/__pycache__/urls.cpython-39.pyc | Bin 0 -> 1582 bytes .../__pycache__/virtualenv.cpython-39.pyc | Bin 0 -> 3272 bytes .../utils/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4462 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 | 629 + .../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-39.pyc | Bin 0 -> 501 bytes .../vcs/__pycache__/bazaar.cpython-39.pyc | Bin 0 -> 3340 bytes .../vcs/__pycache__/git.cpython-39.pyc | Bin 0 -> 12548 bytes .../vcs/__pycache__/mercurial.cpython-39.pyc | Bin 0 -> 5045 bytes .../vcs/__pycache__/subversion.cpython-39.pyc | Bin 0 -> 8462 bytes .../__pycache__/versioncontrol.cpython-39.pyc | Bin 0 -> 21168 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 + .../Lib/site-packages/pip/_vendor/__init__.py | 111 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2891 bytes .../_vendor/__pycache__/distro.cpython-39.pyc | Bin 0 -> 38353 bytes .../_vendor/__pycache__/six.cpython-39.pyc | Bin 0 -> 27495 bytes .../typing_extensions.cpython-39.pyc | Bin 0 -> 68479 bytes .../pip/_vendor/cachecontrol/__init__.py | 18 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 629 bytes .../__pycache__/_cmd.cpython-39.pyc | Bin 0 -> 1557 bytes .../__pycache__/adapter.cpython-39.pyc | Bin 0 -> 3121 bytes .../__pycache__/cache.cpython-39.pyc | Bin 0 -> 1828 bytes .../__pycache__/compat.cpython-39.pyc | Bin 0 -> 733 bytes .../__pycache__/controller.cpython-39.pyc | Bin 0 -> 8195 bytes .../__pycache__/filewrapper.cpython-39.pyc | Bin 0 -> 2773 bytes .../__pycache__/heuristics.cpython-39.pyc | Bin 0 -> 4690 bytes .../__pycache__/serialize.cpython-39.pyc | Bin 0 -> 4237 bytes .../__pycache__/wrapper.cpython-39.pyc | Bin 0 -> 660 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-39.pyc | Bin 0 -> 280 bytes .../__pycache__/file_cache.cpython-39.pyc | Bin 0 -> 3310 bytes .../__pycache__/redis_cache.cpython-39.pyc | Bin 0 -> 1552 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-39.pyc | Bin 0 -> 262 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 439 bytes .../certifi/__pycache__/core.cpython-39.pyc | Bin 0 -> 1530 bytes .../pip/_vendor/certifi/cacert.pem | 4362 ++++++ .../site-packages/pip/_vendor/certifi/core.py | 76 + .../pip/_vendor/chardet/__init__.py | 83 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1886 bytes .../__pycache__/big5freq.cpython-39.pyc | Bin 0 -> 27165 bytes .../__pycache__/big5prober.cpython-39.pyc | Bin 0 -> 1120 bytes .../chardistribution.cpython-39.pyc | Bin 0 -> 6206 bytes .../charsetgroupprober.cpython-39.pyc | Bin 0 -> 2247 bytes .../__pycache__/charsetprober.cpython-39.pyc | Bin 0 -> 3469 bytes .../codingstatemachine.cpython-39.pyc | Bin 0 -> 2896 bytes .../chardet/__pycache__/compat.cpython-39.pyc | Bin 0 -> 385 bytes .../__pycache__/cp949prober.cpython-39.pyc | Bin 0 -> 1127 bytes .../chardet/__pycache__/enums.cpython-39.pyc | Bin 0 -> 2634 bytes .../__pycache__/escprober.cpython-39.pyc | Bin 0 -> 2619 bytes .../chardet/__pycache__/escsm.cpython-39.pyc | Bin 0 -> 7068 bytes .../__pycache__/eucjpprober.cpython-39.pyc | Bin 0 -> 2433 bytes .../__pycache__/euckrfreq.cpython-39.pyc | Bin 0 -> 12049 bytes .../__pycache__/euckrprober.cpython-39.pyc | Bin 0 -> 1128 bytes .../__pycache__/euctwfreq.cpython-39.pyc | Bin 0 -> 27169 bytes .../__pycache__/euctwprober.cpython-39.pyc | Bin 0 -> 1128 bytes .../__pycache__/gb2312freq.cpython-39.pyc | Bin 0 -> 19093 bytes .../__pycache__/gb2312prober.cpython-39.pyc | Bin 0 -> 1136 bytes .../__pycache__/hebrewprober.cpython-39.pyc | Bin 0 -> 3005 bytes .../__pycache__/jisfreq.cpython-39.pyc | Bin 0 -> 22121 bytes .../chardet/__pycache__/jpcntx.cpython-39.pyc | Bin 0 -> 37594 bytes .../langbulgarianmodel.cpython-39.pyc | Bin 0 -> 21796 bytes .../__pycache__/langgreekmodel.cpython-39.pyc | Bin 0 -> 20472 bytes .../langhebrewmodel.cpython-39.pyc | Bin 0 -> 20540 bytes .../langhungarianmodel.cpython-39.pyc | Bin 0 -> 21741 bytes .../langrussianmodel.cpython-39.pyc | Bin 0 -> 26344 bytes .../__pycache__/langthaimodel.cpython-39.pyc | Bin 0 -> 20716 bytes .../langturkishmodel.cpython-39.pyc | Bin 0 -> 20556 bytes .../__pycache__/latin1prober.cpython-39.pyc | Bin 0 -> 2941 bytes .../mbcharsetprober.cpython-39.pyc | Bin 0 -> 2248 bytes .../mbcsgroupprober.cpython-39.pyc | Bin 0 -> 1117 bytes .../chardet/__pycache__/mbcssm.cpython-39.pyc | Bin 0 -> 15704 bytes .../sbcharsetprober.cpython-39.pyc | Bin 0 -> 3101 bytes .../sbcsgroupprober.cpython-39.pyc | Bin 0 -> 1686 bytes .../__pycache__/sjisprober.cpython-39.pyc | Bin 0 -> 2469 bytes .../universaldetector.cpython-39.pyc | Bin 0 -> 5817 bytes .../__pycache__/utf8prober.cpython-39.pyc | Bin 0 -> 1978 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 425 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-39.pyc | Bin 0 -> 182 bytes .../cli/__pycache__/chardetect.cpython-39.pyc | Bin 0 -> 2676 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-39.pyc | Bin 0 -> 187 bytes .../__pycache__/languages.cpython-39.pyc | Bin 0 -> 7918 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-39.pyc | Bin 0 -> 430 bytes .../colorama/__pycache__/ansi.cpython-39.pyc | Bin 0 -> 3215 bytes .../__pycache__/ansitowin32.cpython-39.pyc | Bin 0 -> 7681 bytes .../__pycache__/initialise.cpython-39.pyc | Bin 0 -> 1697 bytes .../colorama/__pycache__/win32.cpython-39.pyc | Bin 0 -> 3929 bytes .../__pycache__/winterm.cpython-39.pyc | Bin 0 -> 4651 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-39.pyc | Bin 0 -> 1043 bytes .../distlib/__pycache__/compat.cpython-39.pyc | Bin 0 -> 31808 bytes .../__pycache__/database.cpython-39.pyc | Bin 0 -> 42467 bytes .../distlib/__pycache__/index.cpython-39.pyc | Bin 0 -> 17276 bytes .../__pycache__/locators.cpython-39.pyc | Bin 0 -> 38240 bytes .../__pycache__/manifest.cpython-39.pyc | Bin 0 -> 10179 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 4961 bytes .../__pycache__/metadata.cpython-39.pyc | Bin 0 -> 26574 bytes .../__pycache__/resources.cpython-39.pyc | Bin 0 -> 10997 bytes .../__pycache__/scripts.cpython-39.pyc | Bin 0 -> 11229 bytes .../distlib/__pycache__/util.cpython-39.pyc | Bin 0 -> 52592 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 20342 bytes .../distlib/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 27155 bytes .../pip/_vendor/distlib/_backport/__init__.py | 6 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 470 bytes .../_backport/__pycache__/misc.cpython-39.pyc | Bin 0 -> 1090 bytes .../__pycache__/shutil.cpython-39.pyc | Bin 0 -> 21664 bytes .../__pycache__/sysconfig.cpython-39.pyc | Bin 0 -> 15954 bytes .../__pycache__/tarfile.cpython-39.pyc | Bin 0 -> 62718 bytes .../pip/_vendor/distlib/_backport/misc.py | 41 + .../pip/_vendor/distlib/_backport/shutil.py | 764 + .../_vendor/distlib/_backport/sysconfig.cfg | 84 + .../_vendor/distlib/_backport/sysconfig.py | 786 + .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ++++ .../pip/_vendor/distlib/compat.py | 1122 ++ .../pip/_vendor/distlib/database.py | 1339 ++ .../pip/_vendor/distlib/index.py | 509 + .../pip/_vendor/distlib/locators.py | 1300 ++ .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 147 + .../pip/_vendor/distlib/metadata.py | 1058 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 429 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 96768 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 180736 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 105984 bytes .../site-packages/pip/_vendor/distlib/util.py | 1969 +++ .../pip/_vendor/distlib/version.py | 739 + .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 90112 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 166400 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 99840 bytes .../pip/_vendor/distlib/wheel.py | 1053 ++ .../Lib/site-packages/pip/_vendor/distro.py | 1386 ++ .../pip/_vendor/html5lib/__init__.py | 35 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1289 bytes .../__pycache__/_ihatexml.cpython-39.pyc | Bin 0 -> 13758 bytes .../__pycache__/_inputstream.cpython-39.pyc | Bin 0 -> 21617 bytes .../__pycache__/_tokenizer.cpython-39.pyc | Bin 0 -> 39712 bytes .../__pycache__/_utils.cpython-39.pyc | Bin 0 -> 4789 bytes .../__pycache__/constants.cpython-39.pyc | Bin 0 -> 66327 bytes .../__pycache__/html5parser.cpython-39.pyc | Bin 0 -> 90998 bytes .../__pycache__/serializer.cpython-39.pyc | Bin 0 -> 10800 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 + .../_trie/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 339 bytes .../_trie/__pycache__/_base.cpython-39.pyc | Bin 0 -> 1583 bytes .../_trie/__pycache__/py.cpython-39.pyc | Bin 0 -> 2244 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-39.pyc | Bin 0 -> 187 bytes .../alphabeticalattributes.cpython-39.pyc | Bin 0 -> 1309 bytes .../filters/__pycache__/base.cpython-39.pyc | Bin 0 -> 857 bytes .../inject_meta_charset.cpython-39.pyc | Bin 0 -> 1863 bytes .../filters/__pycache__/lint.cpython-39.pyc | Bin 0 -> 2605 bytes .../__pycache__/optionaltags.cpython-39.pyc | Bin 0 -> 2750 bytes .../__pycache__/sanitizer.cpython-39.pyc | Bin 0 -> 16873 bytes .../__pycache__/whitespace.cpython-39.pyc | Bin 0 -> 1355 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-39.pyc | Bin 0 -> 924 bytes .../__pycache__/genshi.cpython-39.pyc | Bin 0 -> 1532 bytes .../__pycache__/sax.cpython-39.pyc | Bin 0 -> 1451 bytes .../_vendor/html5lib/treeadapters/genshi.py | 54 + .../pip/_vendor/html5lib/treeadapters/sax.py | 50 + .../_vendor/html5lib/treebuilders/__init__.py | 88 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3319 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 11303 bytes .../__pycache__/dom.cpython-39.pyc | Bin 0 -> 9440 bytes .../__pycache__/etree.cpython-39.pyc | Bin 0 -> 11808 bytes .../__pycache__/etree_lxml.cpython-39.pyc | Bin 0 -> 12991 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-39.pyc | Bin 0 -> 3985 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 6984 bytes .../__pycache__/dom.cpython-39.pyc | Bin 0 -> 1719 bytes .../__pycache__/etree.cpython-39.pyc | Bin 0 -> 3481 bytes .../__pycache__/etree_lxml.cpython-39.pyc | Bin 0 -> 6618 bytes .../__pycache__/genshi.cpython-39.pyc | Bin 0 -> 1875 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-39.pyc | Bin 0 -> 834 bytes .../idna/__pycache__/codec.cpython-39.pyc | Bin 0 -> 3071 bytes .../idna/__pycache__/compat.cpython-39.pyc | Bin 0 -> 753 bytes .../idna/__pycache__/core.cpython-39.pyc | Bin 0 -> 9749 bytes .../idna/__pycache__/idnadata.cpython-39.pyc | Bin 0 -> 23030 bytes .../idna/__pycache__/intranges.cpython-39.pyc | Bin 0 -> 1984 bytes .../__pycache__/package_data.cpython-39.pyc | Bin 0 -> 198 bytes .../idna/__pycache__/uts46data.cpython-39.pyc | Bin 0 -> 151731 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-39.pyc | Bin 0 -> 1401 bytes .../__pycache__/_version.cpython-39.pyc | Bin 0 -> 205 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 1839 bytes .../msgpack/__pycache__/ext.cpython-39.pyc | Bin 0 -> 6267 bytes .../__pycache__/fallback.cpython-39.pyc | Bin 0 -> 25606 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-39.pyc | Bin 0 -> 577 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 433 bytes .../__pycache__/_manylinux.cpython-39.pyc | Bin 0 -> 7281 bytes .../__pycache__/_musllinux.cpython-39.pyc | Bin 0 -> 4596 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2790 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9440 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 3961 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 21508 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 12239 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 3598 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13139 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-39.pyc | Bin 0 -> 300 bytes .../pep517/__pycache__/build.cpython-39.pyc | Bin 0 -> 3548 bytes .../pep517/__pycache__/check.cpython-39.pyc | Bin 0 -> 5095 bytes .../__pycache__/colorlog.cpython-39.pyc | Bin 0 -> 2925 bytes .../pep517/__pycache__/compat.cpython-39.pyc | Bin 0 -> 1516 bytes .../__pycache__/dirtools.cpython-39.pyc | Bin 0 -> 1334 bytes .../__pycache__/envbuild.cpython-39.pyc | Bin 0 -> 4494 bytes .../pep517/__pycache__/meta.cpython-39.pyc | Bin 0 -> 2907 bytes .../__pycache__/wrappers.cpython-39.pyc | Bin 0 -> 12480 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-39.pyc | Bin 0 -> 902 bytes .../__pycache__/_in_process.cpython-39.pyc | Bin 0 -> 10256 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-39.pyc | Bin 0 -> 100323 bytes .../__pycache__/py31compat.cpython-39.pyc | Bin 0 -> 637 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/platformdirs/__init__.py | 331 + .../pip/_vendor/platformdirs/__main__.py | 46 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 10638 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 1209 bytes .../__pycache__/android.cpython-39.pyc | Bin 0 -> 4358 bytes .../__pycache__/api.cpython-39.pyc | Bin 0 -> 5271 bytes .../__pycache__/macos.cpython-39.pyc | Bin 0 -> 3293 bytes .../__pycache__/unix.cpython-39.pyc | Bin 0 -> 7041 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 282 bytes .../__pycache__/windows.cpython-39.pyc | Bin 0 -> 6437 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-39.pyc | Bin 0 -> 5669 bytes .../progress/__pycache__/bar.cpython-39.pyc | Bin 0 -> 2714 bytes .../__pycache__/colors.cpython-39.pyc | Bin 0 -> 1487 bytes .../__pycache__/counter.cpython-39.pyc | Bin 0 -> 1612 bytes .../__pycache__/spinner.cpython-39.pyc | Bin 0 -> 1438 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-39.pyc | Bin 0 -> 3012 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 573 bytes .../__pycache__/cmdline.cpython-39.pyc | Bin 0 -> 15365 bytes .../__pycache__/console.cpython-39.pyc | Bin 0 -> 1870 bytes .../__pycache__/filter.cpython-39.pyc | Bin 0 -> 2631 bytes .../__pycache__/formatter.cpython-39.pyc | Bin 0 -> 2995 bytes .../pygments/__pycache__/lexer.cpython-39.pyc | Bin 0 -> 24425 bytes .../__pycache__/modeline.cpython-39.pyc | Bin 0 -> 1173 bytes .../__pycache__/plugin.cpython-39.pyc | Bin 0 -> 2093 bytes .../__pycache__/regexopt.cpython-39.pyc | Bin 0 -> 2927 bytes .../__pycache__/scanner.cpython-39.pyc | Bin 0 -> 3540 bytes .../__pycache__/sphinxext.cpython-39.pyc | Bin 0 -> 4545 bytes .../pygments/__pycache__/style.cpython-39.pyc | Bin 0 -> 4482 bytes .../pygments/__pycache__/token.cpython-39.pyc | Bin 0 -> 4344 bytes .../__pycache__/unistring.cpython-39.pyc | Bin 0 -> 31202 bytes .../pygments/__pycache__/util.cpython-39.pyc | Bin 0 -> 9159 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-39.pyc | Bin 0 -> 23380 bytes .../pip/_vendor/pygments/formatter.py | 94 + .../_vendor/pygments/formatters/__init__.py | 153 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 4648 bytes .../__pycache__/_mapping.cpython-39.pyc | Bin 0 -> 5404 bytes .../__pycache__/bbcode.cpython-39.pyc | Bin 0 -> 3052 bytes .../__pycache__/groff.cpython-39.pyc | Bin 0 -> 4325 bytes .../__pycache__/html.cpython-39.pyc | Bin 0 -> 29037 bytes .../formatters/__pycache__/img.cpython-39.pyc | Bin 0 -> 17479 bytes .../formatters/__pycache__/irc.cpython-39.pyc | Bin 0 -> 4391 bytes .../__pycache__/latex.cpython-39.pyc | Bin 0 -> 13473 bytes .../__pycache__/other.cpython-39.pyc | Bin 0 -> 4775 bytes .../__pycache__/pangomarkup.cpython-39.pyc | Bin 0 -> 2077 bytes .../formatters/__pycache__/rtf.cpython-39.pyc | Bin 0 -> 4111 bytes .../formatters/__pycache__/svg.cpython-39.pyc | Bin 0 -> 6323 bytes .../__pycache__/terminal.cpython-39.pyc | Bin 0 -> 3892 bytes .../__pycache__/terminal256.cpython-39.pyc | Bin 0 -> 9202 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-39.pyc | Bin 0 -> 9125 bytes .../__pycache__/_mapping.cpython-39.pyc | Bin 0 -> 50808 bytes .../lexers/__pycache__/python.cpython-39.pyc | Bin 0 -> 28953 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-39.pyc | Bin 0 -> 2993 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-39.pyc | Bin 0 -> 7104 bytes .../__pycache__/actions.cpython-39.pyc | Bin 0 -> 7155 bytes .../__pycache__/common.cpython-39.pyc | Bin 0 -> 10046 bytes .../pyparsing/__pycache__/core.cpython-39.pyc | Bin 0 -> 176656 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 9143 bytes .../__pycache__/helpers.cpython-39.pyc | Bin 0 -> 34691 bytes .../__pycache__/results.cpython-39.pyc | Bin 0 -> 24767 bytes .../__pycache__/testing.cpython-39.pyc | Bin 0 -> 12096 bytes .../__pycache__/unicode.cpython-39.pyc | Bin 0 -> 10237 bytes .../pyparsing/__pycache__/util.cpython-39.pyc | Bin 0 -> 8606 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-39.pyc | Bin 0 -> 15574 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-39.pyc | Bin 0 -> 4015 bytes .../__pycache__/__version__.cpython-39.pyc | Bin 0 -> 542 bytes .../_internal_utils.cpython-39.pyc | Bin 0 -> 1289 bytes .../__pycache__/adapters.cpython-39.pyc | Bin 0 -> 17099 bytes .../requests/__pycache__/api.cpython-39.pyc | Bin 0 -> 6706 bytes .../requests/__pycache__/auth.cpython-39.pyc | Bin 0 -> 8318 bytes .../requests/__pycache__/certs.cpython-39.pyc | Bin 0 -> 620 bytes .../__pycache__/compat.cpython-39.pyc | Bin 0 -> 1655 bytes .../__pycache__/cookies.cpython-39.pyc | Bin 0 -> 18809 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 5645 bytes .../requests/__pycache__/help.cpython-39.pyc | Bin 0 -> 2880 bytes .../requests/__pycache__/hooks.cpython-39.pyc | Bin 0 -> 977 bytes .../__pycache__/models.cpython-39.pyc | Bin 0 -> 24358 bytes .../__pycache__/packages.cpython-39.pyc | Bin 0 -> 489 bytes .../__pycache__/sessions.cpython-39.pyc | Bin 0 -> 19693 bytes .../__pycache__/status_codes.cpython-39.pyc | Bin 0 -> 4226 bytes .../__pycache__/structures.cpython-39.pyc | Bin 0 -> 4447 bytes .../requests/__pycache__/utils.cpython-39.pyc | Bin 0 -> 24274 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-39.pyc | Bin 0 -> 593 bytes .../__pycache__/providers.cpython-39.pyc | Bin 0 -> 6692 bytes .../__pycache__/reporters.cpython-39.pyc | Bin 0 -> 2604 bytes .../__pycache__/resolvers.cpython-39.pyc | Bin 0 -> 15295 bytes .../__pycache__/structs.cpython-39.pyc | Bin 0 -> 7266 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 188 bytes .../collections_abc.cpython-39.pyc | Bin 0 -> 362 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-39.pyc | Bin 0 -> 5786 bytes .../rich/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 7278 bytes .../__pycache__/_cell_widths.cpython-39.pyc | Bin 0 -> 7801 bytes .../__pycache__/_emoji_codes.cpython-39.pyc | Bin 0 -> 132688 bytes .../__pycache__/_emoji_replace.cpython-39.pyc | Bin 0 -> 1173 bytes .../__pycache__/_extension.cpython-39.pyc | Bin 0 -> 482 bytes .../rich/__pycache__/_inspect.cpython-39.pyc | Bin 0 -> 6627 bytes .../__pycache__/_log_render.cpython-39.pyc | Bin 0 -> 2565 bytes .../rich/__pycache__/_loop.cpython-39.pyc | Bin 0 -> 1255 bytes .../__pycache__/_lru_cache.cpython-39.pyc | Bin 0 -> 1571 bytes .../rich/__pycache__/_palettes.cpython-39.pyc | Bin 0 -> 5084 bytes .../rich/__pycache__/_pick.cpython-39.pyc | Bin 0 -> 625 bytes .../rich/__pycache__/_ratio.cpython-39.pyc | Bin 0 -> 5109 bytes .../rich/__pycache__/_spinners.cpython-39.pyc | Bin 0 -> 13904 bytes .../rich/__pycache__/_stack.cpython-39.pyc | Bin 0 -> 830 bytes .../rich/__pycache__/_timer.cpython-39.pyc | Bin 0 -> 677 bytes .../rich/__pycache__/_windows.cpython-39.pyc | Bin 0 -> 1853 bytes .../rich/__pycache__/_wrap.cpython-39.pyc | Bin 0 -> 1483 bytes .../rich/__pycache__/abc.cpython-39.pyc | Bin 0 -> 1291 bytes .../rich/__pycache__/align.cpython-39.pyc | Bin 0 -> 7859 bytes .../rich/__pycache__/ansi.cpython-39.pyc | Bin 0 -> 5661 bytes .../rich/__pycache__/bar.cpython-39.pyc | Bin 0 -> 2929 bytes .../rich/__pycache__/box.cpython-39.pyc | Bin 0 -> 7843 bytes .../rich/__pycache__/cells.cpython-39.pyc | Bin 0 -> 3478 bytes .../rich/__pycache__/color.cpython-39.pyc | Bin 0 -> 14737 bytes .../__pycache__/color_triplet.cpython-39.pyc | Bin 0 -> 1412 bytes .../rich/__pycache__/columns.cpython-39.pyc | Bin 0 -> 6116 bytes .../rich/__pycache__/console.cpython-39.pyc | Bin 0 -> 69738 bytes .../rich/__pycache__/constrain.cpython-39.pyc | Bin 0 -> 1650 bytes .../__pycache__/containers.cpython-39.pyc | Bin 0 -> 6411 bytes .../rich/__pycache__/control.cpython-39.pyc | Bin 0 -> 6836 bytes .../__pycache__/default_styles.cpython-39.pyc | Bin 0 -> 5103 bytes .../rich/__pycache__/diagnose.cpython-39.pyc | Bin 0 -> 336 bytes .../rich/__pycache__/emoji.cpython-39.pyc | Bin 0 -> 3189 bytes .../rich/__pycache__/errors.cpython-39.pyc | Bin 0 -> 1656 bytes .../__pycache__/file_proxy.cpython-39.pyc | Bin 0 -> 2230 bytes .../rich/__pycache__/filesize.cpython-39.pyc | Bin 0 -> 2599 bytes .../__pycache__/highlighter.cpython-39.pyc | Bin 0 -> 5304 bytes .../rich/__pycache__/json.cpython-39.pyc | Bin 0 -> 4690 bytes .../rich/__pycache__/jupyter.cpython-39.pyc | Bin 0 -> 3830 bytes .../rich/__pycache__/layout.cpython-39.pyc | Bin 0 -> 14672 bytes .../rich/__pycache__/live.cpython-39.pyc | Bin 0 -> 11272 bytes .../__pycache__/live_render.cpython-39.pyc | Bin 0 -> 3377 bytes .../rich/__pycache__/logging.cpython-39.pyc | Bin 0 -> 9216 bytes .../rich/__pycache__/markup.cpython-39.pyc | Bin 0 -> 5883 bytes .../rich/__pycache__/measure.cpython-39.pyc | Bin 0 -> 4964 bytes .../rich/__pycache__/padding.cpython-39.pyc | Bin 0 -> 4393 bytes .../rich/__pycache__/pager.cpython-39.pyc | Bin 0 -> 1459 bytes .../rich/__pycache__/palette.cpython-39.pyc | Bin 0 -> 3675 bytes .../rich/__pycache__/panel.cpython-39.pyc | Bin 0 -> 6380 bytes .../rich/__pycache__/pretty.cpython-39.pyc | Bin 0 -> 24905 bytes .../rich/__pycache__/progress.cpython-39.pyc | Bin 0 -> 32939 bytes .../__pycache__/progress_bar.cpython-39.pyc | Bin 0 -> 6604 bytes .../rich/__pycache__/prompt.cpython-39.pyc | Bin 0 -> 11344 bytes .../rich/__pycache__/protocol.cpython-39.pyc | Bin 0 -> 1345 bytes .../rich/__pycache__/region.cpython-39.pyc | Bin 0 -> 512 bytes .../rich/__pycache__/repr.cpython-39.pyc | Bin 0 -> 4024 bytes .../rich/__pycache__/rule.cpython-39.pyc | Bin 0 -> 3688 bytes .../rich/__pycache__/scope.cpython-39.pyc | Bin 0 -> 2950 bytes .../rich/__pycache__/screen.cpython-39.pyc | Bin 0 -> 1809 bytes .../rich/__pycache__/segment.cpython-39.pyc | Bin 0 -> 20290 bytes .../rich/__pycache__/spinner.cpython-39.pyc | Bin 0 -> 4330 bytes .../rich/__pycache__/status.cpython-39.pyc | Bin 0 -> 4562 bytes .../rich/__pycache__/style.cpython-39.pyc | Bin 0 -> 20590 bytes .../rich/__pycache__/styled.cpython-39.pyc | Bin 0 -> 1675 bytes .../rich/__pycache__/syntax.cpython-39.pyc | Bin 0 -> 18791 bytes .../rich/__pycache__/table.cpython-39.pyc | Bin 0 -> 26657 bytes .../rich/__pycache__/tabulate.cpython-39.pyc | Bin 0 -> 1717 bytes .../__pycache__/terminal_theme.cpython-39.pyc | Bin 0 -> 1687 bytes .../rich/__pycache__/text.cpython-39.pyc | Bin 0 -> 39437 bytes .../rich/__pycache__/theme.cpython-39.pyc | Bin 0 -> 4667 bytes .../rich/__pycache__/themes.cpython-39.pyc | Bin 0 -> 280 bytes .../rich/__pycache__/traceback.cpython-39.pyc | Bin 0 -> 19347 bytes .../rich/__pycache__/tree.cpython-39.pyc | Bin 0 -> 7197 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 + .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 312 + .../site-packages/pip/_vendor/rich/ansi.py | 228 + .../Lib/site-packages/pip/_vendor/rich/bar.py | 94 + .../Lib/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 + .../Lib/site-packages/pip/_vendor/six.py | 998 ++ .../pip/_vendor/tenacity/__init__.py | 517 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 16266 bytes .../__pycache__/_asyncio.cpython-39.pyc | Bin 0 -> 2581 bytes .../__pycache__/_utils.cpython-39.pyc | Bin 0 -> 1218 bytes .../tenacity/__pycache__/after.cpython-39.pyc | Bin 0 -> 1197 bytes .../__pycache__/before.cpython-39.pyc | Bin 0 -> 1085 bytes .../__pycache__/before_sleep.cpython-39.pyc | Bin 0 -> 1377 bytes .../tenacity/__pycache__/nap.cpython-39.pyc | Bin 0 -> 1179 bytes .../tenacity/__pycache__/retry.cpython-39.pyc | Bin 0 -> 8767 bytes .../tenacity/__pycache__/stop.cpython-39.pyc | Bin 0 -> 4231 bytes .../__pycache__/tornadoweb.cpython-39.pyc | Bin 0 -> 1731 bytes .../tenacity/__pycache__/wait.cpython-39.pyc | Bin 0 -> 7943 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 + .../tomli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 366 bytes .../tomli/__pycache__/_parser.cpython-39.pyc | Bin 0 -> 16341 bytes .../tomli/__pycache__/_re.cpython-39.pyc | Bin 0 -> 2416 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-39.pyc | Bin 0 -> 2176 bytes .../__pycache__/_collections.cpython-39.pyc | Bin 0 -> 10771 bytes .../__pycache__/_version.cpython-39.pyc | Bin 0 -> 200 bytes .../__pycache__/connection.cpython-39.pyc | Bin 0 -> 13665 bytes .../__pycache__/connectionpool.cpython-39.pyc | Bin 0 -> 25349 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 11633 bytes .../urllib3/__pycache__/fields.cpython-39.pyc | Bin 0 -> 8148 bytes .../__pycache__/filepost.cpython-39.pyc | Bin 0 -> 2749 bytes .../__pycache__/poolmanager.cpython-39.pyc | Bin 0 -> 15151 bytes .../__pycache__/request.cpython-39.pyc | Bin 0 -> 5612 bytes .../__pycache__/response.cpython-39.pyc | Bin 0 -> 20823 bytes .../pip/_vendor/urllib3/_collections.py | 337 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 569 + .../pip/_vendor/urllib3/connectionpool.py | 1108 ++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 186 bytes .../_appengine_environ.cpython-39.pyc | Bin 0 -> 1406 bytes .../__pycache__/appengine.cpython-39.pyc | Bin 0 -> 8259 bytes .../__pycache__/ntlmpool.cpython-39.pyc | Bin 0 -> 3613 bytes .../__pycache__/pyopenssl.cpython-39.pyc | Bin 0 -> 15590 bytes .../securetransport.cpython-39.pyc | Bin 0 -> 21912 bytes .../contrib/__pycache__/socks.cpython-39.pyc | Bin 0 -> 5622 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 203 bytes .../__pycache__/bindings.cpython-39.pyc | Bin 0 -> 10695 bytes .../__pycache__/low_level.cpython-39.pyc | Bin 0 -> 9163 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-39.pyc | Bin 0 -> 187 bytes .../packages/__pycache__/six.cpython-39.pyc | Bin 0 -> 27570 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 197 bytes .../__pycache__/makefile.cpython-39.pyc | Bin 0 -> 1295 bytes .../urllib3/packages/backports/makefile.py | 51 + .../pip/_vendor/urllib3/packages/six.py | 1077 ++ .../pip/_vendor/urllib3/poolmanager.py | 536 + .../pip/_vendor/urllib3/request.py | 170 + .../pip/_vendor/urllib3/response.py | 821 + .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1096 bytes .../__pycache__/connection.cpython-39.pyc | Bin 0 -> 3428 bytes .../util/__pycache__/proxy.cpython-39.pyc | Bin 0 -> 1332 bytes .../util/__pycache__/queue.cpython-39.pyc | Bin 0 -> 1051 bytes .../util/__pycache__/request.cpython-39.pyc | Bin 0 -> 3439 bytes .../util/__pycache__/response.cpython-39.pyc | Bin 0 -> 2336 bytes .../util/__pycache__/retry.cpython-39.pyc | Bin 0 -> 16243 bytes .../util/__pycache__/ssl_.cpython-39.pyc | Bin 0 -> 11320 bytes .../ssl_match_hostname.cpython-39.pyc | Bin 0 -> 3270 bytes .../__pycache__/ssltransport.cpython-39.pyc | Bin 0 -> 7466 bytes .../util/__pycache__/timeout.cpython-39.pyc | Bin 0 -> 8934 bytes .../util/__pycache__/url.cpython-39.pyc | Bin 0 -> 10659 bytes .../util/__pycache__/wait.cpython-39.pyc | Bin 0 -> 3119 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 + .../Lib/site-packages/pip/_vendor/vendor.txt | 25 + .../pip/_vendor/webencodings/__init__.py | 342 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 9710 bytes .../__pycache__/labels.cpython-39.pyc | Bin 0 -> 3824 bytes .../__pycache__/mklabels.cpython-39.pyc | Bin 0 -> 1894 bytes .../__pycache__/tests.cpython-39.pyc | Bin 0 -> 5058 bytes .../__pycache__/x_user_defined.cpython-39.pyc | Bin 0 -> 2654 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 + UIKatabatic/Lib/site-packages/pip/py.typed | 4 + .../site-packages/pkg_resources/__init__.py | 3288 ++++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 100426 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 180 bytes .../__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 20497 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201334 bytes .../pkg_resources/_vendor/appdirs.py | 608 + .../_vendor/packaging/__about__.py | 27 + .../_vendor/packaging/__init__.py | 26 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 696 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 542 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 1140 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2894 bytes .../__pycache__/_typing.cpython-39.pyc | Bin 0 -> 1485 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9301 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 4078 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 20577 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 17256 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 1647 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13314 bytes .../_vendor/packaging/_compat.py | 38 + .../_vendor/packaging/_structures.py | 86 + .../_vendor/packaging/_typing.py | 48 + .../_vendor/packaging/markers.py | 328 + .../_vendor/packaging/requirements.py | 145 + .../_vendor/packaging/specifiers.py | 863 + .../pkg_resources/_vendor/packaging/tags.py | 751 + .../pkg_resources/_vendor/packaging/utils.py | 65 + .../_vendor/packaging/version.py | 535 + .../pkg_resources/_vendor/pyparsing.py | 5742 +++++++ .../pkg_resources/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2869 bytes .../__pycache__/setup.cpython-39.pyc | Bin 0 -> 308 bytes .../data/my-test-package-source/setup.py | 6 + .../setuptools-58.1.0.dist-info/INSTALLER | 1 + .../setuptools-58.1.0.dist-info/LICENSE | 19 + .../setuptools-58.1.0.dist-info/METADATA | 119 + .../setuptools-58.1.0.dist-info/RECORD | 296 + .../setuptools-58.1.0.dist-info/REQUESTED | 0 .../setuptools-58.1.0.dist-info/WHEEL | 5 + .../entry_points.txt | 56 + .../setuptools-58.1.0.dist-info/top_level.txt | 3 + .../Lib/site-packages/setuptools/__init__.py | 242 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 8529 bytes .../_deprecation_warning.cpython-39.pyc | Bin 0 -> 539 bytes .../__pycache__/_imp.cpython-39.pyc | Bin 0 -> 2074 bytes .../__pycache__/archive_util.cpython-39.pyc | Bin 0 -> 5803 bytes .../__pycache__/build_meta.cpython-39.pyc | Bin 0 -> 9062 bytes .../__pycache__/config.cpython-39.pyc | Bin 0 -> 20815 bytes .../__pycache__/dep_util.cpython-39.pyc | Bin 0 -> 846 bytes .../__pycache__/depends.cpython-39.pyc | Bin 0 -> 5238 bytes .../__pycache__/dist.cpython-39.pyc | Bin 0 -> 36436 bytes .../__pycache__/errors.cpython-39.pyc | Bin 0 -> 839 bytes .../__pycache__/extension.cpython-39.pyc | Bin 0 -> 1933 bytes .../__pycache__/glob.cpython-39.pyc | Bin 0 -> 3683 bytes .../__pycache__/installer.cpython-39.pyc | Bin 0 -> 2760 bytes .../__pycache__/launch.cpython-39.pyc | Bin 0 -> 890 bytes .../__pycache__/monkey.cpython-39.pyc | Bin 0 -> 4602 bytes .../__pycache__/msvc.cpython-39.pyc | Bin 0 -> 42828 bytes .../__pycache__/namespaces.cpython-39.pyc | Bin 0 -> 3589 bytes .../__pycache__/package_index.cpython-39.pyc | Bin 0 -> 32625 bytes .../__pycache__/py34compat.cpython-39.pyc | Bin 0 -> 469 bytes .../__pycache__/sandbox.cpython-39.pyc | Bin 0 -> 15745 bytes .../__pycache__/unicode_utils.cpython-39.pyc | Bin 0 -> 1103 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 313 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 7269 bytes .../windows_support.cpython-39.pyc | Bin 0 -> 1012 bytes .../setuptools/_deprecation_warning.py | 7 + .../setuptools/_distutils/__init__.py | 15 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 447 bytes .../__pycache__/_msvccompiler.cpython-39.pyc | Bin 0 -> 13802 bytes .../__pycache__/archive_util.cpython-39.pyc | Bin 0 -> 6634 bytes .../__pycache__/bcppcompiler.cpython-39.pyc | Bin 0 -> 6545 bytes .../__pycache__/ccompiler.cpython-39.pyc | Bin 0 -> 33413 bytes .../_distutils/__pycache__/cmd.cpython-39.pyc | Bin 0 -> 13973 bytes .../__pycache__/config.cpython-39.pyc | Bin 0 -> 3576 bytes .../__pycache__/core.cpython-39.pyc | Bin 0 -> 6701 bytes .../cygwinccompiler.cpython-39.pyc | Bin 0 -> 8781 bytes .../__pycache__/debug.cpython-39.pyc | Bin 0 -> 243 bytes .../__pycache__/dep_util.cpython-39.pyc | Bin 0 -> 2763 bytes .../__pycache__/dir_util.cpython-39.pyc | Bin 0 -> 5864 bytes .../__pycache__/dist.cpython-39.pyc | Bin 0 -> 34434 bytes .../__pycache__/errors.cpython-39.pyc | Bin 0 -> 5299 bytes .../__pycache__/extension.cpython-39.pyc | Bin 0 -> 6964 bytes .../__pycache__/fancy_getopt.cpython-39.pyc | Bin 0 -> 10672 bytes .../__pycache__/file_util.cpython-39.pyc | Bin 0 -> 6030 bytes .../__pycache__/filelist.cpython-39.pyc | Bin 0 -> 10822 bytes .../_distutils/__pycache__/log.cpython-39.pyc | Bin 0 -> 2362 bytes .../__pycache__/msvc9compiler.cpython-39.pyc | Bin 0 -> 17559 bytes .../__pycache__/msvccompiler.cpython-39.pyc | Bin 0 -> 14754 bytes .../__pycache__/py35compat.cpython-39.pyc | Bin 0 -> 619 bytes .../__pycache__/py38compat.cpython-39.pyc | Bin 0 -> 414 bytes .../__pycache__/spawn.cpython-39.pyc | Bin 0 -> 2890 bytes .../__pycache__/sysconfig.cpython-39.pyc | Bin 0 -> 12574 bytes .../__pycache__/text_file.cpython-39.pyc | Bin 0 -> 8488 bytes .../__pycache__/unixccompiler.cpython-39.pyc | Bin 0 -> 6864 bytes .../__pycache__/util.cpython-39.pyc | Bin 0 -> 14227 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 7388 bytes .../versionpredicate.cpython-39.pyc | Bin 0 -> 5172 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-39.pyc | Bin 0 -> 522 bytes .../command/__pycache__/bdist.cpython-39.pyc | Bin 0 -> 3652 bytes .../__pycache__/bdist_dumb.cpython-39.pyc | Bin 0 -> 3635 bytes .../__pycache__/bdist_msi.cpython-39.pyc | Bin 0 -> 19817 bytes .../__pycache__/bdist_rpm.cpython-39.pyc | Bin 0 -> 12272 bytes .../__pycache__/bdist_wininst.cpython-39.pyc | Bin 0 -> 8592 bytes .../command/__pycache__/build.cpython-39.pyc | Bin 0 -> 3924 bytes .../__pycache__/build_clib.cpython-39.pyc | Bin 0 -> 4847 bytes .../__pycache__/build_ext.cpython-39.pyc | Bin 0 -> 16259 bytes .../__pycache__/build_py.cpython-39.pyc | Bin 0 -> 9842 bytes .../__pycache__/build_scripts.cpython-39.pyc | Bin 0 -> 4007 bytes .../command/__pycache__/check.cpython-39.pyc | Bin 0 -> 4956 bytes .../command/__pycache__/clean.cpython-39.pyc | Bin 0 -> 2129 bytes .../command/__pycache__/config.cpython-39.pyc | Bin 0 -> 10259 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 13871 bytes .../__pycache__/install_data.cpython-39.pyc | Bin 0 -> 2332 bytes .../install_egg_info.cpython-39.pyc | Bin 0 -> 3067 bytes .../install_headers.cpython-39.pyc | Bin 0 -> 1757 bytes .../__pycache__/install_lib.cpython-39.pyc | Bin 0 -> 5129 bytes .../install_scripts.cpython-39.pyc | Bin 0 -> 2180 bytes .../__pycache__/py37compat.cpython-39.pyc | Bin 0 -> 1023 bytes .../__pycache__/register.cpython-39.pyc | Bin 0 -> 8500 bytes .../command/__pycache__/sdist.cpython-39.pyc | Bin 0 -> 14527 bytes .../command/__pycache__/upload.cpython-39.pyc | Bin 0 -> 5250 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 | 757 + .../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 | 678 + .../_distutils/command/install_data.py | 79 + .../_distutils/command/install_egg_info.py | 77 + .../_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 | 234 + .../setuptools/_distutils/cygwinccompiler.py | 414 + .../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 | 578 + .../setuptools/_distutils/text_file.py | 286 + .../setuptools/_distutils/unixccompiler.py | 332 + .../setuptools/_distutils/util.py | 535 + .../setuptools/_distutils/version.py | 347 + .../setuptools/_distutils/versionpredicate.py | 166 + .../Lib/site-packages/setuptools/_imp.py | 82 + .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 177 bytes .../__pycache__/ordered_set.cpython-39.pyc | Bin 0 -> 16371 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201331 bytes .../_vendor/more_itertools/__init__.py | 4 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 258 bytes .../__pycache__/more.cpython-39.pyc | Bin 0 -> 110003 bytes .../__pycache__/recipes.cpython-39.pyc | Bin 0 -> 17923 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 | 27 + .../setuptools/_vendor/packaging/__init__.py | 26 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 693 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 539 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 1137 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2891 bytes .../__pycache__/_typing.cpython-39.pyc | Bin 0 -> 1482 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9295 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 4072 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 20574 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 17253 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 1644 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13311 bytes .../setuptools/_vendor/packaging/_compat.py | 38 + .../_vendor/packaging/_structures.py | 86 + .../setuptools/_vendor/packaging/_typing.py | 48 + .../setuptools/_vendor/packaging/markers.py | 328 + .../_vendor/packaging/requirements.py | 145 + .../_vendor/packaging/specifiers.py | 863 + .../setuptools/_vendor/packaging/tags.py | 751 + .../setuptools/_vendor/packaging/utils.py | 65 + .../setuptools/_vendor/packaging/version.py | 535 + .../setuptools/_vendor/pyparsing.py | 5742 +++++++ .../site-packages/setuptools/archive_util.py | 205 + .../site-packages/setuptools/build_meta.py | 281 + .../Lib/site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../Lib/site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 8 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 366 bytes .../command/__pycache__/alias.cpython-39.pyc | Bin 0 -> 2360 bytes .../__pycache__/bdist_egg.cpython-39.pyc | Bin 0 -> 13026 bytes .../__pycache__/bdist_rpm.cpython-39.pyc | Bin 0 -> 1573 bytes .../__pycache__/build_clib.cpython-39.pyc | Bin 0 -> 2457 bytes .../__pycache__/build_ext.cpython-39.pyc | Bin 0 -> 9816 bytes .../__pycache__/build_py.cpython-39.pyc | Bin 0 -> 7807 bytes .../__pycache__/develop.cpython-39.pyc | Bin 0 -> 6126 bytes .../__pycache__/dist_info.cpython-39.pyc | Bin 0 -> 1384 bytes .../__pycache__/easy_install.cpython-39.pyc | Bin 0 -> 63577 bytes .../__pycache__/egg_info.cpython-39.pyc | Bin 0 -> 21967 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 4025 bytes .../install_egg_info.cpython-39.pyc | Bin 0 -> 2416 bytes .../__pycache__/install_lib.cpython-39.pyc | Bin 0 -> 4123 bytes .../install_scripts.cpython-39.pyc | Bin 0 -> 2411 bytes .../__pycache__/py36compat.cpython-39.pyc | Bin 0 -> 4578 bytes .../__pycache__/register.cpython-39.pyc | Bin 0 -> 834 bytes .../command/__pycache__/rotate.cpython-39.pyc | Bin 0 -> 2493 bytes .../__pycache__/saveopts.cpython-39.pyc | Bin 0 -> 912 bytes .../command/__pycache__/sdist.cpython-39.pyc | Bin 0 -> 6453 bytes .../command/__pycache__/setopt.cpython-39.pyc | Bin 0 -> 4663 bytes .../command/__pycache__/test.cpython-39.pyc | Bin 0 -> 8018 bytes .../command/__pycache__/upload.cpython-39.pyc | Bin 0 -> 807 bytes .../__pycache__/upload_docs.cpython-39.pyc | Bin 0 -> 6150 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 | 232 + .../setuptools/command/develop.py | 193 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2290 +++ .../setuptools/command/egg_info.py | 734 + .../setuptools/command/install.py | 125 + .../setuptools/command/install_egg_info.py | 62 + .../setuptools/command/install_lib.py | 122 + .../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 | 189 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 252 + .../setuptools/command/upload.py | 17 + .../setuptools/command/upload_docs.py | 202 + .../Lib/site-packages/setuptools/config.py | 749 + .../Lib/site-packages/setuptools/dep_util.py | 25 + .../Lib/site-packages/setuptools/depends.py | 175 + .../Lib/site-packages/setuptools/dist.py | 1150 ++ .../Lib/site-packages/setuptools/errors.py | 16 + .../Lib/site-packages/setuptools/extension.py | 55 + .../setuptools/extern/__init__.py | 73 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2908 bytes .../Lib/site-packages/setuptools/glob.py | 167 + .../Lib/site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../Lib/site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/installer.py | 97 + .../Lib/site-packages/setuptools/launch.py | 36 + .../Lib/site-packages/setuptools/monkey.py | 177 + .../Lib/site-packages/setuptools/msvc.py | 1805 +++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1119 ++ .../site-packages/setuptools/py34compat.py | 13 + .../Lib/site-packages/setuptools/sandbox.py | 530 + .../setuptools/script (dev).tmpl | 6 + .../Lib/site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/unicode_utils.py | 42 + .../Lib/site-packages/setuptools/version.py | 6 + .../Lib/site-packages/setuptools/wheel.py | 213 + .../setuptools/windows_support.py | 29 + .../werkzeug-3.1.3.dist-info/INSTALLER | 1 + .../werkzeug-3.1.3.dist-info/LICENSE.txt | 28 + .../werkzeug-3.1.3.dist-info/METADATA | 99 + .../werkzeug-3.1.3.dist-info/RECORD | 116 + .../werkzeug-3.1.3.dist-info/WHEEL | 4 + .../Lib/site-packages/werkzeug/__init__.py | 4 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 315 bytes .../__pycache__/_internal.cpython-39.pyc | Bin 0 -> 6771 bytes .../__pycache__/_reloader.cpython-39.pyc | Bin 0 -> 12664 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 28051 bytes .../__pycache__/formparser.cpython-39.pyc | Bin 0 -> 12391 bytes .../werkzeug/__pycache__/http.cpython-39.pyc | Bin 0 -> 38235 bytes .../werkzeug/__pycache__/local.cpython-39.pyc | Bin 0 -> 20598 bytes .../__pycache__/security.cpython-39.pyc | Bin 0 -> 5392 bytes .../__pycache__/serving.cpython-39.pyc | Bin 0 -> 29870 bytes .../werkzeug/__pycache__/test.cpython-39.pyc | Bin 0 -> 42240 bytes .../__pycache__/testapp.cpython-39.pyc | Bin 0 -> 6551 bytes .../werkzeug/__pycache__/urls.cpython-39.pyc | Bin 0 -> 5728 bytes .../__pycache__/user_agent.cpython-39.pyc | Bin 0 -> 1826 bytes .../werkzeug/__pycache__/utils.cpython-39.pyc | Bin 0 -> 21969 bytes .../werkzeug/__pycache__/wsgi.cpython-39.pyc | Bin 0 -> 19588 bytes .../Lib/site-packages/werkzeug/_internal.py | 211 + .../Lib/site-packages/werkzeug/_reloader.py | 471 + .../werkzeug/datastructures/__init__.py | 64 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2211 bytes .../__pycache__/accept.cpython-39.pyc | Bin 0 -> 12278 bytes .../__pycache__/auth.cpython-39.pyc | Bin 0 -> 10439 bytes .../__pycache__/cache_control.cpython-39.pyc | Bin 0 -> 10141 bytes .../__pycache__/csp.cpython-39.pyc | Bin 0 -> 4834 bytes .../__pycache__/etag.cpython-39.pyc | Bin 0 -> 4222 bytes .../__pycache__/file_storage.cpython-39.pyc | Bin 0 -> 6601 bytes .../__pycache__/headers.cpython-39.pyc | Bin 0 -> 22799 bytes .../__pycache__/mixins.cpython-39.pyc | Bin 0 -> 13335 bytes .../__pycache__/range.cpython-39.pyc | Bin 0 -> 7361 bytes .../__pycache__/structures.cpython-39.pyc | Bin 0 -> 44052 bytes .../werkzeug/datastructures/accept.py | 350 + .../werkzeug/datastructures/auth.py | 317 + .../werkzeug/datastructures/cache_control.py | 273 + .../werkzeug/datastructures/csp.py | 100 + .../werkzeug/datastructures/etag.py | 106 + .../werkzeug/datastructures/file_storage.py | 209 + .../werkzeug/datastructures/headers.py | 662 + .../werkzeug/datastructures/mixins.py | 317 + .../werkzeug/datastructures/range.py | 214 + .../werkzeug/datastructures/structures.py | 1239 ++ .../site-packages/werkzeug/debug/__init__.py | 565 + .../debug/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 14704 bytes .../debug/__pycache__/console.cpython-39.pyc | Bin 0 -> 8111 bytes .../debug/__pycache__/repr.cpython-39.pyc | Bin 0 -> 8805 bytes .../debug/__pycache__/tbtools.cpython-39.pyc | Bin 0 -> 11638 bytes .../site-packages/werkzeug/debug/console.py | 219 + .../Lib/site-packages/werkzeug/debug/repr.py | 282 + .../werkzeug/debug/shared/ICON_LICENSE.md | 6 + .../werkzeug/debug/shared/console.png | Bin 0 -> 507 bytes .../werkzeug/debug/shared/debugger.js | 344 + .../werkzeug/debug/shared/less.png | Bin 0 -> 191 bytes .../werkzeug/debug/shared/more.png | Bin 0 -> 200 bytes .../werkzeug/debug/shared/style.css | 150 + .../site-packages/werkzeug/debug/tbtools.py | 450 + .../Lib/site-packages/werkzeug/exceptions.py | 894 ++ .../Lib/site-packages/werkzeug/formparser.py | 430 + .../Lib/site-packages/werkzeug/http.py | 1405 ++ .../Lib/site-packages/werkzeug/local.py | 653 + .../werkzeug/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 178 bytes .../__pycache__/dispatcher.cpython-39.pyc | Bin 0 -> 2774 bytes .../__pycache__/http_proxy.cpython-39.pyc | Bin 0 -> 6797 bytes .../__pycache__/lint.cpython-39.pyc | Bin 0 -> 12790 bytes .../__pycache__/profiler.cpython-39.pyc | Bin 0 -> 5532 bytes .../__pycache__/proxy_fix.cpython-39.pyc | Bin 0 -> 5930 bytes .../__pycache__/shared_data.cpython-39.pyc | Bin 0 -> 9137 bytes .../werkzeug/middleware/dispatcher.py | 81 + .../werkzeug/middleware/http_proxy.py | 236 + .../site-packages/werkzeug/middleware/lint.py | 439 + .../werkzeug/middleware/profiler.py | 155 + .../werkzeug/middleware/proxy_fix.py | 183 + .../werkzeug/middleware/shared_data.py | 283 + .../Lib/site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 134 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 4616 bytes .../__pycache__/converters.cpython-39.pyc | Bin 0 -> 8908 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 5508 bytes .../routing/__pycache__/map.cpython-39.pyc | Bin 0 -> 30628 bytes .../__pycache__/matcher.cpython-39.pyc | Bin 0 -> 5073 bytes .../routing/__pycache__/rules.cpython-39.pyc | Bin 0 -> 27697 bytes .../werkzeug/routing/converters.py | 261 + .../werkzeug/routing/exceptions.py | 152 + .../Lib/site-packages/werkzeug/routing/map.py | 951 ++ .../site-packages/werkzeug/routing/matcher.py | 202 + .../site-packages/werkzeug/routing/rules.py | 928 ++ .../site-packages/werkzeug/sansio/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 174 bytes .../sansio/__pycache__/http.cpython-39.pyc | Bin 0 -> 4030 bytes .../__pycache__/multipart.cpython-39.pyc | Bin 0 -> 7457 bytes .../sansio/__pycache__/request.cpython-39.pyc | Bin 0 -> 17253 bytes .../__pycache__/response.cpython-39.pyc | Bin 0 -> 24585 bytes .../sansio/__pycache__/utils.cpython-39.pyc | Bin 0 -> 4625 bytes .../Lib/site-packages/werkzeug/sansio/http.py | 170 + .../werkzeug/sansio/multipart.py | 323 + .../site-packages/werkzeug/sansio/request.py | 534 + .../site-packages/werkzeug/sansio/response.py | 763 + .../site-packages/werkzeug/sansio/utils.py | 167 + .../Lib/site-packages/werkzeug/security.py | 166 + .../Lib/site-packages/werkzeug/serving.py | 1125 ++ .../Lib/site-packages/werkzeug/test.py | 1464 ++ .../Lib/site-packages/werkzeug/testapp.py | 194 + .../Lib/site-packages/werkzeug/urls.py | 203 + .../Lib/site-packages/werkzeug/user_agent.py | 47 + .../Lib/site-packages/werkzeug/utils.py | 691 + .../werkzeug/wrappers/__init__.py | 3 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 293 bytes .../__pycache__/request.cpython-39.pyc | Bin 0 -> 21443 bytes .../__pycache__/response.cpython-39.pyc | Bin 0 -> 27932 bytes .../werkzeug/wrappers/request.py | 650 + .../werkzeug/wrappers/response.py | 831 + .../Lib/site-packages/werkzeug/wsgi.py | 595 + .../zipp-3.21.0.dist-info/INSTALLER | 1 + .../zipp-3.21.0.dist-info/LICENSE | 17 + .../zipp-3.21.0.dist-info/METADATA | 106 + .../zipp-3.21.0.dist-info/RECORD | 18 + .../site-packages/zipp-3.21.0.dist-info/WHEEL | 5 + .../zipp-3.21.0.dist-info/top_level.txt | 1 + .../Lib/site-packages/zipp/__init__.py | 455 + .../zipp/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 14505 bytes .../__pycache__/_functools.cpython-39.pyc | Bin 0 -> 769 bytes .../zipp/__pycache__/glob.cpython-39.pyc | Bin 0 -> 4227 bytes .../Lib/site-packages/zipp/_functools.py | 20 + .../Lib/site-packages/zipp/compat/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 170 bytes .../compat/__pycache__/overlay.cpython-39.pyc | Bin 0 -> 1143 bytes .../compat/__pycache__/py310.cpython-39.pyc | Bin 0 -> 407 bytes .../Lib/site-packages/zipp/compat/overlay.py | 37 + .../Lib/site-packages/zipp/compat/py310.py | 13 + UIKatabatic/Lib/site-packages/zipp/glob.py | 113 + UIKatabatic/Scripts/Activate.ps1 | 437 + UIKatabatic/Scripts/activate | 66 + UIKatabatic/Scripts/activate.bat | 33 + UIKatabatic/Scripts/deactivate.bat | 21 + UIKatabatic/Scripts/flask.exe | Bin 0 -> 106354 bytes UIKatabatic/Scripts/pip.exe | Bin 0 -> 106367 bytes UIKatabatic/Scripts/pip3.9.exe | Bin 0 -> 106367 bytes UIKatabatic/Scripts/pip3.exe | Bin 0 -> 106367 bytes UIKatabatic/Scripts/python.exe | Bin 0 -> 599032 bytes UIKatabatic/Scripts/pythonw.exe | Bin 0 -> 598520 bytes UIKatabatic/pyvenv.cfg | 3 + Website | 1 + path/to/save/synthetic_data.csv | 584 + uploads/indian_liver_patient.csv | 584 + uploads/nursery.csv | 12961 ++++++++++++++++ uploads/synthetic_data (5).csv | 12961 ++++++++++++++++ uploads/synthetic_data.csv | 12961 ++++++++++++++++ 1759 files changed, 355151 insertions(+) create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt create mode 100644 UIKatabatic/Lib/site-packages/_distutils_hack/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/_distutils_hack/override.py create mode 100644 UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/blinker/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/blinker/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/blinker/__pycache__/_utilities.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/blinker/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/blinker/_utilities.py create mode 100644 UIKatabatic/Lib/site-packages/blinker/base.py create mode 100644 UIKatabatic/Lib/site-packages/blinker/py.typed create mode 100644 UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/click/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/_compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/_termui_impl.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/_textwrap.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/_winconsole.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/core.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/decorators.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/formatting.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/globals.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/shell_completion.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/termui.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/testing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/types.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/click/_compat.py create mode 100644 UIKatabatic/Lib/site-packages/click/_termui_impl.py create mode 100644 UIKatabatic/Lib/site-packages/click/_textwrap.py create mode 100644 UIKatabatic/Lib/site-packages/click/_winconsole.py create mode 100644 UIKatabatic/Lib/site-packages/click/core.py create mode 100644 UIKatabatic/Lib/site-packages/click/decorators.py create mode 100644 UIKatabatic/Lib/site-packages/click/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/click/formatting.py create mode 100644 UIKatabatic/Lib/site-packages/click/globals.py create mode 100644 UIKatabatic/Lib/site-packages/click/parser.py create mode 100644 UIKatabatic/Lib/site-packages/click/py.typed create mode 100644 UIKatabatic/Lib/site-packages/click/shell_completion.py create mode 100644 UIKatabatic/Lib/site-packages/click/termui.py create mode 100644 UIKatabatic/Lib/site-packages/click/testing.py create mode 100644 UIKatabatic/Lib/site-packages/click/types.py create mode 100644 UIKatabatic/Lib/site-packages/click/utils.py create mode 100644 UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/colorama/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/ansi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/initialise.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/win32.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/__pycache__/winterm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/ansi.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/ansitowin32.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/initialise.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/ansi_test.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/ansitowin32_test.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/initialise_test.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/isatty_test.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/utils.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/tests/winterm_test.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/win32.py create mode 100644 UIKatabatic/Lib/site-packages/colorama/winterm.py create mode 100644 UIKatabatic/Lib/site-packages/distutils-precedence.pth create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/REQUESTED create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/entry_points.txt create mode 100644 UIKatabatic/Lib/site-packages/flask/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/flask/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/app.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/blueprints.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/cli.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/config.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/ctx.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/debughelpers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/globals.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/helpers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/logging.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/sessions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/signals.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/templating.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/testing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/typing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/views.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/__pycache__/wrappers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/app.py create mode 100644 UIKatabatic/Lib/site-packages/flask/blueprints.py create mode 100644 UIKatabatic/Lib/site-packages/flask/cli.py create mode 100644 UIKatabatic/Lib/site-packages/flask/config.py create mode 100644 UIKatabatic/Lib/site-packages/flask/ctx.py create mode 100644 UIKatabatic/Lib/site-packages/flask/debughelpers.py create mode 100644 UIKatabatic/Lib/site-packages/flask/globals.py create mode 100644 UIKatabatic/Lib/site-packages/flask/helpers.py create mode 100644 UIKatabatic/Lib/site-packages/flask/json/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/flask/json/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/json/__pycache__/provider.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/json/__pycache__/tag.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/json/provider.py create mode 100644 UIKatabatic/Lib/site-packages/flask/json/tag.py create mode 100644 UIKatabatic/Lib/site-packages/flask/logging.py create mode 100644 UIKatabatic/Lib/site-packages/flask/py.typed create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/README.md create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/app.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/scaffold.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/app.py create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/blueprints.py create mode 100644 UIKatabatic/Lib/site-packages/flask/sansio/scaffold.py create mode 100644 UIKatabatic/Lib/site-packages/flask/sessions.py create mode 100644 UIKatabatic/Lib/site-packages/flask/signals.py create mode 100644 UIKatabatic/Lib/site-packages/flask/templating.py create mode 100644 UIKatabatic/Lib/site-packages/flask/testing.py create mode 100644 UIKatabatic/Lib/site-packages/flask/typing.py create mode 100644 UIKatabatic/Lib/site-packages/flask/views.py create mode 100644 UIKatabatic/Lib/site-packages/flask/wrappers.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/LICENSE create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/top_level.txt create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_adapters.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_collections.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_functools.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_itertools.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_meta.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_text.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/diagnose.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_adapters.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_collections.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_compat.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_functools.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_itertools.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_meta.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/_text.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py311.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py39.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/py311.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/compat/py39.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/diagnose.py create mode 100644 UIKatabatic/Lib/site-packages/importlib_metadata/py.typed create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/_json.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/encoding.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/serializer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/signer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/url_safe.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/_json.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/encoding.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/exc.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/py.typed create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/serializer.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/signer.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/timed.py create mode 100644 UIKatabatic/Lib/site-packages/itsdangerous/url_safe.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt create mode 100644 UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/bccache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/compiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/constants.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/debug.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/defaults.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/environment.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/ext.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/filters.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/lexer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/loaders.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/meta.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/nodes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/runtime.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/sandbox.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/tests.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/__pycache__/visitor.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/jinja2/_identifier.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/async_utils.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/bccache.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/compiler.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/constants.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/debug.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/defaults.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/environment.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/ext.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/filters.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/idtracking.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/lexer.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/loaders.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/meta.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/nativetypes.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/nodes.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/optimizer.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/parser.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/py.typed create mode 100644 UIKatabatic/Lib/site-packages/jinja2/runtime.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/sandbox.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/tests.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/utils.py create mode 100644 UIKatabatic/Lib/site-packages/jinja2/visitor.py create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/__pycache__/_native.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/_native.py create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/_speedups.c create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/_speedups.cp39-win_amd64.pyd create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/_speedups.pyi create mode 100644 UIKatabatic/Lib/site-packages/markupsafe/py.typed create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/REQUESTED create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/entry_points.txt create mode 100644 UIKatabatic/Lib/site-packages/pip-22.0.4.dist-info/top_level.txt create mode 100644 UIKatabatic/Lib/site-packages/pip/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/build_env.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/command_context.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/main.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/req_command.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/spinners.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/debug.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/index.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/configuration.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/installed.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/sdist.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/distributions/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/collector.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/package_finder.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/index/sources.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/_distutils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/locations/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/main.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/direct_url.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/index.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/link.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/scheme.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/search_scope.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/target_python.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/models/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/auth.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/download.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/session.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/req_tracker.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/self_outdated_check.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/_log.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/datetime.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/distutils_args.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/egg_link.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/filetypes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/models.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/subprocess.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/unpacking.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/urls.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/utils/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_internal/wheel_builder.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/__pycache__/distro.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/enums.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/chardet/version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/win32.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/distro.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/_utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/constants.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/html5parser.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/serializer.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/_version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/tags.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/build.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/check.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/colorlog.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/dirtools.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/envbuild.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/in_process/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/in_process/_in_process.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/meta.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pep517/wrappers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__pycache__/bar.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__pycache__/colors.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__pycache__/counter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/bar.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/colors.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/counter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/progress/spinner.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/console.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/filter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/style.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/token.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pygments/util.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/actions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/common.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/core.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/helpers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/results.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/testing.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/unicode.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/pyparsing/util.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__main__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_lru_cache.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/tabulate.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_extension.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_loop.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_lru_cache.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_pick.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_stack.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_timer.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_windows.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/abc.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/align.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/ansi.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/bar.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/box.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/cells.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/color.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/columns.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/console.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/constrain.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/containers.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/control.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/emoji.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/errors.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/filesize.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/json.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/layout.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/live.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/live_render.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/logging.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/markup.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/measure.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/padding.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/pager.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/palette.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/panel.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/pretty.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/progress.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/prompt.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/protocol.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/region.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/repr.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/rule.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/scope.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/screen.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/segment.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/spinner.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/status.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/style.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/styled.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/syntax.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/table.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/tabulate.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/text.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/theme.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/themes.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/traceback.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/rich/tree.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/six.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/_utils.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/after.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/before.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/nap.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/retry.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/stop.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tenacity/wait.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/tomli/_re.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/typing_extensions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/vendor.txt create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 UIKatabatic/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 UIKatabatic/Lib/site-packages/pip/py.typed create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_typing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/_compat.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/_typing.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/tags.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/extern/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/tests/data/my-test-package-source/__pycache__/setup.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/LICENSE create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/REQUESTED create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/entry_points.txt create mode 100644 UIKatabatic/Lib/site-packages/setuptools-58.1.0.dist-info/top_level.txt create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/sandbox.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_deprecation_warning.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/core.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/debug.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/extension.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/py35compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/util.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/_msvccompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/archive_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/bcppcompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/ccompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/cmd.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/bdist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/build.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/build_clib.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/build_ext.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/build_py.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/build_scripts.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/check.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/clean.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/config.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install_data.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install_headers.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install_lib.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/install_scripts.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/py37compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/register.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/sdist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/command/upload.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/config.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/core.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/debug.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/dep_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/dir_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/dist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/errors.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/extension.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/fancy_getopt.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/file_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/filelist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/log.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/msvc9compiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/msvccompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/py35compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/py38compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/spawn.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/sysconfig.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/text_file.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/unixccompiler.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/version.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_distutils/versionpredicate.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_imp.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/more.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/ordered_set.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_typing.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/_compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/_typing.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/tags.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/archive_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/build_meta.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/cli-32.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/cli-64.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/cli.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/build_clib.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/build_ext.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/build_py.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/develop.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/dist_info.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/easy_install.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/egg_info.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/install.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/install_lib.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/install_scripts.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/py36compat.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/register.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/rotate.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/saveopts.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/sdist.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/setopt.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/upload.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/__pycache__/upload_docs.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/alias.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/bdist_egg.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/bdist_rpm.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/build_clib.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/build_ext.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/build_py.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/develop.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/dist_info.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/easy_install.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/egg_info.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/install.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/install_egg_info.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/install_lib.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/install_scripts.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/launcher manifest.xml create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/py36compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/register.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/rotate.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/saveopts.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/sdist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/setopt.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/test.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/upload.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/command/upload_docs.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/config.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/dep_util.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/depends.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/dist.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/errors.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/extension.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/extern/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/setuptools/glob.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/gui-32.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/gui-64.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/gui.exe create mode 100644 UIKatabatic/Lib/site-packages/setuptools/installer.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/launch.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/monkey.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/msvc.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/namespaces.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/package_index.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/py34compat.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/sandbox.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/script (dev).tmpl create mode 100644 UIKatabatic/Lib/site-packages/setuptools/script.tmpl create mode 100644 UIKatabatic/Lib/site-packages/setuptools/unicode_utils.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/version.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/wheel.py create mode 100644 UIKatabatic/Lib/site-packages/setuptools/windows_support.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug-3.1.3.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/werkzeug-3.1.3.dist-info/LICENSE.txt create mode 100644 UIKatabatic/Lib/site-packages/werkzeug-3.1.3.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/werkzeug-3.1.3.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/werkzeug-3.1.3.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/http.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/local.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/security.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/serving.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/test.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/urls.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/_internal.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/_reloader.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/accept.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/auth.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/cache_control.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/csp.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/etag.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/file_storage.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/headers.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/mixins.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/range.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/datastructures/structures.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/console.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/repr.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/console.png create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/debugger.js create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/less.png create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/more.png create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/shared/style.css create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/debug/tbtools.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/formparser.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/http.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/local.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/dispatcher.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/http_proxy.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/lint.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/profiler.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/proxy_fix.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/middleware/shared_data.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/py.typed create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/converters.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/exceptions.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/map.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/matcher.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/routing/rules.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/http.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/multipart.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/request.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/response.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/sansio/utils.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/security.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/serving.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/test.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/testapp.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/urls.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/user_agent.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/utils.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/request.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wrappers/response.py create mode 100644 UIKatabatic/Lib/site-packages/werkzeug/wsgi.py create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/INSTALLER create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/LICENSE create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/METADATA create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/RECORD create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/WHEEL create mode 100644 UIKatabatic/Lib/site-packages/zipp-3.21.0.dist-info/top_level.txt create mode 100644 UIKatabatic/Lib/site-packages/zipp/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/zipp/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/__pycache__/_functools.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/__pycache__/glob.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/_functools.py create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/__init__.py create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/__pycache__/__init__.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/__pycache__/overlay.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/__pycache__/py310.cpython-39.pyc create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/overlay.py create mode 100644 UIKatabatic/Lib/site-packages/zipp/compat/py310.py create mode 100644 UIKatabatic/Lib/site-packages/zipp/glob.py create mode 100644 UIKatabatic/Scripts/Activate.ps1 create mode 100644 UIKatabatic/Scripts/activate create mode 100644 UIKatabatic/Scripts/activate.bat create mode 100644 UIKatabatic/Scripts/deactivate.bat create mode 100644 UIKatabatic/Scripts/flask.exe create mode 100644 UIKatabatic/Scripts/pip.exe create mode 100644 UIKatabatic/Scripts/pip3.9.exe create mode 100644 UIKatabatic/Scripts/pip3.exe create mode 100644 UIKatabatic/Scripts/python.exe create mode 100644 UIKatabatic/Scripts/pythonw.exe create mode 100644 UIKatabatic/pyvenv.cfg create mode 160000 Website create mode 100644 path/to/save/synthetic_data.csv create mode 100644 uploads/indian_liver_patient.csv create mode 100644 uploads/nursery.csv create mode 100644 uploads/synthetic_data (5).csv create mode 100644 uploads/synthetic_data.csv diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA new file mode 100644 index 00000000..82261f2a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA @@ -0,0 +1,92 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 3.0.2 +Summary: Safely add untrusted strings to HTML/XML markup. +Maintainer-email: Pallets +License: 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. + +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, https://github.com/pallets/markupsafe/ +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 +Classifier: Typing :: Typed +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +License-File: LICENSE.txt + +# 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. + + +## Examples + +```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 diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD new file mode 100644 index 00000000..02df9a5b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD @@ -0,0 +1,14 @@ +MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=RjHsDbX9kKVH4zaBcmTGeYIUM4FG-KyUtKV_lu6MnsQ,1503 +MarkupSafe-3.0.2.dist-info/METADATA,sha256=nhoabjupBG41j_JxPCJ3ylgrZ6Fx8oMCFbiLF9Kafqc,4067 +MarkupSafe-3.0.2.dist-info/RECORD,, +MarkupSafe-3.0.2.dist-info/WHEEL,sha256=UAgGEIlEKluxCX20ppULf3M0rfG_1DUMdncOI_parX8,99 +MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=pREerPwvinB62tNCMOwqxBS2YHV6R52Wcq1d-rB4Z5o,13609 +markupsafe/__pycache__/__init__.cpython-39.pyc,, +markupsafe/__pycache__/_native.cpython-39.pyc,, +markupsafe/_native.py,sha256=2ptkJ40yCcp9kq3L1NqpgjfpZB-obniYKFFKUOkHh4Q,218 +markupsafe/_speedups.c,sha256=SglUjn40ti9YgQAO--OgkSyv9tXq9vvaHyVhQows4Ok,4353 +markupsafe/_speedups.cp39-win_amd64.pyd,sha256=Js1kySYtXhpjeY5zTOELmQOkMGIfUg9KECXjFaqbtZQ,13312 +markupsafe/_speedups.pyi,sha256=LSDmXYOefH4HVpAXuL8sl7AttLw0oXh1njVoVZp2wqQ,42 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL new file mode 100644 index 00000000..ed6931f5 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.2.0) +Root-Is-Purelib: false +Tag: cp39-cp39-win_amd64 + diff --git a/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/UIKatabatic/Lib/site-packages/_distutils_hack/__init__.py b/UIKatabatic/Lib/site-packages/_distutils_hack/__init__.py new file mode 100644 index 00000000..5f40996a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/_distutils_hack/__init__.py @@ -0,0 +1,128 @@ +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() + distutils = importlib.import_module('setuptools._distutils') + distutils.__name__ = 'distutils' + sys.modules['distutils'] = distutils + + # sanity 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/UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7553145d8360f6e0ca49c098c372546db12ebf55 GIT binary patch literal 5094 zcmbtYO>^7E8Qujz3Zf)hmYqz}Hd8cC(r{{1v6D0(qbeVkle)3#G_sQ^M;RF8E=5Qn zK<|Q5#7dXSGfgg?<{wxyz2w@TgKK9xlXGu5Bz@im36hfIPNtA{fn6+ipMBrw{a6M| zOBIHz`r^O0yH&>iMUCmJgvPrl`tPU&6Fg$g{LY))w5_IP?sn5QccTKw?M@jP1pDP2mJ%z&&uI;oG3Z`dHpw@2z5G0!$@zn zs3rSKwu4lPHhnaG*=Srx(REaUr)-Dsaa9#;lckpO(6)uO%amt&oJS>LpKxpk?`uvY zn=clsS>MuJ-_D^5jyYo+V+h`UpuMoyPZR)nE!hD`Z&Rj&ewrkazU;LI>F9kJZ%@7P zf=DNxlKm)XOYNmy>D@2ZyYKZ9F^HrW#@>B>pzC>4->-XjyP@`a!GRaaKzM254Pqg6 zsDc)Tw`4ci3lpWiM0rvvJmHJP3-*!_gS%2=O05SH!1BIh9sy5PAi^|E;vj-N4!oCTeY@_(N$Lf$C-KUF8+}&8(y>?t zz+SK`y&qd7h%nPx(H2PSwQ^=dG}+upHrZUL4O_CsJ*hO%_+i{hGIu{vF*d0)hn~J+ zY7tsA)pwiM-`={XF?uVOGU{(_NWGgT{jGa9@&8c(+(8<)w{C^4Egh!vN3uqimw+U!dB?3ZGx3`5(bW9P$%OIfwjf>wyD%;lqVOCR?qVm03z=rCyM>yVR(^ zk~wkElM~^qB}|!B)*_fvJL&b;UqJgmC~SDC4RWiA2!=IlWU~Hm$}Q;Q)tiVgJj~MTu0GQqaukvvIK_~ zERwpgcP;W5!*?nkuJ@uS*@wwQFeI?hOFC2b)jEJ-?S(3dd*Fn(7pRboqi()zKC^k_ z?!Axi-nnyY)4#WQ!{4~MdH3Gko3}QzvQ9-5wz86uM9t2u1k@i*mD$@et?{h1-woT{ z)7!=(Guxb@-TQc(vSY?sYPNa;dI{^0`Su}8ot=`f*77%Sm`7ZI z20P_Frq}-fTI`gM`CmW~h@{l`?x~6Is82MSGqPGRrrw6%%qo)swK=1RY(Dp`wDqO@ z(a-HYLu?>I`Tm3l)Yl0k^wli0LgvuCrv>tK?%I4K%E^*fvF8yT$}mwByTTQ*az;*Q zLo73NIA&@kEZS9o2GsJ_Uh_(n05y($gH=D@EEL4M7)}N_tn>~zH!MsVhj=O%Byc(yY|+buf1~B zOok|h2m|llOVV%;J}!xK1~zK8VTSQaX75wNGv;Khc0nXQK~$lTYmkK|Q)F{x2u;0+ zr!xYx(fKZlzJ^LNN->aLRD>n$ha3rpBT5MVjwp*c+)J`7TrvL;UadK2gt?Gi*cgZ0 z+cFJ42od#EqiyJnDd{2%l-68F(XXL8L;^G5YLTcY_zvr^5Tre3|KNY)M@|YlA0njz z0(NX4l@3eCdE6gf(0$qVAtV3Kok0{4%Z|?Mh$vt@BSD}QzTu72vYH6YU5kQVO9bl; zj8+#>4Obttp?U}V@@e^LmzRGDn=br8Cp=2>8)vNdFgo|G^+IrU-}s zI>CKoj9HPbPs#OM0VdbpJ-jw?&$Sk9^)?MA0>NlT5e31e9<G>NJqq&v*RoC}|-(&s-S`y^q`k1J7e%R_Z9k&diCz_)HQu zzqT!7`9)u?Cxn2YI9B%ivWQW)T>7v~KBgPV=QD^%h_qczc063pF#!?h z>@yaxI5lKqfnIHt;PidUGjVdcE*`qA;4mB#D2GKy?px-nei*6ww zYyckOgOQiDki0B%MVVS{C7=5lJgak5nSe}*PIi$@C=KIr#G#x|E80g^#fc)7s`wRQ zWn=V%6O!i7@}Cy+Y?%&@dGh=MJ-tX3Da_zEf-*23i{4$!gX%hIO4IkCVE$)U>@v5w W^}SPam)&{Sbr;;l>XowXI{yW_YXN@% literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc b/UIKatabatic/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2322ab655e4f88fde62d2650e7458a71927b6b01 GIT binary patch literal 225 zcmYe~<>g`k0zTDe={i9AF^Gcsl_p9 d7V5)H*DI*J#bJ}1pHiBWYR3q)=Q9v9006`kKtuol literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/_distutils_hack/override.py b/UIKatabatic/Lib/site-packages/_distutils_hack/override.py new file mode 100644 index 00000000..2cc433a4 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/_distutils_hack/override.py @@ -0,0 +1 @@ +__import__('_distutils_hack').do_override() diff --git a/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..79c9825a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2010 Jason Kirtland + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/METADATA b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/METADATA new file mode 100644 index 00000000..6d343f57 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.3 +Name: blinker +Version: 1.9.0 +Summary: Fast, simple object-to-object and broadcast signaling +Author: Jason Kirtland +Maintainer-email: Pallets Ecosystem +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://blinker.readthedocs.io +Project-URL: Source, https://github.com/pallets-eco/blinker/ + +# Blinker + +Blinker provides a fast dispatching system that allows any number of +interested parties to subscribe to events, or "signals". + + +## Pallets Community Ecosystem + +> [!IMPORTANT]\ +> This project is part of the Pallets Community Ecosystem. Pallets is the open +> source organization that maintains Flask; Pallets-Eco enables community +> maintenance of related projects. If you are interested in helping maintain +> this project, please reach out on [the Pallets Discord server][discord]. +> +> [discord]: https://discord.gg/pallets + + +## Example + +Signal receivers can subscribe to specific senders or receive signals +sent by any sender. + +```pycon +>>> from blinker import signal +>>> started = signal('round-started') +>>> def each(round): +... print(f"Round {round}") +... +>>> started.connect(each) + +>>> def round_two(round): +... print("This is round two.") +... +>>> started.connect(round_two, sender=2) + +>>> for round in range(1, 4): +... started.send(round) +... +Round 1! +Round 2! +This is round two. +Round 3! +``` + diff --git a/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/RECORD b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/RECORD new file mode 100644 index 00000000..fed260cf --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/RECORD @@ -0,0 +1,12 @@ +blinker-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +blinker-1.9.0.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 +blinker-1.9.0.dist-info/METADATA,sha256=uIRiM8wjjbHkCtbCyTvctU37IAZk0kEe5kxAld1dvzA,1633 +blinker-1.9.0.dist-info/RECORD,, +blinker-1.9.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 +blinker/__init__.py,sha256=I2EdZqpy4LyjX17Hn1yzJGWCjeLaVaPzsMgHkLfj_cQ,317 +blinker/__pycache__/__init__.cpython-39.pyc,, +blinker/__pycache__/_utilities.cpython-39.pyc,, +blinker/__pycache__/base.cpython-39.pyc,, +blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675 +blinker/base.py,sha256=QpDuvXXcwJF49lUBcH5BiST46Rz9wSG7VW_p7N_027M,19132 +blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL new file mode 100644 index 00000000..e3c6feef --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.10.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/blinker/__init__.py b/UIKatabatic/Lib/site-packages/blinker/__init__.py new file mode 100644 index 00000000..1772fa4a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker/__init__.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from .base import ANY +from .base import default_namespace +from .base import NamedSignal +from .base import Namespace +from .base import Signal +from .base import signal + +__all__ = [ + "ANY", + "default_namespace", + "NamedSignal", + "Namespace", + "Signal", + "signal", +] diff --git a/UIKatabatic/Lib/site-packages/blinker/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/blinker/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4edd309c8a6b8fb0d58067f244d0c2b3e04c521 GIT binary patch literal 464 zcmaKo%Sr<=6o!+zWG-z5Uqa|Y#jU6)x{*pZr3*tKW}0*un#l~4%)-}k=PS)t5c&$P zJQ=aLG6{da|0Fp{j+o7I1nuJFv%JO#eR%V?1z>Iw!uAC~B8fGsF~u0kK!!S~LmG}8 z0Y@|%IR=htJTd_$l#HAJCo~y31x{&-QHf;shG{1A6`D`>a0{B_VIquaoN!fR>>l3b zW8vNM8Kz^YwxZXL8&NCUijDI7mtf?oDvi)!GjD&_$RSMZ&j!*(kg|)t5HE?B)Jq1k zoaaN%`L=g`r#SC?4Th)?R{ei&NH`Z-bN-IHnNQ~BYjJAq-hEiiONu^tsxkALnw-aQ+4$~_OZLy zDyKt2x=MZEE99YljKn9}S0p690#D4WFYT2U-|g7&-RvYykhM^Tj)IFm@N4IkcX$`L7PyLBpRWVgenvc!1mNx! z)7(27536GK$K5akS9MzIP+8GdSmv3Kp*~5=@aU)-J`$O}6CEAJ;g4b>QZ0CxrA47a zDfCp9peTY69+i$onA@{55eHVbv$GS{mhRjhRn_e%%+>1xtF|wv^%-yI+iiH$uCotx zyj!G7{glcBo@e?%X}PsL@9@z0^$nD9K^{5AE5Rkxto_WK6~tYjmxHPpm^q!3N8~Y) zo4C&Db+Sh^U6AL_oV=jFI&)Z2zD?#3?+f}Ma-|RNnTDE9gfu>5rFgjGYVc4AsRpGG#boe}P^Y?@3?6<5|L;?s4k3B6!4LUxpmHrf zout`mdMwmnSmfoYke{)s&Wl{97!yBm4N~Tcd?7%0}x;AT)Un$?}5A8yf4vT~NDv z3p#@8(2Y6KP3@1Ig(E+oVq4*h0SNsvpCiTp9J zz$sC30rjn`a45p5g2t07(80>L{oqubpBDD{A19o>&*+?O{eF2u8cr7`!I`l zp)=ym4i2F4AM761MFwoOx?P4e>CP;LAt@YRE}trylG{b8( literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/blinker/__pycache__/base.cpython-39.pyc b/UIKatabatic/Lib/site-packages/blinker/__pycache__/base.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..703ba51b01ae8b86fe067c51c4065728b1c0b8df GIT binary patch literal 17245 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/blinker/_utilities.py b/UIKatabatic/Lib/site-packages/blinker/_utilities.py new file mode 100644 index 00000000..000c902a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker/_utilities.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import collections.abc as c +import inspect +import typing as t +from weakref import ref +from weakref import WeakMethod + +T = t.TypeVar("T") + + +class Symbol: + """A constant symbol, nicer than ``object()``. Repeated calls return the + same instance. + + >>> Symbol('foo') is Symbol('foo') + True + >>> Symbol('foo') + foo + """ + + symbols: t.ClassVar[dict[str, Symbol]] = {} + + def __new__(cls, name: str) -> Symbol: + if name in cls.symbols: + return cls.symbols[name] + + obj = super().__new__(cls) + cls.symbols[name] = obj + return obj + + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return self.name + + def __getnewargs__(self) -> tuple[t.Any, ...]: + return (self.name,) + + +def make_id(obj: object) -> c.Hashable: + """Get a stable identifier for a receiver or sender, to be used as a dict + key or in a set. + """ + if inspect.ismethod(obj): + # The id of a bound method is not stable, but the id of the unbound + # function and instance are. + return id(obj.__func__), id(obj.__self__) + + if isinstance(obj, (str, int)): + # Instances with the same value always compare equal and have the same + # hash, even if the id may change. + return obj + + # Assume other types are not hashable but will always be the same instance. + return id(obj) + + +def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: + if inspect.ismethod(obj): + return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] + + return ref(obj, callback) diff --git a/UIKatabatic/Lib/site-packages/blinker/base.py b/UIKatabatic/Lib/site-packages/blinker/base.py new file mode 100644 index 00000000..d051b94a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/blinker/base.py @@ -0,0 +1,512 @@ +from __future__ import annotations + +import collections.abc as c +import sys +import typing as t +import weakref +from collections import defaultdict +from contextlib import contextmanager +from functools import cached_property +from inspect import iscoroutinefunction + +from ._utilities import make_id +from ._utilities import make_ref +from ._utilities import Symbol + +F = t.TypeVar("F", bound=c.Callable[..., t.Any]) + +ANY = Symbol("ANY") +"""Symbol for "any sender".""" + +ANY_ID = 0 + + +class Signal: + """A notification emitter. + + :param doc: The docstring for the signal. + """ + + ANY = ANY + """An alias for the :data:`~blinker.ANY` sender symbol.""" + + set_class: type[set[t.Any]] = set + """The set class to use for tracking connected receivers and senders. + Python's ``set`` is unordered. If receivers must be dispatched in the order + they were connected, an ordered set implementation can be used. + + .. versionadded:: 1.7 + """ + + @cached_property + def receiver_connected(self) -> Signal: + """Emitted at the end of each :meth:`connect` call. + + The signal sender is the signal instance, and the :meth:`connect` + arguments are passed through: ``receiver``, ``sender``, and ``weak``. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver connects.") + + @cached_property + def receiver_disconnected(self) -> Signal: + """Emitted at the end of each :meth:`disconnect` call. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: ``receiver`` and ``sender``. + + This signal is emitted **only** when :meth:`disconnect` is called + explicitly. This signal cannot be emitted by an automatic disconnect + when a weakly referenced receiver or sender goes out of scope, as the + instance is no longer be available to be used as the sender for this + signal. + + An alternative approach is available by subscribing to + :attr:`receiver_connected` and setting up a custom weakref cleanup + callback on weak receivers and senders. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver disconnects.") + + def __init__(self, doc: str | None = None) -> None: + if doc: + self.__doc__ = doc + + self.receivers: dict[ + t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] + ] = {} + """The map of connected receivers. Useful to quickly check if any + receivers are connected to the signal: ``if s.receivers:``. The + structure and data is not part of the public API, but checking its + boolean value is. + """ + + self.is_muted: bool = False + self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} + + def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: + """Connect ``receiver`` to be called when the signal is sent by + ``sender``. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends. + """ + receiver_id = make_id(receiver) + sender_id = ANY_ID if sender is ANY else make_id(sender) + + if weak: + self.receivers[receiver_id] = make_ref( + receiver, self._make_cleanup_receiver(receiver_id) + ) + else: + self.receivers[receiver_id] = receiver + + self._by_sender[sender_id].add(receiver_id) + self._by_receiver[receiver_id].add(sender_id) + + if sender is not ANY and sender_id not in self._weak_senders: + # store a cleanup for weakref-able senders + try: + self._weak_senders[sender_id] = make_ref( + sender, self._make_cleanup_sender(sender_id) + ) + except TypeError: + pass + + if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: + try: + self.receiver_connected.send( + self, receiver=receiver, sender=sender, weak=weak + ) + except TypeError: + # TODO no explanation or test for this + self.disconnect(receiver, sender) + raise + + return receiver + + def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: + """Connect the decorated function to be called when the signal is sent + by ``sender``. + + The decorated function will be called when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument along + with any extra keyword arguments. + + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends.= + + .. versionadded:: 1.1 + """ + + def decorator(fn: F) -> F: + self.connect(fn, sender, weak) + return fn + + return decorator + + @contextmanager + def connected_to( + self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY + ) -> c.Generator[None, None, None]: + """A context manager that temporarily connects ``receiver`` to the + signal while a ``with`` block executes. When the block exits, the + receiver is disconnected. Useful for tests. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. + + .. versionadded:: 1.1 + """ + self.connect(receiver, sender=sender, weak=False) + + try: + yield None + finally: + self.disconnect(receiver) + + @contextmanager + def muted(self) -> c.Generator[None, None, None]: + """A context manager that temporarily disables the signal. No receivers + will be called if the signal is sent, until the ``with`` block exits. + Useful for tests. + """ + self.is_muted = True + + try: + yield None + finally: + self.is_muted = False + + def send( + self, + sender: t.Any | None = None, + /, + *, + _async_wrapper: c.Callable[ + [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Call all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _async_wrapper: Will be called on any receivers that are async + coroutines to turn them into sync callables. For example, could run + the receiver with an event loop. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionchanged:: 1.7 + Added the ``_async_wrapper`` argument. + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if iscoroutinefunction(receiver): + if _async_wrapper is None: + raise RuntimeError("Cannot send to a coroutine function.") + + result = _async_wrapper(receiver)(sender, **kwargs) + else: + result = receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + async def send_async( + self, + sender: t.Any | None = None, + /, + *, + _sync_wrapper: c.Callable[ + [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Await all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _sync_wrapper: Will be called on any receivers that are sync + callables to turn them into async coroutines. For example, + could call the receiver in a thread. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionadded:: 1.7 + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if not iscoroutinefunction(receiver): + if _sync_wrapper is None: + raise RuntimeError("Cannot send to a non-coroutine function.") + + result = await _sync_wrapper(receiver)(sender, **kwargs) + else: + result = await receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + def has_receivers_for(self, sender: t.Any) -> bool: + """Check if there is at least one receiver that will be called with the + given ``sender``. A receiver connected to :data:`ANY` will always be + called, regardless of sender. Does not check if weakly referenced + receivers are still live. See :meth:`receivers_for` for a stronger + search. + + :param sender: Check for receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + if not self.receivers: + return False + + if self._by_sender[ANY_ID]: + return True + + if sender is ANY: + return False + + return make_id(sender) in self._by_sender + + def receivers_for( + self, sender: t.Any + ) -> c.Generator[c.Callable[..., t.Any], None, None]: + """Yield each receiver to be called for ``sender``, in addition to those + to be called for :data:`ANY`. Weakly referenced receivers that are not + live will be disconnected and skipped. + + :param sender: Yield receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + # TODO: test receivers_for(ANY) + if not self.receivers: + return + + sender_id = make_id(sender) + + if sender_id in self._by_sender: + ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] + else: + ids = self._by_sender[ANY_ID].copy() + + for receiver_id in ids: + receiver = self.receivers.get(receiver_id) + + if receiver is None: + continue + + if isinstance(receiver, weakref.ref): + strong = receiver() + + if strong is None: + self._disconnect(receiver_id, ANY_ID) + continue + + yield strong + else: + yield receiver + + def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: + """Disconnect ``receiver`` from being called when the signal is sent by + ``sender``. + + :param receiver: A connected receiver callable. + :param sender: Disconnect from only this sender. By default, disconnect + from all senders. + """ + sender_id: c.Hashable + + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = make_id(sender) + + receiver_id = make_id(receiver) + self._disconnect(receiver_id, sender_id) + + if ( + "receiver_disconnected" in self.__dict__ + and self.receiver_disconnected.receivers + ): + self.receiver_disconnected.send(self, receiver=receiver, sender=sender) + + def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: + if sender_id == ANY_ID: + if self._by_receiver.pop(receiver_id, None) is not None: + for bucket in self._by_sender.values(): + bucket.discard(receiver_id) + + self.receivers.pop(receiver_id, None) + else: + self._by_sender[sender_id].discard(receiver_id) + self._by_receiver[receiver_id].discard(sender_id) + + def _make_cleanup_receiver( + self, receiver_id: c.Hashable + ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: + """Create a callback function to disconnect a weakly referenced + receiver when it is garbage collected. + """ + + def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: + # If the interpreter is shutting down, disconnecting can result in a + # weird ignored exception. Don't call it in that case. + if not sys.is_finalizing(): + self._disconnect(receiver_id, ANY_ID) + + return cleanup + + def _make_cleanup_sender( + self, sender_id: c.Hashable + ) -> c.Callable[[weakref.ref[t.Any]], None]: + """Create a callback function to disconnect all receivers for a weakly + referenced sender when it is garbage collected. + """ + assert sender_id != ANY_ID + + def cleanup(ref: weakref.ref[t.Any]) -> None: + self._weak_senders.pop(sender_id, None) + + for receiver_id in self._by_sender.pop(sender_id, ()): + self._by_receiver[receiver_id].discard(sender_id) + + return cleanup + + def _cleanup_bookkeeping(self) -> None: + """Prune unused sender/receiver bookkeeping. Not threadsafe. + + Connecting & disconnecting leaves behind a small amount of bookkeeping + data. Typical workloads using Blinker, for example in most web apps, + Flask, CLI scripts, etc., are not adversely affected by this + bookkeeping. + + With a long-running process performing dynamic signal routing with high + volume, e.g. connecting to function closures, senders are all unique + object instances. Doing all of this over and over may cause memory usage + to grow due to extraneous bookkeeping. (An empty ``set`` for each stale + sender/receiver pair.) + + This method will prune that bookkeeping away, with the caveat that such + pruning is not threadsafe. The risk is that cleanup of a fully + disconnected receiver/sender pair occurs while another thread is + connecting that same pair. If you are in the highly dynamic, unique + receiver/sender situation that has lead you to this method, that failure + mode is perhaps not a big deal for you. + """ + for mapping in (self._by_sender, self._by_receiver): + for ident, bucket in list(mapping.items()): + if not bucket: + mapping.pop(ident, None) + + def _clear_state(self) -> None: + """Disconnect all receivers and senders. Useful for tests.""" + self._weak_senders.clear() + self.receivers.clear() + self._by_sender.clear() + self._by_receiver.clear() + + +class NamedSignal(Signal): + """A named generic notification emitter. The name is not used by the signal + itself, but matches the key in the :class:`Namespace` that it belongs to. + + :param name: The name of the signal within the namespace. + :param doc: The docstring for the signal. + """ + + def __init__(self, name: str, doc: str | None = None) -> None: + super().__init__(doc) + + #: The name of this signal. + self.name: str = name + + def __repr__(self) -> str: + base = super().__repr__() + return f"{base[:-1]}; {self.name!r}>" # noqa: E702 + + +class Namespace(dict[str, NamedSignal]): + """A dict mapping names to signals.""" + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` for the given ``name``, creating it + if required. Repeated calls with the same name return the same signal. + + :param name: The name of the signal. + :param doc: The docstring of the signal. + """ + if name not in self: + self[name] = NamedSignal(name, doc) + + return self[name] + + +class _PNamespaceSignal(t.Protocol): + def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... + + +default_namespace: Namespace = Namespace() +"""A default :class:`Namespace` for creating named signals. :func:`signal` +creates a :class:`NamedSignal` in this namespace. +""" + +signal: _PNamespaceSignal = default_namespace.signal +"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given +``name``, creating it if required. Repeated calls with the same name return the +same signal. +""" diff --git a/UIKatabatic/Lib/site-packages/blinker/py.typed b/UIKatabatic/Lib/site-packages/blinker/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt new file mode 100644 index 00000000..d12a8491 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt @@ -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/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/METADATA b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/METADATA new file mode 100644 index 00000000..366d1a7e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/METADATA @@ -0,0 +1,74 @@ +Metadata-Version: 2.3 +Name: click +Version: 8.1.8 +Summary: Composable command line interface toolkit +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Requires-Dist: colorama; platform_system == 'Windows' +Requires-Dist: importlib-metadata; python_version < '3.8' +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/click/ + +# $ 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 + + +## A Simple Example + +```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() +``` + +``` +$ 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 + diff --git a/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/RECORD b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/RECORD new file mode 100644 index 00000000..c44ec60d --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/RECORD @@ -0,0 +1,38 @@ +click-8.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.8.dist-info/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.8.dist-info/METADATA,sha256=WJtQ6uGS2ybLfvUE4vC0XIhIBr4yFGwjrMBR2fiCQ-Q,2263 +click-8.1.8.dist-info/RECORD,, +click-8.1.8.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 +click/__init__.py,sha256=j1DJeCbga4ribkv5uyvIAzI0oFN13fW9mevDKShFelo,3188 +click/__pycache__/__init__.cpython-39.pyc,, +click/__pycache__/_compat.cpython-39.pyc,, +click/__pycache__/_termui_impl.cpython-39.pyc,, +click/__pycache__/_textwrap.cpython-39.pyc,, +click/__pycache__/_winconsole.cpython-39.pyc,, +click/__pycache__/core.cpython-39.pyc,, +click/__pycache__/decorators.cpython-39.pyc,, +click/__pycache__/exceptions.cpython-39.pyc,, +click/__pycache__/formatting.cpython-39.pyc,, +click/__pycache__/globals.cpython-39.pyc,, +click/__pycache__/parser.cpython-39.pyc,, +click/__pycache__/shell_completion.cpython-39.pyc,, +click/__pycache__/termui.cpython-39.pyc,, +click/__pycache__/testing.cpython-39.pyc,, +click/__pycache__/types.cpython-39.pyc,, +click/__pycache__/utils.cpython-39.pyc,, +click/_compat.py,sha256=IGKh_J5QdfKELitnRfTGHneejWxoCw_NX9tfMbdcg3w,18730 +click/_termui_impl.py,sha256=a5z7I9gOFeMmu7Gb6_RPyQ8GPuVP1EeblixcWSPSQPk,24783 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=Q1nEVdctZwvIPOlt4vfHko0TYnHCeE40UEEul8Wpyvs,114748 +click/decorators.py,sha256=7t6F-QWowtLh6F_6l-4YV4Y4yNTcqFQEu9i37zIz68s,18925 +click/exceptions.py,sha256=V7zDT6emqJ8iNl0kF1P5kpFmLMWQ1T1L7aNNKM4YR0w,9600 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=cuJ6Bbo073lgEEmhjr394PeM-QFmXM-Ci-wmfsd7H5g,1954 +click/parser.py,sha256=h4sndcpF5OHrZQN8vD8IWb5OByvW7ABbhRToxovrqS8,19067 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=TR0dXEGcvWb9Eo3aaQEXGhnvNS3FF4H4QcuLnvAvYo4,18636 +click/termui.py,sha256=dLxiS70UOvIYBda_nEEZaPAFOVDVmRs1sEPMuLDowQo,28310 +click/testing.py,sha256=3RA8anCf7TZ8-5RAF5it2Te-aWXBAL5VLasQnMiC2ZQ,16282 +click/types.py,sha256=BD5Qqq4h-8kawBmOIzJlmq4xzThAf4wCvaOLZSBDNx0,36422 +click/utils.py,sha256=ce-IrO9ilII76LGkU354pOdHbepM8UftfNH7SfMU_28,20330 diff --git a/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/WHEEL new file mode 100644 index 00000000..e3c6feef --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click-8.1.8.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.10.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/click/__init__.py b/UIKatabatic/Lib/site-packages/click/__init__.py new file mode 100644 index 00000000..2610d0e1 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/__init__.py @@ -0,0 +1,75 @@ +""" +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 HelpOption as HelpOption +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.8" diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4398a01b4dd28f19914e35d62ff0f2e46aaedb63 GIT binary patch literal 2641 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 CD)JQo literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/_textwrap.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/_textwrap.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bcd12f3d7d2f4afb1601faa4514e8b0edea2ee2 GIT binary patch literal 1524 zcmZWpUvJws5GN^0mL11!gS1UH>}fy;0b4c<0|pGmP@o02bcG+bbsYq6geDcPrJ2RM)WN_-tKAYY*`-JR?e!a|uR-tkU%{N0aEwzqo(##ayinH>6r{EbR` za8Mq>v|oadMADqZ>o<)V=q&fqN2DkDC6Qc_sej?czN9~q$iId-GK{Djq=hck zX*o}HGEpW)dwT?+Jc4O|1))exC5f5xrd;{^+4mD0{X$z*xt0;9^x=oEl@Kf16&kRHRdzk?`A&1-KDpt@j7za~>^zOSL=eXMX;PJF{-lAAUUB|7;Um7gaVC@F6HXRVIXBSDTM6Oq^`mTaB$cuAr)oDdOf96kzUyhs^UZy*SZodf$O1Z`1IB2G@VyJ@`Cc2gb{N#lu^Tt>LP8)j z8Wul=#RSj-CeszYA{X=t`R!oDmfn&Bg2-x5(iu0Og64t7R=oCK1MgpxKN&Lh__ky# zuwUU{fHySASVwzN;JQjzb7hiJA@%aC#EWLl9yl00mDxsDJ}ojG1#93wL<=*ooR`T{ zASnbiVE!MWt#u1Tq4To`5Mu`*2<2>-1}ucR%g*n&p=tR?eHRL$lerSY^@NxgvI3S0 z*B9crO7hJPg-h}*!%JdI1N8v)?m-TN)N|osi3cl;`2cMnqre`u1a{JRAQ10{^`RF6 z=NUe4`#X&8^_zV_D#T9Vy>UT#w#f9vd;&qPxA_~*vvHHQac`w)GB%6}AFfaFEuwER JBc|$m{{jfXc@6*o literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/_winconsole.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/_winconsole.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d96ae84e7df7f9abd76b6c187f0a4cb019141e5 GIT binary patch literal 7775 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/core.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/core.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f486ee3949595f8d6b6d81d5b0f911879b9c322 GIT binary patch literal 90922 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

LC+JntDI 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/decorators.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/decorators.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e7d4a3e9b8591e7ac95d90ebf155133f9db7a05 GIT binary patch literal 17504 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/exceptions.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/exceptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db9d8175caa801b74c22d09f5a8fd886c348ec86 GIT binary patch literal 10282 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/globals.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/globals.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef8fcbea60819b16c9d82a2ee0ba4f7d80c13a8a GIT binary patch literal 2415 zcmah~U2hvj6x~^W#BrRjHiaYwX^{9bDyB%#2MZxkXlZC=qBa$(39`pKV|$bJ&T3}t zBv#5p+gJWUA6nkZ&){e5D-u%w0xxi8)*F%%iIsPDX6O3Ox#!+{mMtz;JzSr?|L5S> zInVpUF3w&hEWX06f5*T*P9m>O@bn{pRA?87C&+$LHQY|AUFHQ|jOIp_b_F|yCtiCV z`&IrXFY`HGdFJzZUVU16LfQ-N{ko{(xya`>JhxlRclpL^JBxOwy#OzSFTu|;UwK+= zFJZO%jPOhRGFHoc(|QxN4U5V>`5J7m@Hg<^6;AGZ^{cNChu5l;v=qsJMXv~!Sj}z8 z*oY%@Yr1Mg<8Ek#V$qMcSfs^Is%UNew5-EO#3n5(Va6&B>|gWC&h5R0TU&eX-S=LS z)=Lb^lBg>A@Yn6F=H3G>l-`Slh?2c;gg!7b*?X{!-yLRHkC`yoyBqfQG=O}Zu;73V zgx(9HFgW;R5Xl~JHIn1>@<5nQFjfk%Izbje%_8tIctkB=Z2Uh?h0M|!PK>`_;Qog9!v6tG6g^WkrM`ds9q}F!;!QVCJblBU zUY?K>@)$M`Jzji7ekO4>dtUdh;|(%aVvljiJx95wW+><^VCv|gv#=YK?hZpu0~XVs zpkpmKWtuX2$d0LzRf>xRfzYq{$Vj8Iw=V)i`$~=|i;oY7LW$fZyfQkHO3-kWAO)ex zyhSLI7^#{F9N>^O`{Ouhb`z#`o{lc%B9Mw1sd9hT$b>Scp>~cE6^@t+qhpJ@KaOZ$ zDmp}EphT!12SXdk%(V!HvP%z#A>NL{!O$RB=Oje=DxnR+4r3Y&Sv&~i0S%3Y#gI)x z`0O#u3JyNUV#YwD>fG!~nvC`EB8zLZITB{r?9N)Hp#zzS?pelXP8tn50d|DQI2XLx zq@OpgXa1WBQ*1=DPHNJyPqi?XzV5CX!u+_-W$gz9EqDsN!4vQJEsD#{>C+Z zXV;d8g$6(jxkLq=FUD4VE+r-{224XQI!Aton4Hzulf0yQ*XniqZ{kDz_-?Yk#rA73Yjzc~GE+xBwIqL~O- z>LK(FdtT64bI87X=`hfK#0HRc!z2nB1MSui(Xo>g+G zLW+LXuaL5@-nPETtvYGAu~lD9%jP(NsHsJ4rSoQ}1mkvX$xat{AMV`jY~8-Ob!WTv zZF@Dd?ckd(Vk<>D^^HJBLdRVz&q@}Bq9Vz-3m`4_q>R$a_lebK7P%r+Hq{Q!g#}Xi jVkG%E5?|UD)0-G7q~@1N#m87Ek~Q3$h4uB7(o*RkJ|1oE literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/parser.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/parser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f137c98a88649db3389a5681601b858e7795685 GIT binary patch literal 13560 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 N_8psecEX(~{vQC_{0sm9 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/shell_completion.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/shell_completion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..878e553c29f5deeb72fdf188f89af51b60abbab4 GIT binary patch literal 17071 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 a_|d}H;jy73hvl7lRr^J8wx}Nb;Qs(T@}*t? literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/termui.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/termui.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..18f85d9cfc906b335927b16a6fce3076b6831722 GIT binary patch literal 25860 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 D3}Kb0 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/types.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/types.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..88f2d7064b961fe0a5850d4fe42e52ce722e538a GIT binary patch literal 33441 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/__pycache__/utils.cpython-39.pyc b/UIKatabatic/Lib/site-packages/click/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9fa916fdb37dc9dc9492a4e3f045d1bc096ac80 GIT binary patch literal 18778 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 UM!2$mTAP;AA2Y;G*Qh-Czbmh$9{>OV literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/click/_compat.py b/UIKatabatic/Lib/site-packages/click/_compat.py new file mode 100644 index 00000000..9153d150 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/_compat.py @@ -0,0 +1,623 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +WIN = sys.platform.startswith("win") +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO[t.Any]) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO[t.Any], bool], bool], + find_binary: t.Callable[[t.IO[t.Any]], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, "os.PathLike[str]", int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO[t.Any]: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: "t.Union[str, os.PathLike[str]]", + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO[t.Any], bool]: + binary = "b" in mode + filename = os.fspath(filename) + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO[t.Any], af), True + + +class _AtomicFile: + def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + 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/UIKatabatic/Lib/site-packages/click/_termui_impl.py b/UIKatabatic/Lib/site-packages/click/_termui_impl.py new file mode 100644 index 00000000..ad9f8f6c --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/_termui_impl.py @@ -0,0 +1,788 @@ +""" +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 shutil import which +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: + if _tempfilepager(generator, pager_cmd, color): + return + elif _pipepager(generator, pager_cmd, color): + return + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if (WIN or sys.platform.startswith("os2")) and _tempfilepager( + generator, "more", color + ): + return + if _pipepager(generator, "less", color): + return + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if _pipepager(generator, "more", color): + return + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> bool: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + 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_absolute], + shell=True, + stdin=subprocess.PIPE, + env=env, + errors="replace", + text=True, + ) + assert c.stdin is not None + try: + for text in generator: + if not color: + text = strip_ansi(text) + + c.stdin.write(text) + except (OSError, KeyboardInterrupt): + pass + else: + c.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 + + return True + + +def _tempfilepager( + generator: t.Iterable[str], + cmd: str, + color: t.Optional[bool], +) -> bool: + """Page through text by invoking a program on a temporary file. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + # Which is necessary for Windows, it is also recommended in the Popen docs. + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + import subprocess + 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: + subprocess.call([cmd_absolute, filename]) + except OSError: + # Command not found + pass + finally: + os.close(fd) + os.unlink(filename) + + return True + + +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 which(editor) is not None: + 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) + args = ["explorer", f"/select,{url}"] + else: + args = ["start"] + if wait: + args.append("/WAIT") + args.append("") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + elif CYGWIN: + if locate: + url = _unquote_file(url) + args = ["cygstart", os.path.dirname(url)] + else: + args = ["cygstart"] + if wait: + args.append("-w") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + + 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 termios + import tty + + @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/UIKatabatic/Lib/site-packages/click/_textwrap.py b/UIKatabatic/Lib/site-packages/click/_textwrap.py new file mode 100644 index 00000000..b47dcbd4 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/click/_winconsole.py b/UIKatabatic/Lib/site-packages/click/_winconsole.py new file mode 100644 index 00000000..6b20df31 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/click/core.py b/UIKatabatic/Lib/site-packages/click/core.py new file mode 100644 index 00000000..e6305011 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/core.py @@ -0,0 +1,3047 @@ +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 .decorators import HelpOption + 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"]: + """Returns all declared parameters in the order they should be processed. + + The declared parameters are re-shuffled depending on the order in which + they were invoked, as well as the eagerness of each parameters. + + The invocation order takes precedence over the declaration order. I.e. the + order in which the user provided them to the CLI is respected. + + This behavior and its effect on callback evaluation is detailed at: + https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order + """ + + 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, + __callback: "t.Callable[..., V]", + *args: t.Any, + **kwargs: t.Any, + ) -> V: ... + + @t.overload + def invoke( + __self, + __callback: "Command", + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: ... + + def invoke( + __self, + __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) -> 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, # type: ignore[arg-type] + info_name=info_name, + parent=parent, + **extra, + ) + + 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._help_option: t.Optional[HelpOption] = None + 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. + + Unless ``add_help_option`` is ``False``. + + .. versionchanged:: 8.1.8 + The help option is now cached to avoid creating it multiple times. + """ + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + # Cache the help option object in private _help_option attribute to + # avoid creating it multiple times. Not doing this will break the + # callback odering by iter_params_for_processing(), which relies on + # object comparison. + if self._help_option is None: + # Avoid circular import. + from .decorators import HelpOption + + self._help_option = HelpOption(help_options) + + return self._help_option + + 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 # type: ignore[return-value] + + 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( + f"Could not determine name for option with declarations {decls!r}" + ) + + 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 default_value else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + elif 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("Argument is marked as exposed, but does not have a name.") + 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/UIKatabatic/Lib/site-packages/click/decorators.py b/UIKatabatic/Lib/site-packages/click/decorators.py new file mode 100644 index 00000000..bcf8906e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/decorators.py @@ -0,0 +1,562 @@ +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 + + +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 + + +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 + 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) + + +class HelpOption(Option): + """Pre-configured ``--help`` option which immediately prints the help page + and exits the program. + """ + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + **kwargs: t.Any, + ) -> None: + 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.setdefault("callback", self.show_help) + + super().__init__(param_decls, **kwargs) + + @staticmethod + def show_help(ctx: Context, param: Parameter, value: bool) -> None: + """Callback that print the help page on ```` and exits.""" + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Decorator for the pre-configured ``--help`` option defined above. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + kwargs.setdefault("cls", HelpOption) + return option(*param_decls, **kwargs) diff --git a/UIKatabatic/Lib/site-packages/click/exceptions.py b/UIKatabatic/Lib/site-packages/click/exceptions.py new file mode 100644 index 00000000..0b831516 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/exceptions.py @@ -0,0 +1,296 @@ +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .globals import resolve_color_default +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) + # The context will be removed by the time we print the message, so cache + # the color settings here to be used later on (in `show`) + self.show_color: t.Optional[bool] = resolve_color_default() + 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, + color=self.show_color, + ) + + +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/UIKatabatic/Lib/site-packages/click/formatting.py b/UIKatabatic/Lib/site-packages/click/formatting.py new file mode 100644 index 00000000..ddd2a2f8 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/click/globals.py b/UIKatabatic/Lib/site-packages/click/globals.py new file mode 100644 index 00000000..191e712d --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/globals.py @@ -0,0 +1,67 @@ +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/UIKatabatic/Lib/site-packages/click/parser.py b/UIKatabatic/Lib/site-packages/click/parser.py new file mode 100644 index 00000000..600b8436 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/parser.py @@ -0,0 +1,531 @@ +""" +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/UIKatabatic/Lib/site-packages/click/py.typed b/UIKatabatic/Lib/site-packages/click/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/click/shell_completion.py b/UIKatabatic/Lib/site-packages/click/shell_completion.py new file mode 100644 index 00000000..07d0f09b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/shell_completion.py @@ -0,0 +1,603 @@ +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 shutil + import subprocess + + bash_exe = shutil.which("bash") + + if bash_exe is None: + match = None + else: + output = subprocess.run( + [bash_exe, "--norc", "-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/UIKatabatic/Lib/site-packages/click/termui.py b/UIKatabatic/Lib/site-packages/click/termui.py new file mode 100644 index 00000000..c084f196 --- /dev/null +++ b/UIKatabatic/Lib/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) + 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/UIKatabatic/Lib/site-packages/click/testing.py b/UIKatabatic/Lib/site-packages/click/testing.py new file mode 100644 index 00000000..772b2159 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/testing.py @@ -0,0 +1,483 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import _compat +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 + old__compat_should_strip_ansi = _compat.should_strip_ansi + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + _compat.should_strip_ansi = should_strip_ansi + + 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 + _compat.should_strip_ansi = old__compat_should_strip_ansi + 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: + pass diff --git a/UIKatabatic/Lib/site-packages/click/types.py b/UIKatabatic/Lib/site-packages/click/types.py new file mode 100644 index 00000000..a70fd58c --- /dev/null +++ b/UIKatabatic/Lib/site-packages/click/types.py @@ -0,0 +1,1093 @@ +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. + + 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. + + .. versionchanged:: 2.0 + Added the ``atomic`` parameter. + """ + + 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: + 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!r} 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/UIKatabatic/Lib/site-packages/click/utils.py b/UIKatabatic/Lib/site-packages/click/utils.py new file mode 100644 index 00000000..836c6f21 --- /dev/null +++ b/UIKatabatic/Lib/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: + 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, color) # 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: t.Union[str, "os.PathLike[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 or Path 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/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/METADATA b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/METADATA new file mode 100644 index 00000000..a1b5c575 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/METADATA @@ -0,0 +1,441 @@ +Metadata-Version: 2.1 +Name: colorama +Version: 0.4.6 +Summary: Cross-platform colored terminal text. +Project-URL: Homepage, https://github.com/tartley/colorama +Author-email: Jonathan Hartley +License-File: LICENSE.txt +Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Terminals +Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7 +Description-Content-Type: text/x-rst + +.. image:: https://img.shields.io/pypi/v/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Latest Version + +.. image:: https://img.shields.io/pypi/pyversions/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Supported Python versions + +.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg + :target: https://github.com/tartley/colorama/actions/workflows/test.yml + :alt: Build Status + +Colorama +======== + +Makes ANSI escape character sequences (for producing colored terminal text and +cursor positioning) work under MS Windows. + +.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif + :target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD + :alt: Donate with Paypal + +`PyPI for releases `_ | +`Github for source `_ | +`Colorama for enterprise on Tidelift `_ + +If you find Colorama useful, please |donate| to the authors. Thank you! + +Installation +------------ + +Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8. + +No requirements other than the standard library. + +.. code-block:: bash + + pip install colorama + # or + conda install -c anaconda colorama + +Description +----------- + +ANSI escape character sequences have long been used to produce colored terminal +text and cursor positioning on Unix and Macs. Colorama makes this work on +Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which +would appear as gobbledygook in the output), and converting them into the +appropriate win32 calls to modify the state of the terminal. On other platforms, +Colorama does nothing. + +This has the upshot of providing a simple cross-platform API for printing +colored terminal text from Python, and has the happy side-effect that existing +applications or libraries which use ANSI sequences to produce colored output on +Linux or Macs can now also work on Windows, simply by calling +``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()`` +(all versions, but may have other side-effects – see below). + +An alternative approach is to install ``ansi.sys`` on Windows machines, which +provides the same behaviour for all applications running in terminals. Colorama +is intended for situations where that isn't easy (e.g., maybe your app doesn't +have an installer.) + +Demo scripts in the source code repository print some colored text using +ANSI sequences. Compare their output under Gnome-terminal's built in ANSI +handling, versus on Windows Command-Prompt using Colorama: + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png + :width: 661 + :height: 357 + :alt: ANSI sequences on Ubuntu under gnome-terminal. + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png + :width: 668 + :height: 325 + :alt: Same ANSI sequences on Windows, using Colorama. + +These screenshots show that, on Windows, Colorama does not support ANSI 'dim +text'; it looks the same as 'normal text'. + +Usage +----- + +Initialisation +.............. + +If the only thing you want from Colorama is to get ANSI escapes to work on +Windows, then run: + +.. code-block:: python + + from colorama import just_fix_windows_console + just_fix_windows_console() + +If you're on a recent version of Windows 10 or better, and your stdout/stderr +are pointing to a Windows console, then this will flip the magic configuration +switch to enable Windows' built-in ANSI support. + +If you're on an older version of Windows, and your stdout/stderr are pointing to +a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a +magic file object that intercepts ANSI escape sequences and issues the +appropriate Win32 calls to emulate them. + +In all other circumstances, it does nothing whatsoever. Basically the idea is +that this makes Windows act like Unix with respect to ANSI escape handling. + +It's safe to call this function multiple times. It's safe to call this function +on non-Windows platforms, but it won't do anything. It's safe to call this +function when one or both of your stdout/stderr are redirected to a file – it +won't do anything to those streams. + +Alternatively, you can use the older interface with more features (but also more +potential footguns): + +.. code-block:: python + + from colorama import init + init() + +This does the same thing as ``just_fix_windows_console``, except for the +following differences: + +- It's not safe to call ``init`` multiple times; you can end up with multiple + layers of wrapping and broken ANSI support. + +- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI, + and if it thinks they don't, then it will wrap ``sys.stdout`` and + ``sys.stderr`` in a magic file object that strips out ANSI escape sequences + before printing them. This happens on all platforms, and can be convenient if + you want to write your code to emit ANSI escape sequences unconditionally, and + let Colorama decide whether they should actually be output. But note that + Colorama's heuristic is not particularly clever. + +- ``init`` also accepts explicit keyword args to enable/disable various + functionality – see below. + +To stop using Colorama before your program exits, simply call ``deinit()``. +This will restore ``stdout`` and ``stderr`` to their original values, so that +Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is +cheaper than calling ``init()`` again (but does the same thing). + +Most users should depend on ``colorama >= 0.4.6``, and use +``just_fix_windows_console``. The old ``init`` interface will be supported +indefinitely for backwards compatibility, but we don't plan to fix any issues +with it, also for backwards compatibility. + +Colored Output +.............. + +Cross-platform printing of colored text can then be done using Colorama's +constant shorthand for ANSI escape sequences. These are deliberately +rudimentary, see below. + +.. code-block:: python + + from colorama import Fore, Back, Style + print(Fore.RED + 'some red text') + print(Back.GREEN + 'and with a green background') + print(Style.DIM + 'and in dim text') + print(Style.RESET_ALL) + print('back to normal now') + +...or simply by manually printing ANSI sequences from your own code: + +.. code-block:: python + + print('\033[31m' + 'some red text') + print('\033[39m') # and reset to default color + +...or, Colorama can be used in conjunction with existing ANSI libraries +such as the venerable `Termcolor `_ +the fabulous `Blessings `_, +or the incredible `_Rich `_. + +If you wish Colorama's Fore, Back and Style constants were more capable, +then consider using one of the above highly capable libraries to generate +colors, etc, and use Colorama just for its primary purpose: to convert +those ANSI sequences to also work on Windows: + +SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama. +We are only interested in converting ANSI codes to win32 API calls, not +shortcuts like the above to generate ANSI characters. + +.. code-block:: python + + from colorama import just_fix_windows_console + from termcolor import colored + + # use Colorama to make Termcolor work on Windows too + just_fix_windows_console() + + # then use Termcolor for all colored text output + print(colored('Hello, World!', 'green', 'on_red')) + +Available formatting constants are:: + + Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Style: DIM, NORMAL, BRIGHT, RESET_ALL + +``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will +perform this reset automatically on program exit. + +These are fairly well supported, but not part of the standard:: + + Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX + Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX + +Cursor Positioning +.................. + +ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for +an example of how to generate them. + +Init Keyword Args +................. + +``init()`` accepts some ``**kwargs`` to override default behaviour. + +init(autoreset=False): + If you find yourself repeatedly sending reset sequences to turn off color + changes at the end of every print, then ``init(autoreset=True)`` will + automate that: + + .. code-block:: python + + from colorama import init + init(autoreset=True) + print(Fore.RED + 'some red text') + print('automatically back to default color again') + +init(strip=None): + Pass ``True`` or ``False`` to override whether ANSI codes should be + stripped from the output. The default behaviour is to strip if on Windows + or if output is redirected (not a tty). + +init(convert=None): + Pass ``True`` or ``False`` to override whether to convert ANSI codes in the + output into win32 calls. The default behaviour is to convert if on Windows + and output is to a tty (terminal). + +init(wrap=True): + On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr`` + with proxy objects, which override the ``.write()`` method to do their work. + If this wrapping causes you problems, then this can be disabled by passing + ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or + ``strip`` or ``convert`` are True. + + When wrapping is disabled, colored printing on non-Windows platforms will + continue to work as normal. To do cross-platform colored output, you can + use Colorama's ``AnsiToWin32`` proxy directly: + + .. code-block:: python + + import sys + from colorama import init, AnsiToWin32 + init(wrap=False) + stream = AnsiToWin32(sys.stderr).stream + + # Python 2 + print >>stream, Fore.BLUE + 'blue text on stderr' + + # Python 3 + print(Fore.BLUE + 'blue text on stderr', file=stream) + +Recognised ANSI Sequences +......................... + +ANSI sequences generally take the form:: + + ESC [ ; ... + +Where ```` is an integer, and ```` is a single letter. Zero or +more params are passed to a ````. If no params are passed, it is +generally synonymous with passing a single zero. No spaces exist in the +sequence; they have been inserted here simply to read more easily. + +The only ANSI sequences that Colorama converts into win32 calls are:: + + ESC [ 0 m # reset all (colors and brightness) + ESC [ 1 m # bright + ESC [ 2 m # dim (looks same as normal brightness) + ESC [ 22 m # normal brightness + + # FOREGROUND: + ESC [ 30 m # black + ESC [ 31 m # red + ESC [ 32 m # green + ESC [ 33 m # yellow + ESC [ 34 m # blue + ESC [ 35 m # magenta + ESC [ 36 m # cyan + ESC [ 37 m # white + ESC [ 39 m # reset + + # BACKGROUND + ESC [ 40 m # black + ESC [ 41 m # red + ESC [ 42 m # green + ESC [ 43 m # yellow + ESC [ 44 m # blue + ESC [ 45 m # magenta + ESC [ 46 m # cyan + ESC [ 47 m # white + ESC [ 49 m # reset + + # cursor positioning + ESC [ y;x H # position cursor at x across, y down + ESC [ y;x f # position cursor at x across, y down + ESC [ n A # move cursor n lines up + ESC [ n B # move cursor n lines down + ESC [ n C # move cursor n characters forward + ESC [ n D # move cursor n characters backward + + # clear the screen + ESC [ mode J # clear the screen + + # clear the line + ESC [ mode K # clear the line + +Multiple numeric params to the ``'m'`` command can be combined into a single +sequence:: + + ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background + +All other ANSI sequences of the form ``ESC [ ; ... `` +are silently stripped from the output on Windows. + +Any other form of ANSI sequence, such as single-character codes or alternative +initial characters, are not recognised or stripped. It would be cool to add +them though. Let me know if it would be useful for you, via the Issues on +GitHub. + +Status & Known Problems +----------------------- + +I've personally only tested it on Windows XP (CMD, Console2), Ubuntu +(gnome-terminal, xterm), and OS X. + +Some valid ANSI sequences aren't recognised. + +If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the +explanation there of why we do not want PRs that allow Colorama to generate new +types of ANSI codes. + +See outstanding issues and wish-list: +https://github.com/tartley/colorama/issues + +If anything doesn't work for you, or doesn't do what you expected or hoped for, +I'd love to hear about it on that issues list, would be delighted by patches, +and would be happy to grant commit access to anyone who submits a working patch +or two. + +.. _README-hacking.md: README-hacking.md + +License +------- + +Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see +LICENSE file. + +Professional support +-------------------- + +.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png + :alt: Tidelift + :target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + +.. list-table:: + :widths: 10 100 + + * - |tideliftlogo| + - Professional support for colorama is available as part of the + `Tidelift Subscription`_. + Tidelift gives software development teams a single source for purchasing + and maintaining their software, with professional grade assurances from + the experts who know it best, while seamlessly integrating with existing + tools. + +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + +Thanks +------ + +See the CHANGELOG for more thanks! + +* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. +* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, + providing a solution to issue #7's setuptools/distutils debate, + and other fixes. +* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. +* Matthew McCormick for politely pointing out a longstanding crash on non-Win. +* Ben Hoyt, for a magnificent fix under 64-bit Windows. +* Jesse at Empty Square for submitting a fix for examples in the README. +* User 'jamessp', an observant documentation fix for cursor positioning. +* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 + fix. +* Julien Stuyck, for wisely suggesting Python3 compatible updates to README. +* Daniel Griffith for multiple fabulous patches. +* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty + output. +* Roger Binns, for many suggestions, valuable feedback, & bug reports. +* Tim Golden for thought and much appreciated feedback on the initial idea. +* User 'Zearin' for updates to the README file. +* John Szakmeister for adding support for light colors +* Charles Merriam for adding documentation to demos +* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes +* Florian Bruhin for a fix when stdout or stderr are None +* Thomas Weininger for fixing ValueError on Windows +* Remi Rampin for better Github integration and fixes to the README file +* Simeon Visser for closing a file handle using 'with' and updating classifiers + to include Python 3.3 and 3.4 +* Andy Neff for fixing RESET of LIGHT_EX colors. +* Jonathan Hartley for the initial idea and implementation. diff --git a/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/RECORD b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/RECORD new file mode 100644 index 00000000..1e4031eb --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/RECORD @@ -0,0 +1,31 @@ +colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158 +colorama-0.4.6.dist-info/RECORD,, +colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105 +colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491 +colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266 +colorama/__pycache__/__init__.cpython-39.pyc,, +colorama/__pycache__/ansi.cpython-39.pyc,, +colorama/__pycache__/ansitowin32.cpython-39.pyc,, +colorama/__pycache__/initialise.cpython-39.pyc,, +colorama/__pycache__/win32.cpython-39.pyc,, +colorama/__pycache__/winterm.cpython-39.pyc,, +colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 +colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128 +colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325 +colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75 +colorama/tests/__pycache__/__init__.cpython-39.pyc,, +colorama/tests/__pycache__/ansi_test.cpython-39.pyc,, +colorama/tests/__pycache__/ansitowin32_test.cpython-39.pyc,, +colorama/tests/__pycache__/initialise_test.cpython-39.pyc,, +colorama/tests/__pycache__/isatty_test.cpython-39.pyc,, +colorama/tests/__pycache__/utils.cpython-39.pyc,, +colorama/tests/__pycache__/winterm_test.cpython-39.pyc,, +colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839 +colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678 +colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741 +colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866 +colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079 +colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709 +colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181 +colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134 diff --git a/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL new file mode 100644 index 00000000..d79189fd --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.11.1 +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt new file mode 100644 index 00000000..3105888e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2010 Jonathan Hartley +All rights reserved. + +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 copyright holders, nor those 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/UIKatabatic/Lib/site-packages/colorama/__init__.py b/UIKatabatic/Lib/site-packages/colorama/__init__.py new file mode 100644 index 00000000..383101cd --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.4.6' + diff --git a/UIKatabatic/Lib/site-packages/colorama/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..74902f1741dc89e464068dc44746665863eb2a3d GIT binary patch literal 453 zcmYk2%}N6?5Pu@N&5OIm^Nz_yFU-MBX^}+uV4RK^clbhB%ZFj%18ui7=80 zPC|%9B9%2SQ&kxySdJXJR+>3fT-4bw26jsXae08$T!sDG<#VAlZ+0Q{9}Lc}WHOTVX^ zzaBzfnKoQiguDlO8?FMrhl7)1?5mifVoc17D`sA-niu0+zwW4|6KeUi81hNsQ?k9e lAA`=ADgHiSpAcx4knVi#>Zekb3&GByX#-vEgq^Sz{QwoIdrtrW literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/__pycache__/ansi.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/__pycache__/ansi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c64fd2e22adf86eb143bf4418f29cb912acb8020 GIT binary patch literal 3203 zcmc&$OK;mo5ayDUL{U#Gj@=|htG=VQk&zVWAt?gOl4`qAWJ9vyhEd8g+>OmxmXzhX zX$%J_;QWyE=)bhr0tNUNa_Y>|a^x3U_)=2)X@|3%*?BI#T+Y_uy8Y$fn=-9we<3k> znLy0L2;Txw&Cw`v2-O{(8je9tns}o*CQZ^5{3qxKG)?U{#7WX?G()p6OD$?NNAqtq znrGI5;iQ2s&?3-9McY76(Gt)lmIi(X=qq#@=xIe~fxb#-fSyrwj%5xsC(p8g1(pLW zG8=G;&UUrR^}RprwXGm5?+oc~pOrV+fN@W-uv}|*m&^W^$30&#UiOC+9*SXk#Djqd z2AlAtKji8W@OOfN*AJ_9m$AF$Eg?pC=jPa;`ZCxKMvMktb;vj8keWleE(?8c#9S0= z@98%l!+7$JqWSbx-Ouy9)pN4@oB_&xB1_tX=C-)jX=dto5ht&!(%dz&om zDcigqZ_XQpL3Q*>=1{CFhAw&}%;J`G0F7|S0qxAbkvFk#-0!|N3;RFX_nv;|UIjM3 z(ydElq1l3sCqy9nOzk@c3uMT2$b_pn1t7;db1;uk#~H={?y#RYt~mrxLCDYO%lduh zaX0iiV}sI!N}OLp+XJPIWB5*+X2+`f!GK+zP&AE-V4S$n)_E8qa+wANr9nYKSwRsQ z)PP(tWx58js)J48iG8BANf>o}{d)ibp*SE7?a9s8WS_hxl>A9TOX&OBJ~_}|>%zd9 zF!%KXa$pecg+<57=2jBYpaGY5C_FC0mx0)lsZAz4A-GIItZ<@IqGCuhWc_E-9C$lS zCVun!yJx&@xo$8BgzH|%&0)YbGfQl^_e#gsRL6_jU?jYO@?2Nit{c}Z%(JfhV%O`( z9R3lAnQ%5%0!P^#-Fyv(N+XLX`i!g5U-P)=KESc7a}@d)bSH!6RSzT3!wRa45$Iw? zYSFanVpG(n8SG*-3qdJKTbZ%T!y%8bpnZ(w_`*4=Q=vJoaB`}`YjMKr{01zQWH4cx zDiM8s^$Xw})y7`#y~gVL>Lv6o#3_q1PpdK;D;w>vCX^K>lp*gD>gpG(OZ~Xg*{F3I zl?jb;UMPoFkJy(`+PGM$xlpS=_+~=mq>ae)F=XQl=f@%Z5D3+zp>pCT4GlXEr>+{G z(SAqnNwTE0SB#^G{w~R@)1Ed~SGu=A+&HTF2}c8~T_OB4V4we|D_*?7;vd60UPkx? z0mH}9qa2OosD$4^P<8SiRKjL%_&c;;Kg*5jMwb05Zu3-fy(Mz{)aTsc@XI#i1R zbz;IfpMcs(Iu=biX=*t(O*ay0AYY0fFoyi=qFIH8M9iB36JXbEcRinP!N zKMpyIu)-s>D=H(PT@h|6LZ3vq;Rw?=LR%vT;W0uF;R(Vo2rj~}2p&NDaQc+1WMZKO z@s>uX*^r6FPP5sT$w$prYh^>43$690Og*eEHrs18Y1SXr+A^`Rw7k}oiB7ZIT$8!h z^5W8(65%#~mKjBYC?sN@5{YD9@nX?PXOCW8Zz5Gt)RC(9Y*dL z5t9oY%q3|wmLJMwd!_TR){<$JW^S$3I@c;RA9GzDtK*n+e2UEjRgV8kGUd8-=({e* zk9Ur>&NB#U1pL_I`1!-}<3lEgPoFbisKZnB0hKKrouZ^m6H62d1R^OD%1W86tA>5v lKBe_Te2m}MK|)vtFcT^r4GV7Du+3tom@Ce}olFwE{{a)&YlZ*- literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91bf17d114f793481d55dca0d28669aa70c908bd GIT binary patch literal 8281 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/__pycache__/win32.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/__pycache__/win32.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a54b273e04902c067203f5178187272e84b8651b GIT binary patch literal 4436 zcmai1TXPf16`r0MjmGlbfHCH#HQ*rddRfS=wkWd3HsFeoiDl#Llv7hrHbbyFQF>rJ3V7r2AquCr%&Hcf9KW?1_yHnzAvZ$ zzIAQFF#bl3-medhuTi4YreScyGdS}YH$8K2mRsCzSe}JC)3BPhXEQ_C!m4NXndhL_ zL2uT}GGpCn&De%;MPJo?QDp}GxQ#hk?!Gd-9PiV0|2M`TS?kAJ2G-`VcEB5G4tj&l zA#bQT>Q|UQ9s~?ca(Ip@3h9hOI^%|S zGd*V<^4?5GZ~Eu>ARhwKGklnjpzaq&mGMzN_KJCv{1iW}wJ^oU`C0T_<`euJdOqiq z{5Tu;hLzrcDCSECU7GxRY5uE?wMfWlqa{RR zXJbJ`&*E@rV{Hk4zYgMHGl*-I4IH}>)nf7aPEdIkY>8;25;j5^G=nc7z@6K(J1>-b zw-Gcqd2nw8yZ-~lkmLvdUoe@Wxmu=dm(xx16urqPG5sI~TV*z1NKsXN5Rg+tq+9FeT(8{3BqIRfv zE91GTPxbLW=q9Ho=a)<6<>I1Wo?ls9Ecy4>9z0lF@s~;umiJCYTB>}ll?O1Dur<3q zs~o;tuI&jm!guG}G79CB5Mb8Amg?V~i(^^aY{w!}ZY0-hEgtTwQ+)Sv@VwS+HYIe~*jzSAINKEcz>p^Q+jZS`!T(`SKzr^vHW; zn`G)|Q6geoW}6Okn2VqD&dy5eJf=1a9dwvh+XXPOv2VO&G1L~D9k$Q*&6j3ub`jreAtS@hA3C05Uu;|YE{UkRyCAl3Ci9K!$!eU&UVn^4WaBxv{_Tx zs9mXuDC&`3qdnlmJcFH@55tQaSRd(}1?f%ZzPC+z6MY}~5jm=s{SufMM#s%pM$BT! z3u^7Ns<~j`7LdMRm5yBzsYaCL*O{S?vaTa$uRa%rZIFPO@ly`|Xp zhr;*W-4ZSFd`I4+-E>^oyVP@^*}ILf5;UTFv)ze^8&=SIp#}-Za?BqkAUWmLh2^zX zMfKv!O3y)E9m7YDkdh=l4H?k!(0h3Y+_7ttcDowRqk#(o5z;X~KK^<0SoIPXF1#pP$&zQ`UIng*q%n7PZsuSELkFD6= zXZ6fWyJOiDIPJRg3&S*grrRdkS=}~c1WRZz6Zds89gA>)ZA*ggErsDiPEMhcWYdyj zfh1_&S83R0$y)Nu^LTk!Ts)#8OcvVJ8=Z< z@!fxq!y^(1*qW!AZI2^d<=6-tF@g23&|e{F4?oJpRJ1wV2a}qE4Rc@z=Ig|$tpmGb zzGf7(4s6cAW#UZ7?vTk?vD3k`bwBeGbv>(di-xV>Ce}_tUO56;5^otgTV)n>5We6) zs5KgCv|Db+JMDNL`8}w_Le3@8F7sW`Xp2HNLCn_a-)V@}R=lk;Q5?uvqoev;?WVsg zYjG@EpLU#+kNPu2iYSJYH4d;G%b6ye9>I|^?#XC)(!vKsC_eLS!Nw3e3;?&7|{{_>N z#1Df6*eTqyi2h?Smb{MKPn)I-CIR~}mNGTk<6^6|xFOc@=*YyxeJIcHk-O-bKVZ9v zHaD1D20eB#g`#fwq1(pB0eeje9Iq^d^)!KZ%xEgM4>GTf?3Ca1X9p=-*(OTp>~>@MG_{}ofx+?j(+avkjg zTP=K%#LC-fs;R}&+;a{>O4@}cG_WkAMqWn1>bcF~-TS;L;o&U%m zdLkW#U2XnyiRO+R;h9*qd`#Wh;*n2wM4+2tDI;xYE|#qam#;{S)N?7H;13)X8#KZspp^o literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/__pycache__/winterm.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/__pycache__/winterm.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e7d323d06f46a6f901753304b62ebf1ac41b7c3 GIT binary patch literal 5239 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 C1TXLa literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/ansi.py b/UIKatabatic/Lib/site-packages/colorama/ansi.py new file mode 100644 index 00000000..11ec695f --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\a' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/UIKatabatic/Lib/site-packages/colorama/ansitowin32.py b/UIKatabatic/Lib/site-packages/colorama/ansitowin32.py new file mode 100644 index 00000000..abf209e6 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/ansitowin32.py @@ -0,0 +1,277 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL +from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def __enter__(self, *args, **kwargs): + # special method lookup bypasses __getattr__/__getattribute__, see + # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit + # thus, contextlib magic methods are not proxied via __getattr__ + return self.__wrapped.__enter__(*args, **kwargs) + + def __exit__(self, *args, **kwargs): + return self.__wrapped.__exit__(*args, **kwargs) + + def __setstate__(self, state): + self.__dict__ = state + + def __getstate__(self): + return self.__dict__ + + def write(self, text): + self.__convertor.write(text) + + def isatty(self): + stream = self.__wrapped + if 'PYCHARM_HOSTED' in os.environ: + if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): + return True + try: + stream_isatty = stream.isatty + except AttributeError: + return False + else: + return stream_isatty() + + @property + def closed(self): + stream = self.__wrapped + try: + return stream.closed + # AttributeError in the case that the stream doesn't support being closed + # ValueError for the case that the stream has already been detached when atexit runs + except (AttributeError, ValueError): + return True + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + try: + fd = wrapped.fileno() + except Exception: + fd = -1 + system_has_native_ansi = not on_windows or enable_vt_processing(fd) + have_tty = not self.stream.closed and self.stream.isatty() + need_conversion = conversion_supported and not system_has_native_ansi + + # should we strip ANSI sequences from our output? + if strip is None: + strip = need_conversion or not have_tty + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = need_conversion and have_tty + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not self.stream.closed: + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command == BEL: + if paramstring.count(";") == 1: + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text + + + def flush(self): + self.wrapped.flush() diff --git a/UIKatabatic/Lib/site-packages/colorama/initialise.py b/UIKatabatic/Lib/site-packages/colorama/initialise.py new file mode 100644 index 00000000..d5fd4b71 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/initialise.py @@ -0,0 +1,121 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +def _wipe_internal_state_for_tests(): + global orig_stdout, orig_stderr + orig_stdout = None + orig_stderr = None + + global wrapped_stdout, wrapped_stderr + wrapped_stdout = None + wrapped_stderr = None + + global atexit_done + atexit_done = False + + global fixed_windows_console + fixed_windows_console = False + + try: + # no-op if it wasn't registered + atexit.unregister(reset_all) + except AttributeError: + # python 2: no atexit.unregister. Oh well, we did our best. + pass + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +def just_fix_windows_console(): + global fixed_windows_console + + if sys.platform != "win32": + return + if fixed_windows_console: + return + if wrapped_stdout is not None or wrapped_stderr is not None: + # Someone already ran init() and it did stuff, so we won't second-guess them + return + + # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the + # native ANSI support in the console as a side-effect. We only need to actually + # replace sys.stdout/stderr if we're in the old-style conversion mode. + new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False) + if new_stdout.convert: + sys.stdout = new_stdout + new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False) + if new_stderr.convert: + sys.stderr = new_stderr + + fixed_windows_console = True + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + +# Use this for initial setup as well, to reduce code duplication +_wipe_internal_state_for_tests() diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__init__.py b/UIKatabatic/Lib/site-packages/colorama/tests/__init__.py new file mode 100644 index 00000000..8c5661e9 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/__init__.py @@ -0,0 +1 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b97edad84b1c1461e0553025923140e58b636960 GIT binary patch literal 173 zcmYe~<>g`k0zE1y4F^Gc<7=auIATDMB5-AM944RC7D;bJF!U*D5kh4`xXmM&$ zaZFxnYED6nOKNd;Nq#|0s3#D4Czd28C6;6+$M|F>#S~|jr0NzVCTAz6rxwQ~=jY@X pCFUmTm!uY#6zj*wXXa&=#K-FuRNmsS$<0qG%}KQb+4UKS82}|PEZzVB literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85e24722a439bde12e74b57dd08782e79b58d0c6 GIT binary patch literal 2533 zcmeHJTTk3Z6rS;Iy;l}UNn6sU*R-xw2(WFmRn=w#E7UN(d-b6DXeVTIT@HG^6_#oQx<@5kmT0WZ2uyy7bui*!6gy4^Svt5Ft9D~bA}R|d3u zrnDYK2S?KSDdn-Wx5ddY_NXkkMp?g`?)FD3%Lf=Bf1%?;xU&X8OajVCU@*#zmn1N8 z`d}?)GY72A3d{xTup%pgEwD07sv=!A08HqBLXh(dpK*~^;m*DU_?7%d1Qo`>Jf*_= z-JlmO_IV2<+vJRPJSV6{Sr&8ANrnH*aWs^cI2p&%%uX`tWP+u~g1Zn@k(l!{Dy=LY zK0hOT8k+y!Uj44O0|Bz$D2|8Y-dda;iFDlC*?|8ik%;yq(Ld<5`}@7DFXFGquyD~~ zob?XUValT4{N? zPNv^X?7aWl+}>=@U*M^?X8@aju{8se898P#GskR}+r)vx>|9@gIXULCLXH)gn`0$b z%&{^n?_ojAlYWJpgZ)*3Zc5gmNyjfY+`c~rR4(_ABd@%6-SLr4DfW7(i*6henU1A~2703)XYjn>H>f29@9!T2 zeGjGi2>_wBtAFO@mdSihxL4!+FJVCk*CpK08f<6{HnavCT7wO(!G_jgLu;_1CENfB zJM()>_rYIT2%s!PP!>Wc3o(?1Aj(1%Wl_rfHf$@m5#B|>z2@&D%p=@E_yFNUgu4hI zA$*L0n&6)ze1`Bj!aam95U^~#U1C`5E+n=H@BTN5U5@j1i7mhg|NbkfzA#p2V$JXA z{a6MAWGV4%y<`Q5C(X5uP3d%=Zf&;O(s{Inr})N{XYo|2ntqY9k2&MVLm#Wjol8gO z%F7+km2Mc0q9hJOSqj4>WyeE&u7n}hSlz>CAsnAW@DRR2z|?bfM^zv!KD-Ek1uMf! z<{GZ!+U}e?r`mBe{B;tBUR_nSz&#%I1?IuAEOHY-S`n03Eg#H;t5qpuqex%iZx&VO uRYBxf;kYV<@8A;-&T-#wnwoUK*9rcBV`W%=U0OG8(Td?v$E^S8(tiLXfHzJ6 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec59557dcae299d253ff712d09c3c546ae087871 GIT binary patch literal 11536 zcmcIqOOPAKd7c*@3t+)rzQl(_QItg!deHkIC0U>;t;r>|F$vP-N{k>XV-P*N#1g=O zJ+mT(TE>-HrXnXL%PF5+rBtn)6YnWsa>*rCzT}eQm4H$MDi0l}v;G)Uyfw>^-At%^2+ixaZU}jchsF z$dz-A$?~LXcU-mmX}6tI&kw$%+lz!q)^|0g%2SQ$@-#+Bh*W)dV^4Vx%4soC-`m(% z-e(#Y4UrMqhla>{&Zb@7k9tl_qCTnWPk9GK{*EPo<0UpZ&t2Dz!qj7|*C<#~`g$m9 z&DEtV(d4psKU}(ULsnWXPx8^S7lh|3ffqTAO08Kiqlv})weWgasop8r(ZuD-YOQ+N zuil9qMH8(`SiSw&(j8|Pnn7*Zzfo(>&qb3M#j7;pz8{&e+_{eK+iE&PHrAf8b+g;BPIDXfP^ z*%r2NaCHbFt^iJ?aZQQ|k-;@3vLc6TT1*0rd^9~UKd!sV(K~-O3J!kf@C%NEgvO@v zzzod|47zDOur`b>Yr|TzH_SDA-T2%jH(WO!nWcgw$zn1G5@jku;K^`Vu6yOItTct+ za4TUb0j3jp^_3{o0GfI#QR<%Fh)0He3XQ)gpL^rxJ7^xFoGiheb_K^{6PWHb(02Dz=;HQ9k9fcSu!etSz4GVDD8}=4< ziZB5<8^Bp>j<9ORiuJh?JM4*FiW0ZIdfhLW@(?;IB>I3%+>=Q3fy&t!c`PH?4nQrqimR))~AOQ4z|YO1{lV{zfIdTnp3kz@al|GDyH!su0Y8F zN{KFGStSihQiDQKP%I|70F6tsTK5A_bU=9q4WascIXfltS}LRBR)OOC^*^OB%4acnAuUt5MEM1XUG3I-=q*a=%V@%NJuF+gZaEv&gy(uID_%8J=tem$ zw%01PzzcdXgCo1_CKbFX?|!w`T=B$q1+*w7@0J9R9Um z8V~l^9tIG%(NR}fy@-lNe8b!_KL;;`;J&WXqU<@qHbgRr^EqVbK;;lgzKa@ES|ZaxK4}b#kX+XEnX1E zaor=nEl%LNR}{pHxb71UY|_iou0E$`8SFj4XB4`w;Egwa!u*8hkKTe!Z-Igr*T8ih zF)UamI$M?X(3f7|g&o_M#Q>80)^QGmJdIkc;yd1h@Ylo0QH@_=gWl#TtCuE6E;Vc6 zn|L^&;qzwuz|i`%rN_%(Jl%04PWCwvC*ejwYc@(>9Nq45rBzdI#sEXmx8m<2r$ESr z2?b3(sAdcQ&~!)UeWqS%+!B?uZ1f-a!Mz@yZReGNZK2$Dt?>m^LJYTQe)=MGA=Cie zIND=V*&wA4X=O+3$?L=R1e+9DP43MU`qXw@Bo{9%VSfTGxFZ10i~!)kMQiy% z?fwP$Xh+fa2o_OnI4)G`@LU)0iu^vw5KA8FTZ(%1%F0TNLkX{UH6nFl`^6{VFw}Si ziLPt zN2VmF7BYRT@hWaa)5>{u;r_c-?VoC7lQBwM^%4z!03r-LAs{mA_$w$)I;|g|-28;#vYxQBwQ5FbOFdh&8ZSpHa{ZH6fLn zp-PjNK%xm{BwX-}G6ygYS}W^dfc8Q`)QJSxM!h&zBTZ{p&+QtYpn>;;Jct3mjNTc3 z;Hma=!|05(9N;JF`vL2?VXQ$B3+odV2BK{Dl}$PXpD637p2Rge@`Xfc8N$V7Tqs!T zs?DG&8EZioDYtw`$MmFSp<`A9h9j|Zq05aO-(E_3tp-*_SGlWIMt#ffb}}>ItR>bU z7X#YDF7>f}s&8i%$E&@g($HH;Rq)8t%Nu7+j&(J{LQ^2dVC<`yKDb&(0*CpXKje~i zaIb>fx#3Ox>MjP>&mCoV=h*KbfOJ_M*%2_g=~}DUHM^QT{@|Ia{2Y zDbCKl{x)t6fJUYvaMuYMnROLT;0HN|Bf>an{JC`(-X>U_BBN|2l5y6_88~&wats^K z%$a%(j;P;go&5#hr(4%v+QGKQR-;~jw^FYOHaK~v?!)v1XHn?%sTHyr*;quOPxV9@ zm3M)vnV*wg7L77m7cu#wl{Q&8%6D@#E<5gMBJyzL2;{D!1n7EWcx^9?;l|NvZ=xFo zBNY@(-mWx+Ib%BJZZr91`}FSw#mIh9zbhtZKs3taVB|QH1KsU_g(2$NQBZ7amD-uZ z?}KSTW*f*t^i=r!=ubmM+uwsyn>Dh?j!?N%YXysqR`}8NW)1nikcZo_537CEedo1*J$GOBkheFJ#juG8w2`T~#Ka|1DO$0;8@j&3WlCe5~ z-RrtnR0PP^9yB%_TEV+#6qZ>ySjkoeDa`;;Qcil|x@@{1R_f~>vdRvzgu{NnthPBox7H_cusg7tlZBi4^=BG z)zH=Rj1tH#HUddEswWo8wR;q2k(55C0+lX1NPG8NNI<~}9I|7xV?^Q{On(4}d4BFj zExdhIL8B}{qX94TFVSB>)6uctIm=jiu{1QQ^i9zY$| zlA-BHIC`N!8XI{k`kyL=6eo{SW)!0$nAo0f6WRO0Nv4M6TbQpbf>iMv_@i}F7L2BB zFo5sd7_~(zVRRO+{SAKFLR}q;GS57Av~B&SN~Z;&R2AnarXk##hxV|fB2T4Wm54TZ zZ-{qPro-Lw_zI5#K%-o*+W=k939WJTMJ9OTdyinZoHn@X6bB9|F zF`^GGo!1=Uh&TE3NXafY;4Jah8uR*NxB{VsiW_{+Wr#V{(b;y)F=iHji#~M7)a8r| zlL{Vb)dE>hjFx=+VeS8el_BWQ80*uoxHo1895 zCP)xTWq7f)Bf3kKA5*i}ehuL-Bp%cBJ>F099LdWhuYnX&k0tn63Luf@vV#>6D({~_)IL@R2!CR%n8f;F zdc{;_1hL&R&NNvTiO(QVF0zd95#a~Xm!VSD8SambwFE;Qgh`oSc28mo+0uZ*9Bv|gm9ghkB;qH=?M36eohmG9x+zw*99zW6&J z-wDaEBDH?C?SvPHQ)CGxIZ;-HWG*AFK++l267&H}y=X#h0~ZxNMgAYN=l_6*u^chs z!vsn0f6|E@;;KC3s&DUb1p}BecIfIXig(W~q!i(B#G(s??EIMrHYCD9;s9sB&|3Ki zOe@+O>J0qu3FXw-Dxs2~JdK#NoBbv&HeJi|hZs`60a8e|ox>l@q}plF;)?I5+XqqPs+L9gSB3=TCCU7{UCt23vc-3FW zkwj8kve)>YiYuX25 zW&<1DF-|u7I&bQY{+apd@t+tym8nDtCTf!k5o)q?^rvbF7WF}(s^I`IehWu{efMz? z*r_q}gqbtN6hAVdH-x$^rkQXRyO~Z!D7pvN1X8ZZI>E1Iem^DlhUr)(Pi#1Anb_}P zIom65N+$MQlGpCEncxzIp7!@?0qe@?0O|KT})i8*PF`o`Cv zQRld@eW)Y$JkXq4g{al2%D8*`p{$ z$y$I=;v-47AWE*(>R!`Vwza%FKH{Kp#YY?WkZqB9HeMuIAYp(RW%cJSDq>Kv2HaW| zTzrD3<^164_z?{=5q-xof5x7a)Tskve7-RvSO1Au)R&LU>f~@poX0;uo9`Y0jUEJUV2);T=sih>-$#gC~ znaSdsNFM^7#*+-}Rz5wMo>Hy&84N#Tb=^|oU}V*Noi3n(DyP@+i35$Gq{Al@AjofP zA- zGQ~tuVm++EXPaX4X%a40V?G9oD1AnM%X5}0IXDI~Wlmx9r_7wS8}2zhUwsCuVZ*jk<*`m}xkd;TEVVO|DRIfo zaOB5A1`5bP(?gM-dgv)W>e@e`DEbE!J@Z;1fX=-XIkf$K!+k&GqG+_{kTc&rzV~D7 zPfZmJ{9U>D&E|tshVggm^!_>M+`yCk1r0Yi3k{dvX2|NMYt}8-s@ty3jOH7X3$T=C%f>^jmW%gaGU4CLcQn~F~jEhuvDLNr|M<5TtDI- z!Po?M!s+^qJ5!%^XPF_4t)uQSw8!1K4-G!a3oi^_5ayoco4bQ`@He zld$&ae0JZcln+3MQLR|1vnmpG%TGjV*Zm+$3(0oSco2mmNh)TVYxt`6D78P0Yug7V zmQ+|ebze#0*B?s1(GU__*g+Ji^yJn~qP&gZsrMv^c>E;sYH^grp-9hQq#?W@QbI<4 z=q1Wm!rO?Yr*L+1z-V7H&BsaP*F{>8q7nKv;jKTb5thAwd30{zNxnfN43}}kHH9VY zt=!l7m!NIWzYczsTRx{p0*?$f}Y$D_}6msd*xKmMkWU$2)2vNEV`4 zE%*ycJ*yE9+kf;;vbu#QDWTalzBXQJ)w^%(vnpgb?I($lsv4_IjC`M^b|S)!eM26@ zif=!^^}*T$Oi9)vA;QMmZINuNxUu$N1^+(wmA~$*ptkl&u)dZAO1$6jYuo;&NY-j` z7)!tIU(&L@M5+<^VUP$d?8U~jG?xhVph2f3gr#9M%We7=HE29BbC|9S(qhGw=~>D~ zo8!iPLrw#r1RunE#kNdkarV+;?Y^yY+-&vpYC_L&puE;gQ_so9 zY(-->jS-QRT(x@4yc6<;b+Pb78zR>bkh3rhnO*n!LTg<%TQ=Kcw4yaunM{kB zUaTb03`wL*ctb;;q~#Jp#G_9q$G>k@SGAVI-kCR~^h=>%U+4bycd_Olc#Ix(Z^OQ=j6_33{(309$I5HS zxQ6HvM4SH=KFb*v7jW7DKJqP$y+`A3qp4|Ufe-qlZ_+kxW*^`~k?&_;ogvRa{sBs1 zlFNGt!?E$(gXu-nSB&Jn%NV8K=Xgjpz>?IA)V?LBu#cRi<_$FaraVgDB)tK|(m8T& zBuCQd-|7!k7+VXG)U85P_C4(esLmzucspVn^Gjiop zd(HE0I&a4!i8OcaMtABvAp$;cG3hF1XH2p*linL*(jkk7Ji-4-2`W&6Tq90`r}8pU zGb$vU8AV(*ZVUg%9lDsN>#alS>aH74(nr`4dX3EBtHoZuR@RpNl4UxM?;L#(>G{&2 zp6du%$;&d)M_TTd+Aa;qh#t459sMW{oE+xB$_6dIPPCIK45HmCvF00xP@k zvgdO|H)V9cZP7c@rY{fDTCuB=^lTMwZqnaTv38>JeGH8h?Zq}>H`{Yz)0t`C48zZ$ zzQ|VV$uicra)AN}ZC)B8^6>TFHOb^FmyzAs6wt>j^0_v(MB?3zjb3|e8R^FZl)gJe z>G-unRCe+qauiv#<`C)&qm$QI)jn5i#FoHO`M2`p)Y)&dhrkX>C}u9)%%7?(dn zQ(>9Y)^4cVkVDcDC_b3fb>cchF*=aTOX@cWR{J_DLrR?M2${s(NE7dycjc>%J6`$FBy%CJ@O zRNYic2J1UYG|zVC1>IERCen)47%Fh>YRv*B?LYeNINDuwTGsi?LF-i3F59wE!RVBg zVlef2Zr;#O9&fXi;AW7CLCBCFi-v65sY+7xRr!6ia)KJtkxU^d; z4Ft0Sn`Nh1^Gu)IhL()aWB!V5TAcl3+u!$lzeD&-yd`e-^Vh*hAEcWdb@rO(uK84fI=ddZJGbw;uV? zrl8Do4RaHUT!x7dgok8t%FN?!vsn}v)HWAJ%ci?c^ZY2oK>G4DP)Nl$p)f)YiI9l6 zMF>#xkQJyWwhUJ! zTKsWK1i9BjYLHQn%7`Vh&}i7y5ZKW@WW9mpYzDH#MG@ z7Cd0bcaZpdY02}*$TEo3vhGxnX+B7N+*3%Z;N|PoP>!w3BdO(niMm&)(FyJM=h*doVs*)zq6Q6M zxT~*BRxv&b1ufp^0Ja0!x$$SW?@;7<%pYPsIdjbok^z;k@=bgU3cf3SsuzDnGjy~+ zTfz{pCm@^>ME6Xdv4M$&#nG5cC{b>(vZIg>-9Oi`f4aD zqhFvES^rf#^sh#*_w=H^NgIj7E@9P<;?}OlfavV?`Clwu0o}cfwQF~YR`1Rb{|h1!vk_n4BkG`|rb7l;R{9ynHg-$ikxN6mC? z>umVjf-V)m1TZ0`Gqm?`$a}(z=J9q|^Uh()o~V(~ZjRYLqhc=XQ38+I}#m<8LJq)6OhcjG)bHBbjhGi>j3gxq`DL z74MSDsLW65kf#IP0~#9@yFLZr2_9WYLzfVpN=(uy1zh^i8PBVn()@Ov9c1mq0!j8H z$z|z?>rS-+i$a*9mc*usQ6QX|iJo&vRx8?`bk7Yg$a-aoB$VXVENv literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b3d02c95cb02cc4dcd2db5e4b9a014c7ba59aa3 GIT binary patch literal 2786 zcmd5;&2QX96rb_edcC{J(v%2D8lXU7C1_K)RaI1!s;H$3NJ*5|T46amlf;SbU1nyf z5`_!fGr4n0ZscF`6$vT-0w>-Z?}yhL<%n3X-^`m2dw#$7o977|4UfR@;l022UsMSB z3!UQ60_O?bG6lm3qcQQZG-8?fJD~ap7N!70=p6?|! zzn0YfI`mbT`)SJ2W>omEd8rBf?&fi>&r-Dx#+L zwZew>%!y>E)NzYuj?}BXB%%o&|7@>6YHv#}WIN?N?zNwCd8E3%_V#o5e;=xFH&jul z{W98Z%SiFBdST}%+~>00>Be0VCgB4GWXK2k^8_f9B#2OP3v36g z#UJ)Pfm=QW!--EB@eM|q0bwyQlu%k2LMZKFxSTv#eudRo9ok*iU~^Db**pZQnR(AO zS`5<^U-&K;Zq3(As3H>%`#!=#M zLLE9sU3#)GfpdQ}>c7WT$5qyHT+hN7;9)$6z{Dcd{Yu(RG3aG%HN9%+1bDY$;559& zGQ51?6hc(`IC3w*!N{Ghj-sT@Lo1J79yRdo+@FctQ$?fn5_bifb@Uz46Jl@S)kPQgTh;*QY*-GfRlP(=akGmxeh z=}?@evPP1f0r{v1a;EoHv3DX}TT3_R0T(eLL%fSF=8J-0m&&LixIg>?Y(P|TF5X913m$`8=3=GHMV_ojbbMN(qjduv(=(?S!A*eQN3D)O zp`tgz@1P4vnge>ahYHcPHN7!FA?RUJgKYtxvIi620lzZxXEgFtQ6n?Gr#JTgQS6=Q z%Pr7}FvNsYO}5^9m^}r`r%dtkH5Bs^!7Z2|_0a(~+-=C3u<1U(ndI@@8H&ew<~Mk% zrublzXOOT%>)gH|Ls}hWPncQqy*iII{9xo< zY8sc(T|sjP&2?PfDRWsoxv*83HYRhC;&t-H4P;JD-e`H58w6>X@F2*%AV|8bA7i~9 z1V8t~IPVef;o6qae1zs>G#}Q;8#*CfI*b{wBs7C1DCC@itfXA&x87Io>sVS-wcxG@5kTbj{|MF8vo+{Xl{M literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-39.pyc b/UIKatabatic/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae000a85be180a6023b77b1c71b2db414d486331 GIT binary patch literal 1641 zcmcIkUuzRV5Z~RqB$qTvBP|Llf<6dAZ0(aEwNzWRMNP#-rAOenWY>7@4OOF-R%8l_TO)2=O(OFN(9>4-JiXOE+IcqnQvetn;>co z9VeW|q)&ZH5wn=}9pACoiCy0Xn-k~!+zY~8o;xNyC!C4n=Rwc&0_X*+7X;-VFCLQ# z^*z8PzF=_?aG6&uE&;CcMT-}>(EJhY)(2)-3R^a#2 z{N^*)B_{5rPE}!`JX;PaWF`Ovqsk#ZBCI|G0j^P_Xg1m=oAJYss;jSBXW>~6> zi_xqzc?DJ&HOyCUd}t|21~ z*^K;&3pc>>A6$_5V`A!NEVDEQ3?zdcKkEY(kERcE(VbzHd;XU5l<_eZ!Ra0AClLi9<01d=3Uyg-31%EA(v)purwVKXI%vYf?_hM9Z7ac zd0B$=Da9TJ>}@|FdCdEM4POTg@L$+Nw{s}jN#msLOO@~wsdGs4eCI+2<#K_*bMu3L zHlL0W@;44nJ`N0~p~>F?7-2Ld9=?r`MuulZre{W$XHl|Sg|B9qi)_!1@?M^jha|pc z5$^1)P=bG2?jFk@k=Xc*FpK5FLR9pMQOPSsWv@)h0%11GKO-#9jeXM_=_11~Z?Led<{}$L)6h zz+u)QWx0JL-9AX%Ow(bm)+~%@7FbbBiX)N|D{Dz%_7X^3|r`Jf7`sY;ds{Z*){i@T4bV|Cb=_ae*PMih-0|B=b*tL8x;6 zMn`aXtq0(K+n4C%BTHG5hZ~+7K~MlEw{Lk4cJW7*g?kgbG&+J&D9Ho0sJ$h`p;B=SZ^v5%wc-5up% zXEAOi#2L>2mC5@8DAB7kx?dEy7)7AY`3l>KOaY3ad3 zmA^l;Fuz=%5w89^yRx`&uYP2R%Q*8b1aw~tZ=*^HIfOt$7fV!-*8qTYO}kAihC?Ty zS?GZ0mX-FZ&v!4McEn(j^Alwk7Ct{wP_k$GIc5Mtx&Y=iI(z1UdkBRMcrNHv8YB;n z@@ev9GKb}m^=y=D7nzM?&24_UUxOX=|AVKGEDKCBfst0Pm2`p$1@&jb@CGPIR2arLkc^RT8;*gI4zWH$@nG^u zU=M52G%T0~c0z$p2+l01>460mh-MXtw#^gu2&xs-Crv66b!25hh$W|9%coI@1MwjO z#-p;ZerTJ;NBHqQgi{9VWd0uXWs1okj$5hj_@{ zK9!4^>IY&|Dtonl_rY3SybC)%Gjqo@HN%DQ4kR%PhPg`}$XYCsmFK%xMtC}&c=`@8 zB~+Y(djvE8Nb~qrgk_;ouTkZ8VmRX&7vd%Ki7#Lm$J~i8arhO0W@vt8<$Q*w zUS#M&ysCdpz~m98N&}{@ozK)@f#q67IldnU5%+yn@cpR6dLi~pzK=JVR3eZ_@eTr( zLS@Pwshn;YBv7Uzxbh}}NaS`ac`V*XrH>J?1dE#ppCf#Ya0lVIjOiYplcESvh9<89 zI8eq4ZiN;m;XMKG!l1!;%%)l!_l*~B->+4~G|cjx9$ajYD1mVxOa$DnR~`ti<83QF ziO?cdT#ULMxU&h-5uSxYm4^_=o0vZL^)a8;XWXFp7U7KTE9Xv1+;{lP63;e=RtJbz*K_~? literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/ansi_test.py b/UIKatabatic/Lib/site-packages/colorama/tests/ansi_test.py new file mode 100644 index 00000000..0a20c80f --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/ansi_test.py @@ -0,0 +1,76 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main + +from ..ansi import Back, Fore, Style +from ..ansitowin32 import AnsiToWin32 + +stdout_orig = sys.stdout +stderr_orig = sys.stderr + + +class AnsiTest(TestCase): + + def setUp(self): + # sanity check: stdout should be a file or StringIO object. + # It will only be AnsiToWin32 if init() has previously wrapped it + self.assertNotEqual(type(sys.stdout), AnsiToWin32) + self.assertNotEqual(type(sys.stderr), AnsiToWin32) + + def tearDown(self): + sys.stdout = stdout_orig + sys.stderr = stderr_orig + + + def testForeAttributes(self): + self.assertEqual(Fore.BLACK, '\033[30m') + self.assertEqual(Fore.RED, '\033[31m') + self.assertEqual(Fore.GREEN, '\033[32m') + self.assertEqual(Fore.YELLOW, '\033[33m') + self.assertEqual(Fore.BLUE, '\033[34m') + self.assertEqual(Fore.MAGENTA, '\033[35m') + self.assertEqual(Fore.CYAN, '\033[36m') + self.assertEqual(Fore.WHITE, '\033[37m') + self.assertEqual(Fore.RESET, '\033[39m') + + # Check the light, extended versions. + self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m') + self.assertEqual(Fore.LIGHTRED_EX, '\033[91m') + self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m') + self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m') + self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m') + self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m') + self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m') + self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m') + + + def testBackAttributes(self): + self.assertEqual(Back.BLACK, '\033[40m') + self.assertEqual(Back.RED, '\033[41m') + self.assertEqual(Back.GREEN, '\033[42m') + self.assertEqual(Back.YELLOW, '\033[43m') + self.assertEqual(Back.BLUE, '\033[44m') + self.assertEqual(Back.MAGENTA, '\033[45m') + self.assertEqual(Back.CYAN, '\033[46m') + self.assertEqual(Back.WHITE, '\033[47m') + self.assertEqual(Back.RESET, '\033[49m') + + # Check the light, extended versions. + self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m') + self.assertEqual(Back.LIGHTRED_EX, '\033[101m') + self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m') + self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m') + self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m') + self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m') + self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m') + self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m') + + + def testStyleAttributes(self): + self.assertEqual(Style.DIM, '\033[2m') + self.assertEqual(Style.NORMAL, '\033[22m') + self.assertEqual(Style.BRIGHT, '\033[1m') + + +if __name__ == '__main__': + main() diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/ansitowin32_test.py b/UIKatabatic/Lib/site-packages/colorama/tests/ansitowin32_test.py new file mode 100644 index 00000000..91ca551f --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/ansitowin32_test.py @@ -0,0 +1,294 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from io import StringIO, TextIOWrapper +from unittest import TestCase, main +try: + from contextlib import ExitStack +except ImportError: + # python 2 + from contextlib2 import ExitStack + +try: + from unittest.mock import MagicMock, Mock, patch +except ImportError: + from mock import MagicMock, Mock, patch + +from ..ansitowin32 import AnsiToWin32, StreamWrapper +from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING +from .utils import osname + + +class StreamWrapperTest(TestCase): + + def testIsAProxy(self): + mockStream = Mock() + wrapper = StreamWrapper(mockStream, None) + self.assertTrue( wrapper.random_attr is mockStream.random_attr ) + + def testDelegatesWrite(self): + mockStream = Mock() + mockConverter = Mock() + wrapper = StreamWrapper(mockStream, mockConverter) + wrapper.write('hello') + self.assertTrue(mockConverter.write.call_args, (('hello',), {})) + + def testDelegatesContext(self): + mockConverter = Mock() + s = StringIO() + with StreamWrapper(s, mockConverter) as fp: + fp.write(u'hello') + self.assertTrue(s.closed) + + def testProxyNoContextManager(self): + mockStream = MagicMock() + mockStream.__enter__.side_effect = AttributeError() + mockConverter = Mock() + with self.assertRaises(AttributeError) as excinfo: + with StreamWrapper(mockStream, mockConverter) as wrapper: + wrapper.write('hello') + + def test_closed_shouldnt_raise_on_closed_stream(self): + stream = StringIO() + stream.close() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) + + def test_closed_shouldnt_raise_on_detached_stream(self): + stream = TextIOWrapper(StringIO()) + stream.detach() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) + +class AnsiToWin32Test(TestCase): + + def testInit(self): + mockStdout = Mock() + auto = Mock() + stream = AnsiToWin32(mockStdout, autoreset=auto) + self.assertEqual(stream.wrapped, mockStdout) + self.assertEqual(stream.autoreset, auto) + + @patch('colorama.ansitowin32.winterm', None) + @patch('colorama.ansitowin32.winapi_test', lambda *_: True) + def testStripIsTrueOnWindows(self): + with osname('nt'): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + self.assertTrue(stream.strip) + + def testStripIsFalseOffWindows(self): + with osname('posix'): + mockStdout = Mock(closed=False) + stream = AnsiToWin32(mockStdout) + self.assertFalse(stream.strip) + + def testWriteStripsAnsi(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + stream.wrapped = Mock() + stream.write_and_convert = Mock() + stream.strip = True + + stream.write('abc') + + self.assertFalse(stream.wrapped.write.called) + self.assertEqual(stream.write_and_convert.call_args, (('abc',), {})) + + def testWriteDoesNotStripAnsi(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + stream.wrapped = Mock() + stream.write_and_convert = Mock() + stream.strip = False + stream.convert = False + + stream.write('abc') + + self.assertFalse(stream.write_and_convert.called) + self.assertEqual(stream.wrapped.write.call_args, (('abc',), {})) + + def assert_autoresets(self, convert, autoreset=True): + stream = AnsiToWin32(Mock()) + stream.convert = convert + stream.reset_all = Mock() + stream.autoreset = autoreset + stream.winterm = Mock() + + stream.write('abc') + + self.assertEqual(stream.reset_all.called, autoreset) + + def testWriteAutoresets(self): + self.assert_autoresets(convert=True) + self.assert_autoresets(convert=False) + self.assert_autoresets(convert=True, autoreset=False) + self.assert_autoresets(convert=False, autoreset=False) + + def testWriteAndConvertWritesPlainText(self): + stream = AnsiToWin32(Mock()) + stream.write_and_convert( 'abc' ) + self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) ) + + def testWriteAndConvertStripsAllValidAnsi(self): + stream = AnsiToWin32(Mock()) + stream.call_win32 = Mock() + data = [ + 'abc\033[mdef', + 'abc\033[0mdef', + 'abc\033[2mdef', + 'abc\033[02mdef', + 'abc\033[002mdef', + 'abc\033[40mdef', + 'abc\033[040mdef', + 'abc\033[0;1mdef', + 'abc\033[40;50mdef', + 'abc\033[50;30;40mdef', + 'abc\033[Adef', + 'abc\033[0Gdef', + 'abc\033[1;20;128Hdef', + ] + for datum in data: + stream.wrapped.write.reset_mock() + stream.write_and_convert( datum ) + self.assertEqual( + [args[0] for args in stream.wrapped.write.call_args_list], + [ ('abc',), ('def',) ] + ) + + def testWriteAndConvertSkipsEmptySnippets(self): + stream = AnsiToWin32(Mock()) + stream.call_win32 = Mock() + stream.write_and_convert( '\033[40m\033[41m' ) + self.assertFalse( stream.wrapped.write.called ) + + def testWriteAndConvertCallsWin32WithParamsAndCommand(self): + stream = AnsiToWin32(Mock()) + stream.convert = True + stream.call_win32 = Mock() + stream.extract_params = Mock(return_value='params') + data = { + 'abc\033[adef': ('a', 'params'), + 'abc\033[;;bdef': ('b', 'params'), + 'abc\033[0cdef': ('c', 'params'), + 'abc\033[;;0;;Gdef': ('G', 'params'), + 'abc\033[1;20;128Hdef': ('H', 'params'), + } + for datum, expected in data.items(): + stream.call_win32.reset_mock() + stream.write_and_convert( datum ) + self.assertEqual( stream.call_win32.call_args[0], expected ) + + def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self): + stream = StringIO() + converter = AnsiToWin32(stream) + stream.close() + + converter.reset_all() + + def test_wrap_shouldnt_raise_on_closed_orig_stdout(self): + stream = StringIO() + stream.close() + with \ + patch("colorama.ansitowin32.os.name", "nt"), \ + patch("colorama.ansitowin32.winapi_test", lambda: True): + converter = AnsiToWin32(stream) + self.assertTrue(converter.strip) + self.assertFalse(converter.convert) + + def test_wrap_shouldnt_raise_on_missing_closed_attr(self): + with \ + patch("colorama.ansitowin32.os.name", "nt"), \ + patch("colorama.ansitowin32.winapi_test", lambda: True): + converter = AnsiToWin32(object()) + self.assertTrue(converter.strip) + self.assertFalse(converter.convert) + + def testExtractParams(self): + stream = AnsiToWin32(Mock()) + data = { + '': (0,), + ';;': (0,), + '2': (2,), + ';;002;;': (2,), + '0;1': (0, 1), + ';;003;;456;;': (3, 456), + '11;22;33;44;55': (11, 22, 33, 44, 55), + } + for datum, expected in data.items(): + self.assertEqual(stream.extract_params('m', datum), expected) + + def testCallWin32UsesLookup(self): + listener = Mock() + stream = AnsiToWin32(listener) + stream.win32_calls = { + 1: (lambda *_, **__: listener(11),), + 2: (lambda *_, **__: listener(22),), + 3: (lambda *_, **__: listener(33),), + } + stream.call_win32('m', (3, 1, 99, 2)) + self.assertEqual( + [a[0][0] for a in listener.call_args_list], + [33, 11, 22] ) + + def test_osc_codes(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout, convert=True) + with patch('colorama.ansitowin32.winterm') as winterm: + data = [ + '\033]0\x07', # missing arguments + '\033]0;foo\x08', # wrong OSC command + '\033]0;colorama_test_title\x07', # should work + '\033]1;colorama_test_title\x07', # wrong set command + '\033]2;colorama_test_title\x07', # should work + '\033]' + ';' * 64 + '\x08', # see issue #247 + ] + for code in data: + stream.write(code) + self.assertEqual(winterm.set_title.call_count, 2) + + def test_native_windows_ansi(self): + with ExitStack() as stack: + def p(a, b): + stack.enter_context(patch(a, b, create=True)) + # Pretend to be on Windows + p("colorama.ansitowin32.os.name", "nt") + p("colorama.ansitowin32.winapi_test", lambda: True) + p("colorama.win32.winapi_test", lambda: True) + p("colorama.winterm.win32.windll", "non-None") + p("colorama.winterm.get_osfhandle", lambda _: 1234) + + # Pretend that our mock stream has native ANSI support + p( + "colorama.winterm.win32.GetConsoleMode", + lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) + SetConsoleMode = Mock() + p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) + + stdout = Mock() + stdout.closed = False + stdout.isatty.return_value = True + stdout.fileno.return_value = 1 + + # Our fake console says it has native vt support, so AnsiToWin32 should + # enable that support and do nothing else. + stream = AnsiToWin32(stdout) + SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) + self.assertFalse(stream.strip) + self.assertFalse(stream.convert) + self.assertFalse(stream.should_wrap()) + + # Now let's pretend we're on an old Windows console, that doesn't have + # native ANSI support. + p("colorama.winterm.win32.GetConsoleMode", lambda _: 0) + SetConsoleMode = Mock() + p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) + + stream = AnsiToWin32(stdout) + SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) + self.assertTrue(stream.strip) + self.assertTrue(stream.convert) + self.assertTrue(stream.should_wrap()) + + +if __name__ == '__main__': + main() diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/initialise_test.py b/UIKatabatic/Lib/site-packages/colorama/tests/initialise_test.py new file mode 100644 index 00000000..89f9b075 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/initialise_test.py @@ -0,0 +1,189 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main, skipUnless + +try: + from unittest.mock import patch, Mock +except ImportError: + from mock import patch, Mock + +from ..ansitowin32 import StreamWrapper +from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests +from .utils import osname, replace_by + +orig_stdout = sys.stdout +orig_stderr = sys.stderr + + +class InitTest(TestCase): + + @skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty") + def setUp(self): + # sanity check + self.assertNotWrapped() + + def tearDown(self): + _wipe_internal_state_for_tests() + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + def assertWrapped(self): + self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped') + self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped') + self.assertTrue(isinstance(sys.stdout, StreamWrapper), + 'bad stdout wrapper') + self.assertTrue(isinstance(sys.stderr, StreamWrapper), + 'bad stderr wrapper') + + def assertNotWrapped(self): + self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped') + self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped') + + @patch('colorama.initialise.reset_all') + @patch('colorama.ansitowin32.winapi_test', lambda *_: True) + @patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False) + def testInitWrapsOnWindows(self, _): + with osname("nt"): + init() + self.assertWrapped() + + @patch('colorama.initialise.reset_all') + @patch('colorama.ansitowin32.winapi_test', lambda *_: False) + def testInitDoesntWrapOnEmulatedWindows(self, _): + with osname("nt"): + init() + self.assertNotWrapped() + + def testInitDoesntWrapOnNonWindows(self): + with osname("posix"): + init() + self.assertNotWrapped() + + def testInitDoesntWrapIfNone(self): + with replace_by(None): + init() + # We can't use assertNotWrapped here because replace_by(None) + # changes stdout/stderr already. + self.assertIsNone(sys.stdout) + self.assertIsNone(sys.stderr) + + def testInitAutoresetOnWrapsOnAllPlatforms(self): + with osname("posix"): + init(autoreset=True) + self.assertWrapped() + + def testInitWrapOffDoesntWrapOnWindows(self): + with osname("nt"): + init(wrap=False) + self.assertNotWrapped() + + def testInitWrapOffIncompatibleWithAutoresetOn(self): + self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False)) + + @patch('colorama.win32.SetConsoleTextAttribute') + @patch('colorama.initialise.AnsiToWin32') + def testAutoResetPassedOn(self, mockATW32, _): + with osname("nt"): + init(autoreset=True) + self.assertEqual(len(mockATW32.call_args_list), 2) + self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True) + self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True) + + @patch('colorama.initialise.AnsiToWin32') + def testAutoResetChangeable(self, mockATW32): + with osname("nt"): + init() + + init(autoreset=True) + self.assertEqual(len(mockATW32.call_args_list), 4) + self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True) + self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True) + + init() + self.assertEqual(len(mockATW32.call_args_list), 6) + self.assertEqual( + mockATW32.call_args_list[4][1]['autoreset'], False) + self.assertEqual( + mockATW32.call_args_list[5][1]['autoreset'], False) + + + @patch('colorama.initialise.atexit.register') + def testAtexitRegisteredOnlyOnce(self, mockRegister): + init() + self.assertTrue(mockRegister.called) + mockRegister.reset_mock() + init() + self.assertFalse(mockRegister.called) + + +class JustFixWindowsConsoleTest(TestCase): + def _reset(self): + _wipe_internal_state_for_tests() + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + def tearDown(self): + self._reset() + + @patch("colorama.ansitowin32.winapi_test", lambda: True) + def testJustFixWindowsConsole(self): + if sys.platform != "win32": + # just_fix_windows_console should be a no-op + just_fix_windows_console() + self.assertIs(sys.stdout, orig_stdout) + self.assertIs(sys.stderr, orig_stderr) + else: + def fake_std(): + # Emulate stdout=not a tty, stderr=tty + # to check that we handle both cases correctly + stdout = Mock() + stdout.closed = False + stdout.isatty.return_value = False + stdout.fileno.return_value = 1 + sys.stdout = stdout + + stderr = Mock() + stderr.closed = False + stderr.isatty.return_value = True + stderr.fileno.return_value = 2 + sys.stderr = stderr + + for native_ansi in [False, True]: + with patch( + 'colorama.ansitowin32.enable_vt_processing', + lambda *_: native_ansi + ): + self._reset() + fake_std() + + # Regular single-call test + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(sys.stdout, prev_stdout) + if native_ansi: + self.assertIs(sys.stderr, prev_stderr) + else: + self.assertIsNot(sys.stderr, prev_stderr) + + # second call without resetting is always a no-op + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(sys.stdout, prev_stdout) + self.assertIs(sys.stderr, prev_stderr) + + self._reset() + fake_std() + + # If init() runs first, just_fix_windows_console should be a no-op + init() + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(prev_stdout, sys.stdout) + self.assertIs(prev_stderr, sys.stderr) + + +if __name__ == '__main__': + main() diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/isatty_test.py b/UIKatabatic/Lib/site-packages/colorama/tests/isatty_test.py new file mode 100644 index 00000000..0f84e4be --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/isatty_test.py @@ -0,0 +1,57 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main + +from ..ansitowin32 import StreamWrapper, AnsiToWin32 +from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY + + +def is_a_tty(stream): + return StreamWrapper(stream, None).isatty() + +class IsattyTest(TestCase): + + def test_TTY(self): + tty = StreamTTY() + self.assertTrue(is_a_tty(tty)) + with pycharm(): + self.assertTrue(is_a_tty(tty)) + + def test_nonTTY(self): + non_tty = StreamNonTTY() + self.assertFalse(is_a_tty(non_tty)) + with pycharm(): + self.assertFalse(is_a_tty(non_tty)) + + def test_withPycharm(self): + with pycharm(): + self.assertTrue(is_a_tty(sys.stderr)) + self.assertTrue(is_a_tty(sys.stdout)) + + def test_withPycharmTTYOverride(self): + tty = StreamTTY() + with pycharm(), replace_by(tty): + self.assertTrue(is_a_tty(tty)) + + def test_withPycharmNonTTYOverride(self): + non_tty = StreamNonTTY() + with pycharm(), replace_by(non_tty): + self.assertFalse(is_a_tty(non_tty)) + + def test_withPycharmNoneOverride(self): + with pycharm(): + with replace_by(None), replace_original_by(None): + self.assertFalse(is_a_tty(None)) + self.assertFalse(is_a_tty(StreamNonTTY())) + self.assertTrue(is_a_tty(StreamTTY())) + + def test_withPycharmStreamWrapped(self): + with pycharm(): + self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty()) + self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty()) + self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty()) + self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty()) + + +if __name__ == '__main__': + main() diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/utils.py b/UIKatabatic/Lib/site-packages/colorama/tests/utils.py new file mode 100644 index 00000000..472fafb4 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/utils.py @@ -0,0 +1,49 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from contextlib import contextmanager +from io import StringIO +import sys +import os + + +class StreamTTY(StringIO): + def isatty(self): + return True + +class StreamNonTTY(StringIO): + def isatty(self): + return False + +@contextmanager +def osname(name): + orig = os.name + os.name = name + yield + os.name = orig + +@contextmanager +def replace_by(stream): + orig_stdout = sys.stdout + orig_stderr = sys.stderr + sys.stdout = stream + sys.stderr = stream + yield + sys.stdout = orig_stdout + sys.stderr = orig_stderr + +@contextmanager +def replace_original_by(stream): + orig_stdout = sys.__stdout__ + orig_stderr = sys.__stderr__ + sys.__stdout__ = stream + sys.__stderr__ = stream + yield + sys.__stdout__ = orig_stdout + sys.__stderr__ = orig_stderr + +@contextmanager +def pycharm(): + os.environ["PYCHARM_HOSTED"] = "1" + non_tty = StreamNonTTY() + with replace_by(non_tty), replace_original_by(non_tty): + yield + del os.environ["PYCHARM_HOSTED"] diff --git a/UIKatabatic/Lib/site-packages/colorama/tests/winterm_test.py b/UIKatabatic/Lib/site-packages/colorama/tests/winterm_test.py new file mode 100644 index 00000000..d0955f9e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/tests/winterm_test.py @@ -0,0 +1,131 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main, skipUnless + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch + +from ..winterm import WinColor, WinStyle, WinTerm + + +class WinTermTest(TestCase): + + @patch('colorama.winterm.win32') + def testInit(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 7 + 6 * 16 + 8 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + self.assertEqual(term._fore, 7) + self.assertEqual(term._back, 6) + self.assertEqual(term._style, 8) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testGetAttrs(self): + term = WinTerm() + + term._fore = 0 + term._back = 0 + term._style = 0 + self.assertEqual(term.get_attrs(), 0) + + term._fore = WinColor.YELLOW + self.assertEqual(term.get_attrs(), WinColor.YELLOW) + + term._back = WinColor.MAGENTA + self.assertEqual( + term.get_attrs(), + WinColor.YELLOW + WinColor.MAGENTA * 16) + + term._style = WinStyle.BRIGHT + self.assertEqual( + term.get_attrs(), + WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT) + + @patch('colorama.winterm.win32') + def testResetAll(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 1 + 2 * 16 + 8 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + + term.set_console = Mock() + term._fore = -1 + term._back = -1 + term._style = -1 + + term.reset_all() + + self.assertEqual(term._fore, 1) + self.assertEqual(term._back, 2) + self.assertEqual(term._style, 8) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testFore(self): + term = WinTerm() + term.set_console = Mock() + term._fore = 0 + + term.fore(5) + + self.assertEqual(term._fore, 5) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testBack(self): + term = WinTerm() + term.set_console = Mock() + term._back = 0 + + term.back(5) + + self.assertEqual(term._back, 5) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testStyle(self): + term = WinTerm() + term.set_console = Mock() + term._style = 0 + + term.style(22) + + self.assertEqual(term._style, 22) + self.assertEqual(term.set_console.called, True) + + @patch('colorama.winterm.win32') + def testSetConsole(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 0 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + term.windll = Mock() + + term.set_console() + + self.assertEqual( + mockWin32.SetConsoleTextAttribute.call_args, + ((mockWin32.STDOUT, term.get_attrs()), {}) + ) + + @patch('colorama.winterm.win32') + def testSetConsoleOnStderr(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 0 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + term.windll = Mock() + + term.set_console(on_stderr=True) + + self.assertEqual( + mockWin32.SetConsoleTextAttribute.call_args, + ((mockWin32.STDERR, term.get_attrs()), {}) + ) + + +if __name__ == '__main__': + main() diff --git a/UIKatabatic/Lib/site-packages/colorama/win32.py b/UIKatabatic/Lib/site-packages/colorama/win32.py new file mode 100644 index 00000000..841b0e27 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/win32.py @@ -0,0 +1,180 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + _GetConsoleMode = windll.kernel32.GetConsoleMode + _GetConsoleMode.argtypes = [ + wintypes.HANDLE, + POINTER(wintypes.DWORD) + ] + _GetConsoleMode.restype = wintypes.BOOL + + _SetConsoleMode = windll.kernel32.SetConsoleMode + _SetConsoleMode.argtypes = [ + wintypes.HANDLE, + wintypes.DWORD + ] + _SetConsoleMode.restype = wintypes.BOOL + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in + (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = _GetStdHandle(stream_id) + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = _GetStdHandle(stream_id) + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = _GetStdHandle(stream_id) + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = _GetStdHandle(stream_id) + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = _GetStdHandle(stream_id) + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) + + def GetConsoleMode(handle): + mode = wintypes.DWORD() + success = _GetConsoleMode(handle, byref(mode)) + if not success: + raise ctypes.WinError() + return mode.value + + def SetConsoleMode(handle, mode): + success = _SetConsoleMode(handle, mode) + if not success: + raise ctypes.WinError() diff --git a/UIKatabatic/Lib/site-packages/colorama/winterm.py b/UIKatabatic/Lib/site-packages/colorama/winterm.py new file mode 100644 index 00000000..aad867e8 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/colorama/winterm.py @@ -0,0 +1,195 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +try: + from msvcrt import get_osfhandle +except ImportError: + def get_osfhandle(_): + raise OSError("This isn't windows!") + + +from . import win32 + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + self._light = 0 + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + elif mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + elif mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) + + +def enable_vt_processing(fd): + if win32.windll is None or not win32.winapi_test(): + return False + + try: + handle = get_osfhandle(fd) + mode = win32.GetConsoleMode(handle) + win32.SetConsoleMode( + handle, + mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) + + mode = win32.GetConsoleMode(handle) + if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING: + return True + # Can get TypeError in testsuite where 'fd' is a Mock() + except (OSError, TypeError): + return False diff --git a/UIKatabatic/Lib/site-packages/distutils-precedence.pth b/UIKatabatic/Lib/site-packages/distutils-precedence.pth new file mode 100644 index 00000000..6de4198f --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/LICENSE.txt b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/METADATA b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/METADATA new file mode 100644 index 00000000..c49ceb9a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/METADATA @@ -0,0 +1,81 @@ +Metadata-Version: 2.3 +Name: Flask +Version: 3.1.0 +Summary: A simple framework for building complex web applications. +Maintainer-email: Pallets +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Typing :: Typed +Requires-Dist: Werkzeug>=3.1 +Requires-Dist: Jinja2>=3.1.2 +Requires-Dist: itsdangerous>=2.2 +Requires-Dist: click>=8.1.3 +Requires-Dist: blinker>=1.9 +Requires-Dist: importlib-metadata>=3.6; python_version < '3.10' +Requires-Dist: asgiref>=3.2 ; extra == "async" +Requires-Dist: python-dotenv ; extra == "dotenv" +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/flask/ +Provides-Extra: async +Provides-Extra: dotenv + +# Flask + +Flask is a lightweight [WSGI][] web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around [Werkzeug][] +and [Jinja][], and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +[WSGI]: https://wsgi.readthedocs.io/ +[Werkzeug]: https://werkzeug.palletsprojects.com/ +[Jinja]: https://jinja.palletsprojects.com/ + + +## A Simple Example + +```python +# save this as app.py +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def hello(): + return "Hello, World!" +``` + +``` +$ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + + +## Donate + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/RECORD b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/RECORD new file mode 100644 index 00000000..8a8da112 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/RECORD @@ -0,0 +1,58 @@ +../../Scripts/flask.exe,sha256=tK1QVTPCepWa9ySCA5BWJodpzZx5s0-JLPEoeSUWiow,106354 +flask-3.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask-3.1.0.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +flask-3.1.0.dist-info/METADATA,sha256=Wvf66xwUclGRu89cNcvErpaMf1rMgcxeqIkTc4EmD90,2718 +flask-3.1.0.dist-info/RECORD,, +flask-3.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask-3.1.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 +flask-3.1.0.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40 +flask/__init__.py,sha256=6xMqdVA0FIQ2U1KVaGX3lzNCdXPzoHPaa0hvQCNcfSk,2625 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-39.pyc,, +flask/__pycache__/__main__.cpython-39.pyc,, +flask/__pycache__/app.cpython-39.pyc,, +flask/__pycache__/blueprints.cpython-39.pyc,, +flask/__pycache__/cli.cpython-39.pyc,, +flask/__pycache__/config.cpython-39.pyc,, +flask/__pycache__/ctx.cpython-39.pyc,, +flask/__pycache__/debughelpers.cpython-39.pyc,, +flask/__pycache__/globals.cpython-39.pyc,, +flask/__pycache__/helpers.cpython-39.pyc,, +flask/__pycache__/logging.cpython-39.pyc,, +flask/__pycache__/sessions.cpython-39.pyc,, +flask/__pycache__/signals.cpython-39.pyc,, +flask/__pycache__/templating.cpython-39.pyc,, +flask/__pycache__/testing.cpython-39.pyc,, +flask/__pycache__/typing.cpython-39.pyc,, +flask/__pycache__/views.cpython-39.pyc,, +flask/__pycache__/wrappers.cpython-39.pyc,, +flask/app.py,sha256=GE7QOE_N9THDjuzKx0gUI9aF4hLh0xwBDa7hLVsjy-o,61725 +flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541 +flask/cli.py,sha256=XdmkBD74SnT0jrt2gqyHrE9oXGdWlcdTrJQR-i5aApY,37093 +flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219 +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=7njmzkFJvrPSQudsgONsgQzaGrGppeBINevKgWescPk,23521 +flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602 +flask/json/__pycache__/__init__.cpython-39.pyc,, +flask/json/__pycache__/provider.cpython-39.pyc,, +flask/json/__pycache__/tag.cpython-39.pyc,, +flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672 +flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281 +flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228 +flask/sansio/__pycache__/app.cpython-39.pyc,, +flask/sansio/__pycache__/blueprints.cpython-39.pyc,, +flask/sansio/__pycache__/scaffold.cpython-39.pyc,, +flask/sansio/app.py,sha256=Wj9NVGtiR1jvkZ9gSFd91usUlM8H0g06aPVz2sMh4bw,38116 +flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637 +flask/sansio/scaffold.py,sha256=q6wM4Y4aYMGGN_Litsj3PYKpBS3Zvut0xhDmpBEHFdo,30387 +flask/sessions.py,sha256=pImSFQIDCPtV-XSI8ttAyTTbvtRMkhDeqJ8VPZZUaf0,15430 +flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750 +flask/templating.py,sha256=2TcXLT85Asflm2W9WOSFxKCmYn5e49w_Jkg9-NaaJWo,7537 +flask/testing.py,sha256=5Dxg6VZ0ZPhjwG9ReUl4TrhvkjBYvgIzV949jkY0jIU,10100 +flask/typing.py,sha256=b7mMBIeAoOcAI_vFzzhfOm7KeZ_n868SIMw6xpX5KYQ,3166 +flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962 +flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406 diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/REQUESTED b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/WHEEL new file mode 100644 index 00000000..e3c6feef --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.10.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/entry_points.txt b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/entry_points.txt new file mode 100644 index 00000000..eec6733e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask-3.1.0.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +flask=flask.cli:main + diff --git a/UIKatabatic/Lib/site-packages/flask/__init__.py b/UIKatabatic/Lib/site-packages/flask/__init__.py new file mode 100644 index 00000000..e86eb43e --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/__main__.py b/UIKatabatic/Lib/site-packages/flask/__main__.py new file mode 100644 index 00000000..4e28416e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97715bdb050828880d1056432cf65a4426666ab2 GIT binary patch literal 2269 zcmb`I+ix316vlVgm-Qu%b9L^?=IS_2on8VG1tCfcQU&TmONBJDv|4+{&enTlcHA^o z`U1T2#48W*$iK9&NJ#w`fCs)awc9AXV#l9<^UZkX%$YMAuU4xVc%2^nIk*q{gBn*~ zIW#^q3^V=5Gz@NVGcZDvnI^FnSS-hLJRju40xQ7F@j_4xZDwmO2Bomf%9`z<5>{DN zb19e#YpkZZ44!7wnk(Qst81=;XV{G9sbDsoV{@8o;CVK$c^bUH7Bttvi)>NzOwb6I z*plX1@G@K0JO^H3E1KuQt87*C0(gzBX*|S4R%BG9{89YYu*oThHci?d;mUSCz_k!TkMwRL-1{OTXQS86W(QaH6MXb*(vx2 zKjt@ov3Q%G{FrASaOs3ZOAxu-wuf7 zg|?LxUg)0t>g>uc?2!!Iek?JIFmQQ% zPTOvD1tzATBTfe~-WGZm2l4ydioh&;JLl4I9uZPsQX1OVHAJLiCL6o@3M6epytoMWMC+{k)^kjTkSq{Tr6;%6v zbkVZ1eB^~9D@vh8GU`!LPhRu{Ea3Bio`RnNF7Xr`TJn@z+z5=)KJAs;|KG5lN-26_T#MTx-W#JN_1UGtG)X9n=|1wuh>oJ zU8OmG>Tp~p(L(`p$BVdg?gxR>6^;~P`~sdIIr`=~ciXqy&a+fFec@p*0zXu!N37(; z(rNl(f~pVvZaWmpkydmU_0rkzNLAn805=}^T<=h-9teT5x$@oegKzV^GF)K}tWg4pRMcl7>F zTo)y)T(_NE&@td{Q=ZYr-01?uFiZ5d@}`xuOzZEWJ!Q#{;kQ1_Dz4ifQCe|ql$@-n zE)r}wGgW5DJRFw8-IG)>tkRu40#jMkgK>ND7?d_Oay|7@mO!#hLjQ(kl{)M}5O=*G zl~ZKZNTx~Zy7LTM#@^)&S+gW_B=aN`y<8+|kSvibldO=eLYSTUgNPCfOm`CE0_p%J{BfyKQ0 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/__main__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/__main__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..140ff1c83e78eaacaecfd6af2e8a9a44bf27063e GIT binary patch literal 204 zcmYe~<>g`k0u!}o>2g5&F^GcCdCwImZa(yBqnDkrl%Iiq~#3$- literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/app.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/app.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f123e3c166ae7c25687b8158884849846d3be66f GIT binary patch literal 50308 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 HtndErx!e?99A*@6GSM-(yg( zS1mjr|LUK+|5&%IA84@nxEOqHS+@E+I^5!RYz^&>ZByTgosMJvmpU%~m*VoU(y3t1 z<>h#3=yg2Puf)s4YNu-YOYzFE)~T7k7uScYoi)>6M!(T%n0_^0AD-%*vMu30IxWA2 zw3YbG@NDO-ZQZhXjn|)Bye`&`N}W~iY+KFMA4%h;ov#E*lIlQ5X`;3;Ue?i2a1ra^ zN4r?zZHz{@WSWg=b(l#h672^g8lF}n;eKDHL!U=dggTW6B;$)X6C)WVn%2w)+d^lf zZJZ@&jgP%LN<@r-cVDOx6c8b4wfNMFfvujQBdm_iE%?t~{D@ND;|@M0SWRDe(zF%6 z^kU^Zt8a6UFF&ut-!8B6l^2fjhubM*&#D=(@y2tvQ{m^09G9QwXI{AcEI;?W+*$h0 za;=UBpS>kLD6y57l$M9@p3B9)+4_FEQQP zNDiipa+ju?E4iBlLy@mU!%-@=Zw7TmcM|&jH0DC)Ym;FnV}FG6@-;1nqZqE7uBe(R zDf-cqd|72Zo(_X3$!qkQi++&BTII_!O?4q)IgBHJm##IhNL-9e!j%QbQ@@69iE#We zI@&t2UfN@O?2JoecU&G<#!F*wygaVH0!p=WWQ{GqG`1eO_?CQN8y>T_n&rH#vJp)1 zd_PJe?fbF}ad`>n%T@HqekJ0*8OSxfkqv4PS(ZFS&1q`RP;-`=bJUzi^F5)+592^7 z-~ZnF>CW}`&O;@n+DU|nM>{u!daTpY&coaIyA$Z3M=ssD8})Wnq{Zb?5Izoeh1%&u z#N&^8Q_!l`=s>=M1L$D&3p7@}Vmq&Y{_U=N?%}B!z*|!j539ib1PVC#H)p*A*6wFX*zOi_iBr2wr;H0Nr|=J0#FyS=$} z!@qg^?xz3c#-II-Tburk&6^t!?>^`<${sU0q+ggO{b)CnCMU79Kb7&!TvKZy19e;M z0Ub8Q_gqX0D=E0T-AinL5QPJ#MI0+*e@~|SKnXb}Q|34xQThvFX#GtllvXoAQKGa6 zIB5|ulNk$_O{L=SOl3hFAFvT(PspGbiv_=IrJ9_MW%vsi&qi?+B5Fw>*{T2vHWYf0 zauy}#)lCB9OaX)L1%a&=+XKR(Za4^%UBTOJcCB?~ww`YC0R&H6a>AKVV(J$hH#6<( zH8w~ysor=_z_~f)O6$|vDV?|f>xFJLE3yI{=au3f^J=8%s2~Z2EYU;>v60s`NGApd zU=>%*lB6(`zohxHfuVe#UYLf_+q1hu6J>yIfJuJ>;oo6OQJ%8atBz;8PSvhChwslL z@{PMBWw+PDkkZoiX&54jS!z`y6p!q0?XmUJ8QZVyrwBsrzAWns=9gaK9R=y%N+t|9 zz?bCuy-4gc3PS=FL5vgBfVe%x7Ias~A>R(PmWbHJd=Fr6Fyv+cg>aK;By*%LgEJ|1 zBix*XSVZdVN({)%(Sc^iWll+>OF?{ms-PE4%ptFYUckZs5x{d`eKJoZhu1C~^TY)< z%#>z5go@B}KTg+>J6k9qmL_;;dY$z_p#154!Jf7I8A^?z*pxDr@&fKzE}_Y7ox5QG zVkQI`)>#Ciyhv|Pz_4K;I2DiM?_*Jcz*@!j+$vb2@$=z3a|E8;kUO&XQ#sT9%fCNd z)veq2zBWa{Hj0O)n|o3ygkmUicbIaKdm;%_9woa4bx>(JeF(2J%zlmmuxRhuvY}CC z5^A;m$az^%vi-_=3gY0U$Bw+F%OG&)h-k(1#weN$hRcBfmE0R4@dwC-g(3w9NP%Jl zlt5Q7fzYg$Kn@3GNaRWANhx{GC^JsIJQIKv8zI6`{7sV}YRL;=3QB|R?z5IjfUOi- z_){IaGnf~-asi<2Q6PiiOxrf2a*VX3^g7*-&i_!qHIqIOMxJjo;|G#rNYG?w1S8G0 z*u4Z9e_}C(C`ufv-2}fhlSP>rc1E09unG$#aqkE61Mu!eIE?xlgC+|SZbm(fUQ=cY zfRhUCM`R~a%X9^p4mU@R!#x-}5l{3neG26bXJTKpo1~ORPHyW(NgxjjOXrdKCg%A~ z>*_K28^jgH^WE-LD_Co;h-#3zai19~aHN)(f!y4dht2yFz$s8H%peaV?8%%W)lL1~ zGFzIqyo#O8N?!dF`PamD?xZSrO@Zt_N~6Toin&WNn&pCGKEftRg_hYae@nd+F`=T+Z__cKtJpVxf<8x#%2 zjHDlvrrazt(! zv#xoLl;~%u^`V5MDpY=gCa>s&5oMTP)4)T)CMa1NvX<}CDpRm8?Z#;@h*iPvO9NEc zC`3#m?X0UHK~2({g}X8*cGkAd` sZsp#-L|&j1h^!ZkpO*yQ9}16tMn6;)mDV*}j)w}MX3suO#jch90|M1%!T;sDh2!a$v(v&=+9w205Me1q8v@D7bQLzLuB=lO5UMzM7z=Dfi z@XmlFCJV(8X^T=qMRDRsY$*mE$BhytCu!0)Nz>NNNzx?k>1orRw4JnRnpf+Srl&bc z>XeqH{(j$`nOy*s?EKROcXl54HTQn^d;GrdUe*Q%iUvOS-tlL%fBLFn{4pQH!f_iY?pia z=8lD(m7Q{4XufY@S7n!+_cd=?xVdsO&Wmn;^Zg4>#gX$;^Ol9(mECeafb&}`x0;5x zY5ulXP31^?Zm-;q-@)b`3nP^gDQgqX_f+=C`4G-WE2ENsbMwxH4^%#28jl$6u)F1w z;coG^&F{UKsf@W>-5cC(uUYPm?)FP|rR?r-ce?Mx^)B}&T;GM~HzURSU(2|TdkgOD z!}ZPXZlt)?y$#p<(WblIH*oI`cLXW-yk@(j?wyyi7tP8&^6aPN*v1&R^kzc2l2-@e8@eB(jP=A z54(p@$|02SQS`|}Xv1N=%^lK)Bkob8Iw);;#631^xsSTvg<3x39dtj2Ry-`Jce;;B z>c`y)q-II?xlf?Q$C2)k``uUU%HcJoo^Veh-4RJQ={`AY;p`|&b)ULoxlc>^N8D#n z{v&ALvu*|Lt9TEgb;roJt{c-+@_OUq~7Ii#9Es)jp{RP$^RQayp+D49I@}5B1pY;0XPt2eEqUC<-^^E&sT+8M7=}Q})e#kw5 zK6_dEXs7%A?hoMa9{0*?MfVl=2QS$d&FlSDCcVk|Cs&_x4e#((3v-YC@T&Vm(hmm74{-2ICC6QI~iT-R6KzlRZe&O7D)<0O6GzRczt(ECgIdsNxBLlQ4=ydbwZN;MSGC1OPvK6n5qJx;UJ&T3$J_2w)0{5-tI?XR&Zzc6Re8;J&6T1Ckf^PK zsvjsk{<;}AsJ^6>*9xkr9|a7e=Bn#WFCl-kHp@DBhlNz#cHp(n;nu*(pr(Qop1+8< zkaj(N@{vamE-p43b$K;r#}jtQbQffLYkAt*`XJW8PmkMCuNsGq zi{?ru$aOLoP1ihQsi{uJ&F?_!^q#Fg735v!D16ay`{Li?>yRHWm~KC6{`8uf?VxY9 z*s-sg>gDj}j(ySSY0K9-*3*V=&C|x&mu(~Hf7M)u%w2)(4<8IlNN@Uo@PdIFOC1yS z4aD^g#=o27?$GOf7tK!g1(f!z;o2+N=d)*D*1!9VeJC0EH?M2)aNJ@WvvEs!{*lHx z55(i>K6e@|Kd80po)gS9dJ%x|CwY1a*_I`jqOznmGFnSxKEMseT z%pbDO;*Eq(G3km8KY0_BZ^2iX`H-&}T8957w(|TuW^`NbmQQpAF znu_+1>~*G>0;k?yYPt@XEZ9M_=`;f8d?T1^<4H};E|C@aaf_~*8P-=D<6uuGYOS+a^|F|*w&nK(Bs z{Mql=_~zcR^ZKb}=8$I496}1qvdkgNe%rRJw{!1US?ilS^Syc0K9n173(AM^CN<2n z=gQ^sUQJ)8BYV2tZoXkf=8SqD(ruV2G_ zTk{$41$)U*d!II*H{Hxh%%%D4ig|WWt}&OMH}`3ooejT!XwIvjan8?q-~meL36c|B zBN+ib(Ouk`no7rFY6|S4UR&}tqagbbN}SQ81cHelJANCoe2zuN93-J6;UB_zgll*l z;&M^W#}}yrI5XqUBnnO&63o>==rv!e@?6br#uuK~t@0PNn#Z%2cOe+H)IG=_S;4fXACaA; zAGH^UkK^m}mQg5y1`6h&W%XI#u&qMIvaPplTT-FoK#gWJxfU?}HMPoMvvtXb9F$)f z>_6%eg)2}3!|efw*j%+S{2AB2VqtJIPaCb15`MEA}izQ^Q!vwO)yz_2b!}@O-|cQ~Ixpcw}jPEbRr8&zLv7 zjV9wI1J?s0XtQp~9gyomxz0fd{x#aQY55P+b`46qq$J(0vwywMXbr7x@e5`+7z{z! z+ZU~sJl^ghl(HG3^kIn70(#*Nq~FxB(I%vtAC|U3V0Q|!$jq-4o-eeDuKZGD23uCQ zcJfzE7_Wan9PZ>hc-h41<4$CjH*i4e3Ma_{3Au=_Fi2ft)$Ev8*XRkJf6Y4ZSr zz?`AV%o~BZYT-9?)%;;mYu+%Sw<}C^LmlMdVH~2Y2uQFTX|HwW{JQ2s!J#M>1?O|f z;IrZ!_)hWdZ`1ZPTR66U6jPOegBkZ5XpWM4+zEGdle2SrhB~y#+QX9Y>R59L`+M}3 z@a`Uk1>;OofWAQ~F7&50r3P-LO(=)^53=rtyHWQN5kTFiJss2|^U~mn1`j5ruWwSJQB)<=ojiPi2g-@jqA-8;5#FFtgt>KL zQAIZAv^vfkxijabHd|DuyO@yb%z6?S-bkYtkj(!C4p3ce%iJysOYt2jC2tq(l9@AY zd`s3Kl$hc>whhq)r6mV-rI;<@T&FA|C!boP(pcuOy`3-=C7zO2p%F_w|*T%6Zfu{)X7Jnb}yL)K7`BkVgjbJelA z=W3u3RR`g8X&jGMNx5fIVH4k6~ zMhY}mNI^rr5MWAO#6${;9o)MJ=#Z&La}(-bwrl9=Im{|YQv&UV@Mg@Jmh-3}d%|5s z0%-eTyjTo3A4<((oy!qgAMGayrtd(J@9!xeM(7TX2Z_0#&Pf(*U-j;!In? zc&x%gi1M0veKFlMW9uO+O$9VR*U_|$#$V#Te;W=4*lWowWypF9CTz!dtc>+7+qTWE z7A#DwU>2-v13=O0XUd1#EzZJllfFEjz@gW&LHS^7IkHLX!1^-v;DSiD+JZX528bEa zOGM7~Tv}sw`A(<8|=X z`GT9f0^Zm$R{O4EvdG}&C!(w%fl=YSr_O}l((JYTan1F@d{L8mSS&srKXjl>X6x-{ zTa6Ygo0aD`nhgT9l+zgVs80`DvoReNU_aJ?AJ?M%IpCAT1hUdIkeu~77;lSUvmCEz zP_x-;oJ@TW-k9RGL8f#L7wS9@?5oOvv^Ggv8A@86+*vo8Q9lvlxZr+p2mz}M2tx`# zuqKMycWCw78T+kVPF+GJVc*zToF%;R@%{4A(QIVT0db8=;OA}MtBS@I z6{sW$E#?7tqp`D50Vf_XS5-&ZYd##~hsd!=(QDARsj)cPtOy&f~ayKDYVw6-vP29fu#XA z!B&S*!oMXS605mPcuIs^%d307U(<520oqo806bj~G|fgZ!aPvpL}qCkuy;O+AZjNF6<`&8)N`+kH=U@xtzRUeXiD;_1y7s=brL@ zX#pTw=b#Ihnh@61RF4M({*9R$;7cEX2qqOoIQm_xPHi-;H%v^bc~H%@o34*Z#iCX1 zM;f(+1L$=V4WpQ^ih{Qr_oG37jaMbwdcD?Y9!0*Ce0WaiLwFQ56%>*`)bDU*e-p!Hkh-4nks~#mzF#BA+#b8uYT0oO#&GvopzxRRk&Dz(j<#@SDwotG;^eHjQvpWr)S^XlhCm(~K44wn%ttlID_5ie?Nwy5QLA#?ydo)>+IwlzHsbnUTbY+^R7<pTGg2nEnD%}7>NYeG+Tm*c_-#e*ZIlK@7g#xoLBki}1g#qm8Kz2&)6r|vpE zDozOq9l-4uM3og~W7G=s=lxmwu0pD|_&qvmicAl`)YU4qQs>mVFP!i_jk2?WBjC~g z8E0$^#f&&@apUcEMvgvq@Z`s;2ag{gao|@>9EB;ABT!7u8HpQ#jLI3&4HRf%0g-q8=w?FT@;K3Qz}cQ8O0(L)*178%V-YR=l2&hCjpjtgTIHO3LT>{&Mv?F(J6W;PJcy&NyUEo8=*B7CS^yu7#ssNXW z3K)xkLzoT#IDqy*nqcbfp#%ZVH6WaY&iql3|11nL0BWv-*95Ddnj#rNpg;h$l~gq~ zH4V^W5uWiNeju~0);wQZ_MN%fIZQKgHYfEvwR6Dp2|4bS$ttC|9=usK_@^lAIp>vk zb_u{C<+pzQI;_X{kY0C}?@lM~B&Rm!a{R)AbHeX~mO!I({H5vir6C>9d$6zZi&swz zh+Bi&lTj!`5!qO%e#i8EdYMOWPsP>6GCC2PNzr}`jQXU)00$VDqE{a0ji-1>{WhQv z`Oxs<_x&WY58@;+e1|MPfUZqL3x<)gN~9ut75D=6>iOJdV-^hh%jOA!h!!F0uB_`v z8PR|y?W$ICgy3bWL<8a*1MigB34~%mRL7lLfrWmqeFmn(`bLuxKyclIA3fK^mhDSN z`en|u0-hRBbZL8syQLZwo=|G)O-(bw&GEg+Q7KW^N!p+=*8mLZs(uXTy1v(WCY5el zS8#__6Du+XZF6T{eFs&QG+)c4aRDW0zr34I?-ty?OQlNo zMGR9VM-dkl4lXW=LRSMrF+{Hg?03c|K8^XHIH7BtazJ?CG83gO(FUK_3Tlr&7-KzJ zeba(-+QV#XfWo1&f|{Li`pCwoV(OcMrk%{OE=v)TU#pBVphg#%!0eE;EoYop<5TN; zaw?vZ6PU7^Az|!hMDb=yCwYM$bv7np?y>qDf)UK0jH#3Pq7k>u5{GjxvbsVdNkE;CV_>t9XhGJxoU8Qz*qvvOQ~*T<4h07&l4VtWxh zOH`IFIk7~*bBU%_3iCVUxZuc!6qOV+MzIJCaraDNX$e>>uqnSFXqcV|!u zyIUxkE}M=;N)Ak7$bogypu4uq$)Rs05tdzCl#qkEidT%XQXr=Ix`FvB9`+3U8@T)#4gfpI$d};OO{yyE67tv8{y1=o znWKT2*y<4fAUIJ0yuGVnV4LYK`)Tj~qStQRsi;L+}x6n;d=tiuze^1I8LMcXuF-f**zn!yfd)QRJfP3Na*q9`{Yiz95 z)~Dg7lQ75SE*(e+JU@C&B&DrwgrgayWT|RTd(=_=_}KxXkVknJAz`{INC9iofmzcX!Zc~`Mlc?G@F4( zM6(CoP41ApIoA2P)}&O);VxF0K%ZoM@HY2G+{?SSxZ81e2g)3DcfJM-0MFj%?n0Rb zNx#*-DK6z^_x;GxCpJP6w7WafJ`GU@YFD#{agyPlz{hE`ii}NE`xqrogx-{+1+f4H zP_Y=U?u*_>I^t$N);-6dVZaKYs5&frGzq-@{9FSbYls8# zcv29Yzm!5T%w20qF-f4V*25d{68Ijh9fbbC*b!7?OyeJZVx7dHfAEnf2sTVdjeCsi z$Uev){G)%DZPw^mJnUE7^+&l@Yz^IXh`8~YL5k8sF4NNa~m+miIq+K;7O$F{FeRe%xOfQ<% z>x&sX2uX~FPfhKG!M9O3$M-#?Le(M)QsVlK>syP~VOlIMf#iWOa$>}5WKcT^2#PSu zPv+8IV3jEuOiews9xFf;Etvq;e|cY8$D`04x&D9xeeXKC zkxWa$B0xZ-@9WFIv^a_QN(lSiDLolI@`A|;?ZoDq0+J>8Z(g@~c?D64*g@ z2C;xpi8AVL+{*=sP=!-H)5)DP)x$6vwL*&H4r8@IK`2HgJTvpf85o(Je8bdHtW>Mu z80&`z$f%Y&2#cx?bWHUc)ZoEjlZF;?Hk6)imYU$wuMQ_p{G8~uzGytrPz>%-2MsWR z{mL-$Cu%=n5LGAwGmQ(CtZ2taN4G>a7gDI7zzZ`z2+he$O|dw&Lx5hso-yd>2*tD*^>dwAaxoyxKfN4;`5SlyB1M{DF@ff; z)y3x0Y$MI)j~28+`%hSpRQ6BT)TsU$FTchEhgR!`VuaFPagPN((7}n(w>67}0C0{l zv}4HH1{Vl@hq%K(E8KFF{vy#Ix*o(&BV!$^WctbAjHDzw`7=0y7Huf35!TTgh>Xjs z-NZPXSY5mV!f6$7Wi%1(56dSiRkS8E(bq};25>O z&g#BS>r^yzc*0h29u5jSOh6hRw`rG8B9!r8G3k9cM5ScZ#QN>&sFn;>T^jv2zB_D=fu)}cA^hv5TIgY46KJ?VC9xWM4#sn-F|0~N1zR6 zHiK*seq&*gsX(GvGK|<_gw;y!d2xd4Gl_67svii7tNj?_?2@UzfSSMuRtI9oLUw*I zY0*jJjod_-muMcNbmu{Q*h_{3|FDUqOzq*t2tSR8M`gM$gHp7K%}VwKfXXoX>Y@!c~1Q_)9m6w zB4O9fx&Md<4UYXzoB&eE(DjJ%NAzk5o{C-O_UsV-72A4dn>0iZao9(e^&Gg?>BOKE z2M$V1Kb(H)2>%=|x+6?zZxztqRTCT?W4#J)PS7aaiHU{6oq$5s`BV9zvM!qBLTLxJGN!E%F2bo_H*%LScdP`@pb%3JShA6%l zzX-wL8P=Tw%fJ^RmOSNoI26L(SHXB>SZP=pwzz3Y15za!VrvInTQA*9b159bX% zZ{AZ_b`k*#lcQL)(SKdono59XoMcUkd^{3;%7VH?QDz`<^j z8O~XL&AEMW^S1YG-C?}7>juSic%f(U6J^`5jg%Hi$eMn5p2PPLUPhch67?=99Vr*V zyCwsNz^p*QSK*`RAif@$h86zUB!Ql(DJghLTSLlQfT<*A7-HRL;V1;KF*QY)7%4;# zXK>FXEe-~Q0}~J}9eR9{s_anv7vz}MTw67uaKSv5NJm;nabYky7=Hk?0r3v>jY>gj zbFjcYr>6s7U%5Q&!6C{u^|}u5wneaUdHO&2wA<6{#L*UaU|H0$md z{{6&GSHU;14k0;*QlO3s1}(l$25OO+yI4B550L;+BTV%vw+MaiPONRP=CQVc*w+=y zh6>@UvlT?jG2B`f;a#zwKn~o4@&IMvOH=zYs_`Gwz|Fzu5i%N3*0y) z+B%of?xKs@LQgF7y)oi+eLH@Q$zFC2&L9#-ilf3u=z-uT^q1)rhyYq8=*Ql8g%go4 zEYAjx1_7BYA;of^*a;$qB{67{qQ!aQ6E+}BiUw$iK>T_nWLVE*ZLGP&WLblfPF3R~ zyY_I`gs!ehI_}H`!J1HTJ1$Un2RP*ZoUNqZ~9;}*O%>u1@uJphq_ zF2JD#_>+(}#8R)pUqn4lKy<<{vMhx*Kl_hQg%9+gCNnf*XnzZ{kX~}|Nk*;L{=V)) zT{NfZVWA#Z#tXO)!_wgrUsgtpPKvx9?$QhN^x`gS-T}=5?}obx^Z>HhKyp2RP}=r2 zz>v_$d$i*29*6@h(Af~Cmkf3syqn--N%zMA3Tfr~wWZs>!&;vv<7Ku4VZ&%7q)kF4 z$4v$d4uZB$*LI$qJUaHl_o!okxfi}UA=`EM7}z*eK|@SyNHBTT9-K#jVy~6H9vjm$ z?Hhh;1o6<I+Kk>Su3s)Y==p7A8>$yO+!FE zs?n!)&=aH-ac#6~p&aFwffl#VPeO+L2Xgq|!{I0{{(=|(69>i=B6gy#I|1Ic+ye-ew4-Xr3GK>d;3{q zL5nkyIO2=?LEMc>@ra6ki!H)*thb1_CAnlD0M!Oe#dYU7#E3DAgm+~ zHNK6yAH0R!^Ca`S2ECwXLpB|jC(x+XxSNF^Hiwlah>imc#*pKDcv==u2-@ZVLsS6* z8Di^F1LYc3W(2X&JJz8Ajvze(5ZWu$*O+ZV?}$O@WWylM{3gO}Afc1U!{?&*NlfC% zHFG4~ghz+DRgid4VJcf#f0Aj>%%C?Y?De>Q0%stUZuhM1`e@k4>JPwZY*uv|JNS6Y z&R`@;$Y!>~IcpVqnQ3 zu=ON8k8=$$Z7@oSEx{nwQ|e#iBz4H!P$+i;3ow_WMkc$f?tgAh4 z_z>$05Lya@s*|}2C;my|2T(hge=E%;<`$o>=72+SRX_#{Yrh=Vlow=5*Yx=`4=8SZ zO&v1_MHQeV%wH}zx&kE<>-?}9VZMmnBz~=v)6ZXsv56RO)&T$?eNw{Wc5ABJop>93 z=eS-#1||)s9h9F%&{-Tl4T6EIRlKL=C@aJk9?<2~+%b@zLke!paI-Ere&QHq%`NI` zc`<0uB2aCP5rfmf@R!T5=_)xaLxZru!oduPvKu>~{vikHn>a+dlanVNop>b5Vm^2( zD)pA7=)u-|-4we7oxoa0_^>5LK@cB~yWx zl=@p7hS@Z+c}zQtCAk^7TgTn>Ljq1MqMySBF#tM3B(e$wd&VLNN*30%gw(cyKr_qt zYf^KwD_Ba}8pPHeB)IH+77JStN#fd&8K3Uh>f>CJN(>tiTn3wxF_TTK}{5K^fR)@zaX%iR2S0-bQ2(g+n#572yyLExM z+6VfRSuDOTz_d2L*R8&_)_;Xd0mi z^)@_Nr5Wj^fQ>)v+%q)^E*sZ%j z9K&dQ+7IRMrW46}0O^vYHFLWRh30E$dz1kRt7Hy{zH}4cCqr^0GnV-V>O9ADnKCkY zuz{LU;VMXZJ;`0cR#Ct(1^Zh+hX$xrHQ;gZs_2A=Nv``)Al8&)PU!hk#0+7i4)#UB zjtBhJv&+sQ&fOZy07JG^9@W;FvG+s4gO3heUMrIYrw0HSuOE@15ni4JNfn~a zC%M=i?Ls_KFelRZ7dA>`i5aNXxg#LWNkX5r76de5z(rgHBYZ$pB2u3?2{$<A@Hq1QDGxCbXh&WV;|of^C&^VUlU$6;{y4A!){7PjoOxn~giC^Jz< zr>7svS|VC-HJGx=lI;94v|?U{HhGzgaxy)8#0ech8@m}f5RD0i8qz-{rOJTBHIrz_ zU^USQQ*)4h3GLNez>IAeB$(flr5mN(-8pVFQyG?JWr=fCx>dU^$wd=DR_M4Z1pX3L zYBypLiFCv=lef_fz3L%D2V%J6T^sW*Yo~;Bzbo2^?URfKtKevX{=|)-nWS5qd0k*CY%Z=Efjq{Q&W7b79~9yB{d;!{7dJ2l-_;)QG%I zHW+MkEn%}Q{!CZn(_&BT_e(XOeYjBrgU@I@B*DIQpK zxOHqyTM|0vQlE!U9ck6LNfYK?9Q-dlKeaiWhnG`>91|C+i5UH2u3!-Z*FJ&g>!?le za_qyw^#kQ_dmKXok6KTRC$8SDMkxZ%%j;`Q9#Aa2SB+TA$heR(Y~ccM$w#fcgd07% z6W+4%U1dF|&Vi0BhXaUjVVHzOxcK4YM|cq%=fdJ(F~}oVE;-Ey>DDE&>BO6|tI1I6 zqfB7vqWIIWZvf^W_SnIM;fAUtBZQICSjDJgB?bno8jqc#?2P(lBqVaxkA~tdq7@`B zp%Lvk3KRWm7&K35fPht)KDh}T)?nc<6u4p9q!=JmaAksdg$L*i1$qrk`zqWPo#IQ- zu-px+uU7h6xehjEOE+mNK3|kg+VCqb>@0Ru1-9(wfjI}Aeqi3fxN-gooO5||KXkYJ zMJUcRHDK6aGZ6&5WMOLLI|U%-eLxMkomyXwJWVq*qHWFVv9un{wu>3iMD1mNi%W_d zGhlxKz{3EN5G$L6RxYacxrW=_0}*E=C$Js|T6oMz%pyian8&ueoU0*>p5jtj1Ub~E z>*Yr=Ac zDeOegH9EhS+}8qb7cPGrB&AL0Ot>9lC-FmfWhy1{~-?o)-2)-Ha=Ita&H$!0vF6hgIcs#0OS2M?+&t*O*{W^w&RzLj?L!mz_bk2$kQfT=)y+CIB^VA& zz*ZJ^bZ4O{+*$c>?fHJuxGEN5&@!`3pFQiL#B z`@+3LFlR9q$sH|5ux_op1z0>;r35a3!Nw+<8HhVZ*9&bQyUS7kfIicJ+K(1U%r~|l zp{qtRCmtqDjG3jTfOdLiIrI691$X>b1KV^VKU$6@;|RhLJ&rq?N)fRbXJmL>S$CU~ zB+6VEO3y3BIzM{Pm{1{(*!B;SI?NRhE&_ZH`-_6GgTswGm4V~WP9A$=;^gGP6O&IK z=N>#>J=(&JGSVKOYq!r-s{qjZ4guI{5*~wsnA6}W;T5p#(VZ}N(P+J0)AOiQeIE~$ zN$RsWR0hP^fJz0+>j{=X43!4p)&EAi$VNzfOFhU_u4N>U6xq~j)PH3$!xGydgOIY3 z+nJcVqq*3$!b5CflNqI=(EO_G6?H39N)_wC$KOHjzaTde1ix6w40AJLZa0jrhHcoj+@0@UYcNZzmK#lB z*EBO{4}s4p=B?y(5M;P3-Hk}!NTFX0c$o?}<9MK#`&hsM2Zt-6da^7Fi)wu?u311# zH+m4;_D5M!q15eYbvXODUUv)nWf9m~he4MRR%NaRgX)F-tThG#LI;v88lav~qIqd; zEY2lLdCwL=n1#gg5FL=J_@elUG7dcxq(25%ADbB7EN^)1$ic(nyL{sK!O0HYLHz(&bOq9a2^|C|07@Uj8$*Lm41O`^XnyceSR2ySU+ z184o6LGGf_LhP<<&vBO)q@T~f1l1*7j$Y_kw0Thi_ThaA%nB~}XUGKS!FE@RaI@M>D;V=u?4WyF%9^p?FzUa--GY60!Gd2jXG|``xl{H~Lu#rR+$;!_YxXS=!*h>%)F)Q2@gdPc>lh1!GLT-8PezbbPA ze7Xx&M12QlJ#0$7s2;ozCcFkLZqaYIQIks3hSpw3-G;VR3P<8OUCBQl(>tfHx`WNJ zkD=B|-^rv=3jeVW?w-J0j~k}`3WW&#xTX(~tP9iZ#)ZH%J3;S;&^y$RO9hS{$6W(9 zqt==d*n`9*q!$?q)%%|T>_EQtJ!nbx4UKU{`O_dE=1RTr{y?nssYoIq48M_NdO(YOYg7BilF&{_26i| zo{hVhdo0+I`8}aEejqYeCUo@~=?ZlpyWm4Stdmge?WdAfjP6vwhN^S`aDGXFxz-ke z*h19fKX8FH-gTa;|H6cKAvbnsZY_&2Q7-TOHy%irvN}Mk<#2i-^oxf(c|d(ok^vWa z7t{$R_v8k4-+>*xhv$7>3;!zuAy@41F44&d-;=x_Kmk!!T2t91PGW2m7ITA2ajxd$ z|4N~()79O>)cHB+1lWnNlBLvuG(6vMflgo-c@O#l>PSY4ucIE|L2QA4iI&`qw)zj_ z#Mm?_YXNM;TNX_2X$tSVx&3XpQp}yQr6AW0*zms>5zStNb%2mqtRE=hcbmB#@?Eh! zbpeO)-y*UF`~dr0J4=DspULtv+Oiw;RT`QHW$93=uR>lEK1lrE5lYuybA(`Vqupq-!yynii%s`bCu0VjD2m_gz96ilFMD<34*n5B(^p4V-uz6(@ z`yxUw_scM-LAKNNicQ-(>aKYxgOX&;gX%EnC=aK2_&y$fgopch5W6%7w=>v$WCl^6 zEbPZRcV9Nli3(iN$vu~1TBn2B*Z;8&{Uw#6M(ANZc(MjvEwfabv)!F7%S1RRMySM8 z29pgh%cK}zT$lL&I-2cixO8O3lFqpSq_3@H?xq(FOg?-3NcGUMBZoc)C#d$o42ruP zy0cs6E@lEUs7rf5B8Q<51Zm`nqf^ly%+QYETel8yJ8=XLWd*qSo7|?Yo72>9+Qzjs%GB*lN%iR zUSnjqV7#;S@bKX9zO5s}n`p8OiQ7$FZ*S4@#*N1%$2aYKuR~7meM_gn`M1a_c@Mj; z!hM(frrnobTe-J!U9`;mKQag>9yTt&3tN;+YWY7}uGvM_v2(wa`F5@}Xcx`@2eCQ5 A8vpRaFY+@}Ja*8&ChPpFF`{hf2~42P18qy-9; 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 MGNy9n-1%4k8=fwKsQ>@~ literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/ctx.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/ctx.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d806cde081655d2b57478a1f10d73a5df3a6049 GIT binary patch literal 14658 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/helpers.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/helpers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac75e2d4232c46492b31e39d8a95ff707053bd2a GIT binary patch literal 21716 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/logging.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/logging.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39af824280f0f8b3500913186d767239eeff148a GIT binary patch literal 2499 zcmZuzOK;mo5Z)5do!wrz6MO6plio23%Q>47R ziX+3xB>~$0fL@BAu#fo%{Vlu}D3Eh+y|gn+%5my45xKjZnf+$=n~&y=MvcIA`}&{# zttugZ;N<*Ogvnh(sQwKGf(ROsA#GENV<&Rjj(rx|1^aZ{MR*pX(y-hvgN-YSQDs{EP(m9!vjZ@m5 zm-8nJFk2M!r}PweUjW-hu)HKLgXJaRJR;32?+|&DrZYT_6T?lI#Ciwjwe2L}(LXy#ninyx}(r)3#G3sn-Q z1*lnC%8K@us2O-^Z+~yDwRWFqsq}6vWi;BoC-uHbM!Qe8;Qs?|co(t>cDKXst`3d- ze8hu&-j{mU;<`1(HJYT07qQL3Ho62iQgdm|Q4JU!%}#x`;Y6fL-ENXZO(!kkI;2(x zqX1bvy^xkJ{0d0TyD&H=C*+j;49^$zn5q>+e}Exo=p>rrS)1Fk#Pxs!W&D-nu{UiHq*A8#~^>B0rzX@SR+w37Sjw2FGb`=AGDX#}kj zo2H|X3TZhQE1YLwEG&y?;ll2pfw^8pXl{kNj!Un?y+j?S;;4^d_2|wIOE!LDArg0%xiWWCUwR{NfWh&FL<|~`ZF_ zdNWg#bWX?~A4g`|SkMfgfT!(Q0^3oeGNRb(l9V zr?pO}H-^u+>~s_=r1}(Z@FxyQOJ*{Hj8kgbvxidcAIWhaz97)e3fY~O`%%(`*3P~W zjmO_VT<@%HuCG1V+PUAZX&&n^@vuR#S*&PhSv5YWw_3tjb;y6i7S4c{SI>qP=DGCV l=U7?EI&&2@UL$Hu4E{NgB=mT_;L!QG`71T*(#k(>@n6wm%j*CD literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/sessions.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/sessions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34540479248b9c8e96af873393cf197e3c3d60c8 GIT binary patch literal 14082 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/signals.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/signals.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b097990c49b7ae8e728bf78fd67476bb0d5c67cf GIT binary patch literal 802 zcmZ9KL2uJA6oBodOWU+vHwoB&0a6cv3nzpS5*$FFUC=I8B+G4HL)64Ewj)NaNc;{s z@|Su=LfU0NfD4yUy?lvGa-$YQ7_6B%>v% zD5JFFpbV;zg_J<}jj$1new<|CPs$=kBc!pT6Qqfw2x;nQj1)VXAk7?2k>-wKq=lmy z(y604(lT3oB&*ZgZiOqlp9v{zD{N6qgWc(ssK6+(f%e=&rAlET(I7L>khPE2u&uQZ zBtD^CYWUoMv5B!lTTDFjfo&lR^9dsle8hs#h0K$z{vz9ld2O-$VKCfmKy?dgFN9K? zT3WcVILRRYeDFgxuJBQ)Rto1@qJj}QB->JSIajN*ea!i`v5f}KH69XS<8@ic9cbMh z51VjPvONqdi_4Yy*~5$yw_)5pL>1g^>L8X;hjF~^s$=L=lA+-pnse{ zaODSmb`)~@%u tO@U{RS7C=+Y0|FP?rFbEPt@1_{ULwhRVg9Nk(ANn8k)N_FzdgHY~f&2@(w7)k)u2!;*CTW18>u~gD zhBL!?@ArQ1&BPrWt7!PWbLyY%^_Mm6A5!ln(^6Ye(!O zkZXME3FFiJ;OD0O(shl`@I#+#{E%0AWY|U25A#{nXT1XINBI%{5=I>5FF!H)EBqM7 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 E8`784^Z)<= literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/testing.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/testing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebdb1908a477b20dc7b358956ff7eb11a9773e12 GIT binary patch literal 9513 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/typing.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/typing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6266ba2463cac4bf5730cf35f419b5eebfdc404e GIT binary patch literal 1802 zcmZ`&+iu%N5ap7TMC)cpQ5;#eQ}>qEZKJ&OsVIWlienp26T_DTSqK$Y;z*&rBH7&~ z9QPmk(!c00@u@(80{w&*McvsIX(<9KTI-o}&Rn@-wOZN2&({zC82?bUtlzaW|5-xk zJIf;SH`}s&%O~8L5K4%)ZEjNsoC{YxLC@iZNs$%}|8kN>8+R#y`sT<}lRQ;0HjvVBgn)AIZOEb%H4^Rch z%XF(IM+5N&tQwWJ?$0blF`vIQDqz+Ys@MFoU-T{Kg@Jm0)wPV~;t{m%mANZNZ=(c7$wAP_DjYoTPs?O25+#hD_N3+eDTpuG| z(VU6-WX&3rS?w8y*84qtiinBBiVHcB$@`dN=6ZRk6@Cd%^9Jc>3;ySszim4FLVMWt zT&}S_?U8e%(xSSKgK(S@mDbMQ9PjnJ2YcP4!x#Is z-bV`LTktzqavYe<^!^oy%by?_cYLOpR3aJbY|<2`ty@;IPzF&4nOTQv;XK62QU}AZ zqiY2+b$K9F>gzR;DYMV%{nIm_RrLTFo{y z#hoBj^lrX~6TmLRDN{Pbv0gDDih6$UWvtiDIK6|5ekpdbP%JR`2(DAF%Q$BP4(Za) z6$_L$X>(_U{hjEtQsn~L-i1*l;8`G~TIB9cxdk|N{a~o*=ILADyc>lI-l<~|4MECC z@O{zb2(6=i&? z#Qq2UO5H9Km()q~20hm$TQ@H18>D6Y7IIC}&bU>wVXPIhf)N|Yp}Op%x2o}ii&-0J F{Rc#@=am2e literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/views.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/views.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54ac5ed516225ff6383a15248a7e9b33d7c53260 GIT binary patch literal 5450 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/__pycache__/wrappers.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/__pycache__/wrappers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..104c649ae9e8bbd4b743a789035843c817e44e7e GIT binary patch literal 8450 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 aMniHYWvv){4ET)La}?BauJTjm>c0UBg(?#O literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/app.py b/UIKatabatic/Lib/site-packages/flask/app.py new file mode 100644 index 00000000..905b2477 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/app.py @@ -0,0 +1,1536 @@ +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 werkzeug.wsgi import get_host + +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 + from .typing import HeadersValue + +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, + "SECRET_KEY_FALLBACKS": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "TRUSTED_HOSTS": None, + "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_PARTITIONED": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "MAX_FORM_MEMORY_SIZE": 500_000, + "MAX_FORM_PARTS": 1_000, + "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, + "PROVIDE_AUTOMATIC_OPTIONS": True, + } + ) + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class: type[Request] = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class: type[Response] = Response + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike[str] | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike[str] | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_url_path=static_url_path, + static_folder=static_folder, + static_host=static_host, + host_matching=host_matching, + subdomain_matching=subdomain_matching, + template_folder=template_folder, + instance_path=instance_path, + instance_relative_config=instance_relative_config, + root_path=root_path, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = cli.AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert ( + bool(static_host) == host_matching + ), "Invalid static_host/host_matching combination" + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource( + self, resource: str, mode: str = "rb", encoding: str | None = None + ) -> 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"``. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + path = os.path.join(self.root_path, resource) + + if mode == "rb": + return open(path, mode) # pyright: ignore + + return open(path, mode, encoding=encoding) + + def open_instance_resource( + self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" + ) -> t.IO[t.AnyStr]: + """Open a resource file relative to the application's instance folder + :attr:`instance_path`. Unlike :meth:`open_resource`, files in the + instance folder can be opened for writing. + + :param resource: Path to the resource relative to :attr:`instance_path`. + :param mode: Open the file in this mode. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + path = os.path.join(self.instance_path, resource) + + if "b" in mode: + return open(path, mode) + + return open(path, mode, encoding=encoding) + + 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. + + .. versionchanged:: 3.1 + If :data:`SERVER_NAME` is set, it does not restrict requests to + only that domain, for both ``subdomain_matching`` and + ``host_matching``. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + + .. versionchanged:: 0.9 + This can be called outside a request when the URL adapter is created + for an application context. + + .. versionadded:: 0.6 + """ + if request is not None: + if (trusted_hosts := self.config["TRUSTED_HOSTS"]) is not None: + request.trusted_hosts = trusted_hosts + + # Check trusted_hosts here until bind_to_environ does. + request.host = get_host(request.environ, request.trusted_hosts) # pyright: ignore + subdomain = None + server_name = self.config["SERVER_NAME"] + + if self.url_map.host_matching: + # Don't pass SERVER_NAME, otherwise it's used and the actual + # host is ignored, which breaks host matching. + server_name = None + elif not self.subdomain_matching: + # Werkzeug doesn't implement subdomain matching yet. Until then, + # disable it by forcing the current subdomain to the default, or + # the empty string. + subdomain = self.url_map.default_subdomain or "" + + return self.url_map.bind_to_environ( + request.environ, server_name=server_name, subdomain=subdomain + ) + + # Need at least SERVER_NAME to match/build outside a request. + 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: int | None = None + headers: HeadersValue | None = 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 # pyright: ignore + 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) + + 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/UIKatabatic/Lib/site-packages/flask/blueprints.py b/UIKatabatic/Lib/site-packages/flask/blueprints.py new file mode 100644 index 00000000..b6d4e433 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/blueprints.py @@ -0,0 +1,128 @@ +from __future__ import annotations + +import os +import typing as t +from datetime import timedelta + +from .cli import AppGroup +from .globals import current_app +from .helpers import send_from_directory +from .sansio.blueprints import Blueprint as SansioBlueprint +from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa +from .sansio.scaffold import _sentinel + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +class Blueprint(SansioBlueprint): + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict[str, t.Any] | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore + ) -> None: + super().__init__( + name, + import_name, + static_folder, + static_url_path, + template_folder, + url_prefix, + subdomain, + url_defaults, + root_path, + cli_group, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource( + self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" + ) -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for reading. The + blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource` + method. + + :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"``. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + path = os.path.join(self.root_path, resource) + + if mode == "rb": + return open(path, mode) # pyright: ignore + + return open(path, mode, encoding=encoding) diff --git a/UIKatabatic/Lib/site-packages/flask/cli.py b/UIKatabatic/Lib/site-packages/flask/cli.py new file mode 100644 index 00000000..dd03f3c5 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/cli.py @@ -0,0 +1,1133 @@ +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. + + .. versionchanged:: 3.1 + Added the ``load_dotenv_defaults`` parameter and attribute. + """ + + def __init__( + self, + app_import_path: str | None = None, + create_app: t.Callable[..., Flask] | None = None, + set_debug_flag: bool = True, + load_dotenv_defaults: 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.load_dotenv_defaults = get_load_dotenv(load_dotenv_defaults) + """Whether default ``.flaskenv`` and ``.env`` files should be loaded. + + ``ScriptInfo`` doesn't load anything, this is for reference when doing + the load elsewhere during processing. + + .. versionadded:: 3.1 + """ + + 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 + app: Flask | None = None + if self.create_app is not None: + app = 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: + try: + import dotenv # noqa: F401 + except ImportError: + # Only show an error if a value was passed, otherwise we still want to + # call load_dotenv and show a message without exiting. + if value is not None: + raise click.BadParameter( + "python-dotenv must be installed to load an env file.", + ctx=ctx, + param=param, + ) from None + + # Load if a value was passed, or we want to load default files, or both. + if value is not None or ctx.obj.load_dotenv_defaults: + load_dotenv(value, load_defaults=ctx.obj.load_dotenv_defaults) + + 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, taking precedence over" + " those set by '.env' and '.flaskenv'. Variables set directly in the" + " environment take highest precedence. 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:: 3.1 + ``-e path`` takes precedence over default ``.env`` and ``.flaskenv`` files. + + .. 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[click.Parameter] = 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 # pyright: ignore + + 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" + + 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, + load_dotenv_defaults=self.load_dotenv, + ) + + 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, load_defaults: bool = True +) -> bool: + """Load "dotenv" files to set environment variables. A given path takes + precedence over ``.env``, which takes precedence over ``.flaskenv``. After + loading and combining these files, values are only set if the key is not + already set in ``os.environ``. + + 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. + :param load_defaults: Search for and load the default ``.flaskenv`` and + ``.env`` files. + :return: ``True`` if at least one env var was loaded. + + .. versionchanged:: 3.1 + Added the ``load_defaults`` parameter. A given path takes precedence + over default files. + + .. 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 files present. Install python-dotenv" + " to use them.", + fg="yellow", + err=True, + ) + + return False + + data: dict[str, str | None] = {} + + if load_defaults: + for default_name in (".flaskenv", ".env"): + if not (default_path := dotenv.find_dotenv(default_name, usecwd=True)): + continue + + data |= dotenv.dotenv_values(default_path, encoding="utf-8") + + if path is not None and os.path.isfile(path): + data |= dotenv.dotenv_values(path, encoding="utf-8") + + for key, value in data.items(): + if key in os.environ or value is None: + continue + + os.environ[key] = value + + return bool(data) # True if at least one env var was 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() # pyright: ignore + 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/UIKatabatic/Lib/site-packages/flask/config.py b/UIKatabatic/Lib/site-packages/flask/config.py new file mode 100644 index 00000000..34ef1a57 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/config.py @@ -0,0 +1,367 @@ +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}_" + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + key = key.removeprefix(prefix) + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + 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/UIKatabatic/Lib/site-packages/flask/ctx.py b/UIKatabatic/Lib/site-packages/flask/ctx.py new file mode 100644 index 00000000..9b164d39 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/debughelpers.py b/UIKatabatic/Lib/site-packages/flask/debughelpers.py new file mode 100644 index 00000000..2c8c4c48 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/globals.py b/UIKatabatic/Lib/site-packages/flask/globals.py new file mode 100644 index 00000000..e2c410cc --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/helpers.py b/UIKatabatic/Lib/site-packages/flask/helpers.py new file mode 100644 index 00000000..a6b7e150 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/helpers.py @@ -0,0 +1,634 @@ +from __future__ import annotations + +import importlib.util +import os +import sys +import typing as t +from datetime import datetime +from functools import 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") + + +@t.overload +def stream_with_context( + generator_or_function: t.Iterator[t.AnyStr], +) -> t.Iterator[t.AnyStr]: ... + + +@t.overload +def stream_with_context( + generator_or_function: t.Callable[..., t.Iterator[t.AnyStr]], +) -> t.Callable[[t.Iterator[t.AnyStr]], t.Iterator[t.AnyStr]]: ... + + +def stream_with_context( + generator_or_function: t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]], +) -> 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. This *must not* + be a value provided by the client, otherwise it becomes insecure. + :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) # pyright: ignore + 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] + + +@cache +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/UIKatabatic/Lib/site-packages/flask/json/__init__.py b/UIKatabatic/Lib/site-packages/flask/json/__init__.py new file mode 100644 index 00000000..c0941d04 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/json/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/json/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acb1dad1dd21e9ea384efc092763c5aeebba530c GIT binary patch literal 5958 zcmd5=TW=e=6`s+>maj?N?8ez_Q=$(=RXCH&7DXW}f(^1s>!x)UwS%Ir3yBgbnf7RA zN>Wl~7=7wfANmXSp#_Qp{Y&%M0tNCH`qb}mW+d5B3@7j|B73A6a(GA{p7WjW9KN=; z?BVm{AN;rX?~gq1KlCvBsp8=a&-2YcaU(q8hhE>`_kFrAg{A$n`>pI(MOjqBh5q9H zBKoRgA*}V6_LqE5R*#nTbM!8TEB)2|RrJ>Iw!$b!E!V`yuH_b5HpOkUTzAi(h&yQcRD2gLH$-XItKWT1JE;5V3Xh`L za;xIV?7S}Jjh%tkGO|scB(MFft=1H>%Lk#wpxUpcNiaa3RBiAi8mDDrb-kRHNf@c-)X;`eW5;oHjJ zOTK5T=X>iV{=DpYyHYD2suRfsx14dqezE&pr4o@*4gKoG}o5sc&LQb0nPhW z@!;Nk+;UP#NG!HkY!9U#DJOqASEDZFT^7i^%##B z=A-pPzShw3L<()FEf4un#rndD9|Y5>8y%Q{X|#mws6G#aFSB1~2WF5Yv9?fGd(1j< zgb6LJ0h4nEyT<*+^Guf3YRRY*3k-m!oI$l^p(Cau_MGexs(pBYyobSq8PykR??54t zl^?56T6SzW-eQ_V9U6y>el7nnP_)`ydy{2hPgefXvTm$te_hoZU>uG+Goo~{aO?$5 zzL{3Y9@DC`nRMAmoA>Jl>a8}ZyI#^uc+!N7|MK(={QPg{Y2)A(EYuuCQijRFm(m>D zI5~K=jsF*L#WrT`9Q;zX4~(+%Ucx)ayeG|p^QikI_I|UeB4wM+AQ|g*2wlTvYWVW* zRQ#KzRo}IqEZJcDE?pXy-V2r950ttI z0EyAYS)9lS?nU-TI&sbggACa2VLS+hgI#j#S9{Oz{d8isg)fl?Vf#ZMy~qKcP$`GV z%VFOK4SiRSd=nl1rcgIwSzAS1kKK^~YGI(H^D~%*xa|VSR)JmJ`<`?xZ1zg6)!$=j**WCf1S zP65wW8n6uC%=q|Q*~O1A@@?$Gmfv6$K3|771G0(;`)zQFFy`WNoWi~N&fe=ropWCU zMnTa4&glFtQ|mkOiA?Z^$|v>{WMWIKvsAxiHR8$yg?n1Up7j_Z1fd^A4aMAke zJo%FgJQ*~JBNXYl4@CS1!!l{>Qel~1d@sj7=hyS&E$z05w{Mu*JB3kN=LZ``v&CJp z!%x$Pz4;jsrHu0#{%033{71oq2?o3)k~lV1API5$iJ*QgkjDbk^B_;p2;%neO^`q1 z)fLiQ;nY)yBtAbAn>Xw(Q(>XP@=|y}YB3CHkp9#unoqURv|0SjT6zL1nJx%uO zK2HHO({!GQNly(WvcO47n`ieKbID2zIhYp7U7qI`wTTv`&&ZQ9HDp`|NoA-yF8Oi! zMk~+K74r0PA_Fj1p)drB3>5%7n}@h-1{gynM+G-3a>Xpq&TyUT02q`NM;IU2xKB9` z^4hUmMm(?#$x-H#F{2K!FlBOc*~4v~$4L|@u>FpO8eEgaaE2r`wBtofCT zVm+6FqvGYq1-xuWOvv`2$1)QmJz^ILHiET+(qn^^J3Cubktk{l#M=A(nCdCcNF_Il zGSwKH;UYj_#PB{JBj-1c-_vGv9EOmEJe;PPR9CWs&NEmuBqTACMQy9sA>9@s~XOrgw@^&4z?;-waQw^XO%nR!7Qld*Fd*xq!2v&*vsoZNX-;n7U# zSf;-s%W{g|1(@Xf0)ygUdVKAb4_i4d@xyprP*%|fp(_{GV+P!45?qt|?Fa_gfC z)(jn!s7on3W?G?0gK7_p;XE3ZE|Or?9sdO{7=lob={xwYZ=}o3W_N(fs%$nj^*DOwAUs_F zh+)I2Z_~wI7`NeDSxKi>_)=EGS=;;VSI?SHfBx+0i|w7CrL~a;tYC`{&s~MZC0>rW zX$SN)_e{p-;sb$sTKgQhFbL&iqHl(1;cBVo*O0rdmKOZg^2YaX-re}##@+t|Q?tyZ literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/json/__pycache__/provider.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/json/__pycache__/provider.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0b368702dfdb52147d4708aac44ba06ef3f53cb GIT binary patch literal 7558 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 h$` 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) # type: ignore[arg-type] + + 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/UIKatabatic/Lib/site-packages/flask/json/tag.py b/UIKatabatic/Lib/site-packages/flask/json/tag.py new file mode 100644 index 00000000..8dc3629b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/json/tag.py @@ -0,0 +1,327 @@ +""" +Tagged JSON +~~~~~~~~~~~ + +A compact representation for lossless serialization of non-standard JSON +types. :class:`~flask.sessions.SecureCookieSessionInterface` uses this +to serialize the session data, but it may be useful in other places. It +can be extended to support other types. + +.. autoclass:: TaggedJSONSerializer + :members: + +.. autoclass:: JSONTag + :members: + +Let's see an example that adds support for +:class:`~collections.OrderedDict`. Dicts don't have an order in JSON, so +to handle this we will dump the items as a list of ``[key, value]`` +pairs. Subclass :class:`JSONTag` and give it the new key ``' od'`` to +identify the type. The session serializer processes dicts first, so +insert the new tag at the front of the order since ``OrderedDict`` must +be processed before ``dict``. + +.. code-block:: python + + from flask.json.tag import JSONTag + + class TagOrderedDict(JSONTag): + __slots__ = ('serializer',) + key = ' od' + + def check(self, value): + return isinstance(value, OrderedDict) + + def to_json(self, value): + return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] + + def to_python(self, value): + return OrderedDict(value) + + app.session_interface.serializer.register(TagOrderedDict, index=0) +""" + +from __future__ import annotations + +import typing as t +from base64 import b64decode +from base64 import b64encode +from datetime import datetime +from uuid import UUID + +from markupsafe import Markup +from werkzeug.http import http_date +from werkzeug.http import parse_date + +from ..json import dumps +from ..json import loads + + +class JSONTag: + """Base class for defining type tags for :class:`TaggedJSONSerializer`.""" + + __slots__ = ("serializer",) + + #: The tag to mark the serialized object with. If empty, this tag is + #: only used as an intermediate step during tagging. + key: str = "" + + def __init__(self, serializer: TaggedJSONSerializer) -> None: + """Create a tagger for the given serializer.""" + self.serializer = serializer + + def check(self, value: t.Any) -> bool: + """Check if the given value should be tagged by this tag.""" + raise NotImplementedError + + def to_json(self, value: t.Any) -> t.Any: + """Convert the Python object to an object that is a valid JSON type. + The tag will be added later.""" + raise NotImplementedError + + def to_python(self, value: t.Any) -> t.Any: + """Convert the JSON representation back to the correct type. The tag + will already be removed.""" + raise NotImplementedError + + def tag(self, value: t.Any) -> dict[str, t.Any]: + """Convert the value to a valid JSON type and add the tag structure + around it.""" + return {self.key: self.to_json(value)} + + +class TagDict(JSONTag): + """Tag for 1-item dicts whose only key matches a registered tag. + + Internally, the dict key is suffixed with `__`, and the suffix is removed + when deserializing. + """ + + __slots__ = () + key = " di" + + def check(self, value: t.Any) -> bool: + return ( + isinstance(value, dict) + and len(value) == 1 + and next(iter(value)) in self.serializer.tags + ) + + def to_json(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {f"{key}__": self.serializer.tag(value[key])} + + def to_python(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {key[:-2]: value[key]} + + +class PassDict(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, dict) + + def to_json(self, value: t.Any) -> t.Any: + # JSON objects may only have string keys, so don't bother tagging the + # key here. + return {k: self.serializer.tag(v) for k, v in value.items()} + + tag = to_json + + +class TagTuple(JSONTag): + __slots__ = () + key = " t" + + def check(self, value: t.Any) -> bool: + return isinstance(value, tuple) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + def to_python(self, value: t.Any) -> t.Any: + return tuple(value) + + +class PassList(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, list) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + tag = to_json + + +class TagBytes(JSONTag): + __slots__ = () + key = " b" + + def check(self, value: t.Any) -> bool: + return isinstance(value, bytes) + + def to_json(self, value: t.Any) -> t.Any: + return b64encode(value).decode("ascii") + + def to_python(self, value: t.Any) -> t.Any: + return b64decode(value) + + +class TagMarkup(JSONTag): + """Serialize anything matching the :class:`~markupsafe.Markup` API by + having a ``__html__`` method to the result of that method. Always + deserializes to an instance of :class:`~markupsafe.Markup`.""" + + __slots__ = () + key = " m" + + def check(self, value: t.Any) -> bool: + return callable(getattr(value, "__html__", None)) + + def to_json(self, value: t.Any) -> t.Any: + return str(value.__html__()) + + def to_python(self, value: t.Any) -> t.Any: + return Markup(value) + + +class TagUUID(JSONTag): + __slots__ = () + key = " u" + + def check(self, value: t.Any) -> bool: + return isinstance(value, UUID) + + def to_json(self, value: t.Any) -> t.Any: + return value.hex + + def to_python(self, value: t.Any) -> t.Any: + return UUID(value) + + +class TagDateTime(JSONTag): + __slots__ = () + key = " d" + + def check(self, value: t.Any) -> bool: + return isinstance(value, datetime) + + def to_json(self, value: t.Any) -> t.Any: + return http_date(value) + + def to_python(self, value: t.Any) -> t.Any: + return parse_date(value) + + +class TaggedJSONSerializer: + """Serializer that uses a tag system to compactly represent objects that + are not JSON types. Passed as the intermediate serializer to + :class:`itsdangerous.Serializer`. + + The following extra types are supported: + + * :class:`dict` + * :class:`tuple` + * :class:`bytes` + * :class:`~markupsafe.Markup` + * :class:`~uuid.UUID` + * :class:`~datetime.datetime` + """ + + __slots__ = ("tags", "order") + + #: Tag classes to bind when creating the serializer. Other tags can be + #: added later using :meth:`~register`. + default_tags = [ + TagDict, + PassDict, + TagTuple, + PassList, + TagBytes, + TagMarkup, + TagUUID, + TagDateTime, + ] + + def __init__(self) -> None: + self.tags: dict[str, JSONTag] = {} + self.order: list[JSONTag] = [] + + for cls in self.default_tags: + self.register(cls) + + def register( + self, + tag_class: type[JSONTag], + force: bool = False, + index: int | None = None, + ) -> None: + """Register a new tag with this serializer. + + :param tag_class: tag class to register. Will be instantiated with this + serializer instance. + :param force: overwrite an existing tag. If false (default), a + :exc:`KeyError` is raised. + :param index: index to insert the new tag in the tag order. Useful when + the new tag is a special case of an existing tag. If ``None`` + (default), the tag is appended to the end of the order. + + :raise KeyError: if the tag key is already registered and ``force`` is + not true. + """ + tag = tag_class(self) + key = tag.key + + if key: + if not force and key in self.tags: + raise KeyError(f"Tag '{key}' is already registered.") + + self.tags[key] = tag + + if index is None: + self.order.append(tag) + else: + self.order.insert(index, tag) + + def tag(self, value: t.Any) -> t.Any: + """Convert a value to a tagged representation if necessary.""" + for tag in self.order: + if tag.check(value): + return tag.tag(value) + + return value + + def untag(self, value: dict[str, t.Any]) -> t.Any: + """Convert a tagged representation back to the original type.""" + if len(value) != 1: + return value + + key = next(iter(value)) + + if key not in self.tags: + return value + + return self.tags[key].to_python(value[key]) + + def _untag_scan(self, value: t.Any) -> t.Any: + if isinstance(value, dict): + # untag each item recursively + value = {k: self._untag_scan(v) for k, v in value.items()} + # untag the dict itself + value = self.untag(value) + elif isinstance(value, list): + # untag each item recursively + value = [self._untag_scan(item) for item in value] + + return value + + def dumps(self, value: t.Any) -> str: + """Tag the value and dump it to a compact JSON string.""" + return dumps(self.tag(value), separators=(",", ":")) + + def loads(self, value: str) -> t.Any: + """Load data from a JSON string and deserialized any tagged objects.""" + return self._untag_scan(loads(value)) diff --git a/UIKatabatic/Lib/site-packages/flask/logging.py b/UIKatabatic/Lib/site-packages/flask/logging.py new file mode 100644 index 00000000..0cb8f437 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/py.typed b/UIKatabatic/Lib/site-packages/flask/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/flask/sansio/README.md b/UIKatabatic/Lib/site-packages/flask/sansio/README.md new file mode 100644 index 00000000..623ac198 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/app.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/app.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..567db56efa06c062701c1256bdce95bfcb67b4a8 GIT binary patch literal 28255 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 Mz@hOkH8${n0l+y5bN~PV literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73ae2a1ee2955873a08ce602061125e1e49fcf61 GIT binary patch literal 22805 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 KhFWg&o&N`OYOyW= literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/scaffold.cpython-39.pyc b/UIKatabatic/Lib/site-packages/flask/sansio/__pycache__/scaffold.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3b42cbdc25e384a6037d5a4328ea9e075f4e666 GIT binary patch literal 23644 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 ezMho7l2!Rd1$3x?i<8xf9~aWUiOJ!~qyHa&O 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, + ) -> None: + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: An instance of :attr:`aborter_class` created by + #: :meth:`make_aborter`. This is called by :func:`flask.abort` + #: to raise HTTP errors, and can be called directly as well. + #: + #: .. versionadded:: 2.2 + #: Moved from ``flask.abort``, which calls this object. + self.aborter = self.make_aborter() + + self.json: JSONProvider = self.json_provider_class(self) + """Provides access to JSON methods. Functions in ``flask.json`` + will call methods on this provider when the application context + is active. Used for handling JSON requests and responses. + + An instance of :attr:`json_provider_class`. Can be customized by + changing that attribute on a subclass, or by assigning to this + attribute afterwards. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, + uses Python's built-in :mod:`json` library. A different provider + can use a different JSON library. + + .. versionadded:: 2.2 + """ + + #: A list of functions that are called by + #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function is called + #: with ``error``, ``endpoint`` and ``values``. If a function + #: returns ``None`` or raises a ``BuildError``, it is skipped. + #: Otherwise, its return value is returned by ``url_for``. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: list[ + t.Callable[[Exception, str, dict[str, t.Any]], str] + ] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: dict[str, Blueprint] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict[str, t.Any] = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class(host_matching=host_matching) + + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_first_request: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called" + " on the application. It has already handled its first" + " request, any changes will not be applied" + " consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the application are done before" + " running it." + ) + + @cached_property + def name(self) -> str: # type: ignore + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn: str | None = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + def create_jinja_environment(self) -> Environment: + raise NotImplementedError() + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def make_aborter(self) -> Aborter: + """Create the object to assign to :attr:`aborter`. That object + is called by :func:`flask.abort` to raise HTTP errors, and can + be called directly as well. + + By default, this creates an instance of :attr:`aborter_class`, + which defaults to :class:`werkzeug.exceptions.Aborter`. + + .. versionadded:: 2.2 + """ + return self.aborter_class() + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionchanged:: 2.2 + Autoescaping is now enabled by default for ``.svg`` files. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start the + development server, an interactive debugger will be shown for unhandled + exceptions, and the server will be reloaded when code changes. This maps to the + :data:`DEBUG` config key. It may not behave as expected if set late. + + **Do not enable debug mode when deploying in production.** + + Default: ``False`` + """ + return self.config["DEBUG"] # type: ignore[no-any-return] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + + if self.config["TEMPLATES_AUTO_RELOAD"] is None: + self.jinja_env.auto_reload = value + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView[Blueprint]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods: set[str] = 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 and self.config["PROVIDE_AUTOMATIC_OPTIONS"]: + 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/UIKatabatic/Lib/site-packages/flask/sansio/blueprints.py b/UIKatabatic/Lib/site-packages/flask/sansio/blueprints.py new file mode 100644 index 00000000..4f912cca --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/sansio/scaffold.py b/UIKatabatic/Lib/site-packages/flask/sansio/scaffold.py new file mode 100644 index 00000000..3a839f5a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/sansio/scaffold.py @@ -0,0 +1,792 @@ +from __future__ import annotations + +import importlib.util +import os +import pathlib +import sys +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from jinja2 import BaseLoader +from jinja2 import FileSystemLoader +from werkzeug.exceptions import default_exceptions +from werkzeug.exceptions import HTTPException +from werkzeug.utils import cached_property + +from .. import typing as ft +from ..helpers import get_root_path +from ..templating import _default_template_ctx_processor + +if t.TYPE_CHECKING: # pragma: no cover + from click import Group + +# a singleton sentinel value for parameter defaults +_sentinel = object() + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) +T_route = t.TypeVar("T_route", bound=ft.RouteCallable) + + +def setupmethod(f: F) -> F: + f_name = f.__name__ + + def wrapper_func(self: Scaffold, *args: t.Any, **kwargs: t.Any) -> t.Any: + self._check_setup_finished(f_name) + return f(self, *args, **kwargs) + + return t.cast(F, update_wrapper(wrapper_func, f)) + + +class Scaffold: + """Common behavior shared between :class:`~flask.Flask` and + :class:`~flask.blueprints.Blueprint`. + + :param import_name: The import name of the module where this object + is defined. Usually :attr:`__name__` should be used. + :param static_folder: Path to a folder of static files to serve. + If this is set, a static route will be added. + :param static_url_path: URL prefix for the static route. + :param template_folder: Path to a folder containing template files. + for rendering. If this is set, a Jinja loader will be added. + :param root_path: The path that static, template, and resource files + are relative to. Typically not set, it is discovered based on + the ``import_name``. + + .. versionadded:: 2.0 + """ + + cli: Group + name: str + _static_folder: str | None = None + _static_url_path: str | None = None + + def __init__( + self, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + root_path: str | None = None, + ): + #: The name of the package or module that this object belongs + #: to. Do not change this once it is set by the constructor. + self.import_name = import_name + + self.static_folder = static_folder # type: ignore + self.static_url_path = static_url_path + + #: The path to the templates folder, relative to + #: :attr:`root_path`, to add to the template loader. ``None`` if + #: templates should not be added. + self.template_folder = template_folder + + if root_path is None: + root_path = get_root_path(self.import_name) + + #: Absolute path to the package on the filesystem. Used to look + #: up resources contained in the package. + self.root_path = root_path + + #: A dictionary mapping endpoint names to view functions. + #: + #: To register a view function, use the :meth:`route` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.view_functions: dict[str, ft.RouteCallable] = {} + + #: A data structure of registered error handlers, in the format + #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is + #: the name of a blueprint the handlers are active for, or + #: ``None`` for all requests. The ``code`` key is the HTTP + #: status code for ``HTTPException``, or ``None`` for + #: other exceptions. The innermost dictionary maps exception + #: classes to handler functions. + #: + #: To register an error handler, use the :meth:`errorhandler` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.error_handler_spec: dict[ + ft.AppOrBlueprintKey, + dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]], + ] = defaultdict(lambda: defaultdict(dict)) + + #: A data structure of functions to call at the beginning of + #: each request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`before_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.before_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`after_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.after_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request even if an exception is raised, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`teardown_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.teardown_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.TeardownCallable] + ] = defaultdict(list) + + #: A data structure of functions to call to pass extra context + #: values when rendering templates, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`context_processor` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.template_context_processors: dict[ + ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable] + ] = defaultdict(list, {None: [_default_template_ctx_processor]}) + + #: A data structure of functions to call to modify the keyword + #: arguments passed to the view function, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the + #: :meth:`url_value_preprocessor` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_value_preprocessors: dict[ + ft.AppOrBlueprintKey, + list[ft.URLValuePreprocessorCallable], + ] = defaultdict(list) + + #: A data structure of functions to call to modify the keyword + #: arguments when generating URLs, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`url_defaults` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_default_functions: dict[ + ft.AppOrBlueprintKey, list[ft.URLDefaultCallable] + ] = defaultdict(list) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.name!r}>" + + def _check_setup_finished(self, f_name: str) -> None: + raise NotImplementedError + + @property + def static_folder(self) -> str | None: + """The absolute path to the configured static folder. ``None`` + if no static folder is set. + """ + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + else: + return None + + @static_folder.setter + def static_folder(self, value: str | os.PathLike[str] | None) -> None: + if value is not None: + value = os.fspath(value).rstrip(r"\/") + + self._static_folder = value + + @property + def has_static_folder(self) -> bool: + """``True`` if :attr:`static_folder` is set. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @property + def static_url_path(self) -> str | None: + """The URL prefix that the static route will be accessible from. + + If it was not configured during init, it is derived from + :attr:`static_folder`. + """ + if self._static_url_path is not None: + return self._static_url_path + + if self.static_folder is not None: + basename = os.path.basename(self.static_folder) + return f"/{basename}".rstrip("/") + + return None + + @static_url_path.setter + def static_url_path(self, value: str | None) -> None: + if value is not None: + value = value.rstrip("/") + + self._static_url_path = value + + @cached_property + def jinja_loader(self) -> BaseLoader | None: + """The Jinja loader for this object's templates. By default this + is a class :class:`jinja2.loaders.FileSystemLoader` to + :attr:`template_folder` if it is set. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) + else: + return None + + def _method_route( + self, + method: str, + rule: str, + options: dict[str, t.Any], + ) -> t.Callable[[T_route], T_route]: + if "methods" in options: + raise TypeError("Use the 'route' decorator to use the 'methods' argument.") + + return self.route(rule, methods=[method], **options) + + @setupmethod + def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["GET"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("GET", rule, options) + + @setupmethod + def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["POST"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("POST", rule, options) + + @setupmethod + def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PUT"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PUT", rule, options) + + @setupmethod + def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["DELETE"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("DELETE", rule, options) + + @setupmethod + def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PATCH"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PATCH", rule, options) + + @setupmethod + def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Decorate a view function to register it with the given URL + rule and options. Calls :meth:`add_url_rule`, which has more + details about the implementation. + + .. code-block:: python + + @app.route("/") + def index(): + return "Hello, World!" + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and + ``OPTIONS`` are added automatically. + + :param rule: The URL rule string. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + + def decorator(f: T_route) -> T_route: + endpoint = options.pop("endpoint", None) + self.add_url_rule(rule, endpoint, f, **options) + return f + + return decorator + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a rule for routing incoming requests and building + URLs. The :meth:`route` decorator is a shortcut to call this + with the ``view_func`` argument. These are equivalent: + + .. code-block:: python + + @app.route("/") + def index(): + ... + + .. code-block:: python + + def index(): + ... + + app.add_url_rule("/", view_func=index) + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. An error + will be raised if a function has already been registered for the + endpoint. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is + always added automatically, and ``OPTIONS`` is added + automatically by default. + + ``view_func`` does not necessarily need to be passed, but if the + rule should participate in routing an endpoint name must be + associated with a view function at some point with the + :meth:`endpoint` decorator. + + .. code-block:: python + + app.add_url_rule("/", endpoint="index") + + @app.endpoint("index") + def index(): + ... + + If ``view_func`` has a ``required_methods`` attribute, those + methods are added to the passed and automatic methods. If it + has a ``provide_automatic_methods`` attribute, it is used as the + default if the parameter is not passed. + + :param rule: The URL rule string. + :param endpoint: The endpoint name to associate with the rule + and view function. Used when routing and building URLs. + Defaults to ``view_func.__name__``. + :param view_func: The view function to associate with the + endpoint name. + :param provide_automatic_options: Add the ``OPTIONS`` method and + respond to ``OPTIONS`` requests automatically. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + raise NotImplementedError + + @setupmethod + def endpoint(self, endpoint: str) -> t.Callable[[F], F]: + """Decorate a view function to register it for the given + endpoint. Used if a rule is added without a ``view_func`` with + :meth:`add_url_rule`. + + .. code-block:: python + + app.add_url_rule("/ex", endpoint="example") + + @app.endpoint("example") + def example(): + ... + + :param endpoint: The endpoint name to associate with the view + function. + """ + + def decorator(f: F) -> F: + self.view_functions[endpoint] = f + return f + + return decorator + + @setupmethod + def before_request(self, f: T_before_request) -> T_before_request: + """Register a function to run before each request. + + For example, this can be used to open a database connection, or + to load the logged in user from the session. + + .. code-block:: python + + @app.before_request + def load_user(): + if "user_id" in session: + g.user = db.session.get(session["user_id"]) + + The function will be called without any arguments. If it returns + a non-``None`` value, the value is handled as if it was the + return value from the view, and further request handling is + stopped. + + This is available on both app and blueprint objects. When used on an app, this + executes before every request. When used on a blueprint, this executes before + every request that the blueprint handles. To register with a blueprint and + execute before every request, use :meth:`.Blueprint.before_app_request`. + """ + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def after_request(self, f: T_after_request) -> T_after_request: + """Register a function to run after each request to this object. + + The function is called with the response object, and must return + a response object. This allows the functions to modify or + replace the response before it is sent. + + If a function raises an exception, any remaining + ``after_request`` functions will not be called. Therefore, this + should not be used for actions that must execute, such as to + close resources. Use :meth:`teardown_request` for that. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.after_app_request`. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f: T_teardown) -> T_teardown: + """Register a function to be called when the request context is + popped. Typically this happens at the end of each request, but + contexts may be pushed manually as well during testing. + + .. code-block:: python + + with app.test_request_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the request context is + made inactive. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.teardown_app_request`. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def context_processor( + self, + f: T_template_context_processor, + ) -> T_template_context_processor: + """Registers a template context processor function. These functions run before + rendering a template. The keys of the returned dict are added as variables + available in the template. + + This is available on both app and blueprint objects. When used on an app, this + is called for every rendered template. When used on a blueprint, this is called + for templates rendered from the blueprint's views. To register with a blueprint + and affect every template, use :meth:`.Blueprint.app_context_processor`. + """ + self.template_context_processors[None].append(f) + return f + + @setupmethod + def url_value_preprocessor( + self, + f: T_url_value_preprocessor, + ) -> T_url_value_preprocessor: + """Register a URL value preprocessor function for all view + functions in the application. These functions will be called before the + :meth:`before_request` functions. + + The function can modify the values captured from the matched url before + they are passed to the view. For example, this can be used to pop a + common language code value and place it in ``g`` rather than pass it to + every view. + + The function is passed the endpoint name and values dict. The return + value is ignored. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_value_preprocessor`. + """ + self.url_value_preprocessors[None].append(f) + return f + + @setupmethod + def url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_defaults`. + """ + self.url_default_functions[None].append(f) + return f + + @setupmethod + def errorhandler( + self, code_or_exception: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Register a function to handle errors by code or exception class. + + A decorator that is used to register a function given an + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + This is available on both app and blueprint objects. When used on an app, this + can handle errors from every request. When used on a blueprint, this can handle + errors from requests that the blueprint handles. To register with a blueprint + and affect every request, use :meth:`.Blueprint.app_errorhandler`. + + .. versionadded:: 0.7 + Use :meth:`register_error_handler` instead of modifying + :attr:`error_handler_spec` directly, for application wide error + handlers. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code_or_exception: the code as integer for the handler, or + an arbitrary exception + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.register_error_handler(code_or_exception, f) + return f + + return decorator + + @setupmethod + def register_error_handler( + self, + code_or_exception: type[Exception] | int, + f: ft.ErrorHandlerCallable, + ) -> None: + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + exc_class, code = self._get_exc_class_and_code(code_or_exception) + self.error_handler_spec[None][code][exc_class] = f + + @staticmethod + def _get_exc_class_and_code( + exc_class_or_code: type[Exception] | int, + ) -> tuple[type[Exception], int | None]: + """Get the exception class being handled. For HTTP status codes + or ``HTTPException`` subclasses, return both the exception and + status code. + + :param exc_class_or_code: Any exception class, or an HTTP status + code as an integer. + """ + exc_class: type[Exception] + + if isinstance(exc_class_or_code, int): + try: + exc_class = default_exceptions[exc_class_or_code] + except KeyError: + raise ValueError( + f"'{exc_class_or_code}' is not a recognized HTTP" + " error code. Use a subclass of HTTPException with" + " that code instead." + ) from None + else: + exc_class = exc_class_or_code + + if isinstance(exc_class, Exception): + raise TypeError( + f"{exc_class!r} is an instance, not a class. Handlers" + " can only be registered for Exception classes or HTTP" + " error codes." + ) + + if not issubclass(exc_class, Exception): + raise ValueError( + f"'{exc_class.__name__}' is not a subclass of Exception." + " Handlers can only be registered for Exception classes" + " or HTTP error codes." + ) + + if issubclass(exc_class, HTTPException): + return exc_class, exc_class.code + else: + return exc_class, None + + +def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str: + """Internal helper that returns the default endpoint for a given + function. This always is the function name. + """ + assert view_func is not None, "expected view func if endpoint is not provided." + return view_func.__name__ + + +def _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 package_path.is_relative_to(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 pathlib.PurePath(package_path).is_relative_to(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/UIKatabatic/Lib/site-packages/flask/sessions.py b/UIKatabatic/Lib/site-packages/flask/sessions.py new file mode 100644 index 00000000..375de065 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/sessions.py @@ -0,0 +1,398 @@ +from __future__ import annotations + +import collections.abc as c +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 + + +class SessionMixin(MutableMapping[str, t.Any]): + """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 + + +class SecureCookieSession(CallbackDict[str, t.Any], SessionMixin): + """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: c.Mapping[str, t.Any] | c.Iterable[tuple[str, t.Any]] | None = 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_cookie_partitioned(self, app: Flask) -> bool: + """Returns True if the cookie should be partitioned. By default, uses + the value of :data:`SESSION_COOKIE_PARTITIONED`. + + .. versionadded:: 3.1 + """ + return app.config["SESSION_COOKIE_PARTITIONED"] # type: ignore[no-any-return] + + def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None: + """A helper method that returns an expiration date for the session + or ``None`` if the session is linked to the browser session. The + default implementation returns now + the permanent session + lifetime configured on the application. + """ + if session.permanent: + return datetime.now(timezone.utc) + app.permanent_session_lifetime + return None + + def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool: + """Used by session backends to determine if a ``Set-Cookie`` header + should be set for this session cookie for this response. If the session + has been modified, the cookie is set. If the session is permanent and + the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is + always set. + + This check is usually skipped if the session was deleted. + + .. versionadded:: 0.11 + """ + + return session.modified or ( + session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"] + ) + + def open_session(self, app: Flask, request: Request) -> SessionMixin | None: + """This is called at the beginning of each request, after + pushing the request context, before matching the URL. + + This must return an object which implements a dictionary-like + interface as well as the :class:`SessionMixin` interface. + + This will return ``None`` to indicate that loading failed in + some way that is not immediately an error. The request + context will fall back to using :meth:`make_null_session` + in this case. + """ + raise NotImplementedError() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + """This is called at the end of each request, after generating + a response, before removing the request context. It is skipped + if :meth:`is_null_session` returns ``True``. + """ + raise NotImplementedError() + + +session_json_serializer = TaggedJSONSerializer() + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class SecureCookieSessionInterface(SessionInterface): + """The default session interface that stores sessions in signed cookies + through the :mod:`itsdangerous` module. + """ + + #: the salt that should be applied on top of the secret key for the + #: signing of cookie based sessions. + salt = "cookie-session" + #: the hash function to use for the signature. The default is sha1 + digest_method = staticmethod(_lazy_sha1) + #: the name of the itsdangerous supported key derivation. The default + #: is hmac. + key_derivation = "hmac" + #: A python serializer for the payload. The default is a compact + #: JSON derived serializer with support for some extra Python types + #: such as datetime objects or tuples. + serializer = session_json_serializer + session_class = SecureCookieSession + + def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None: + if not app.secret_key: + return None + + keys: list[str | bytes] = [app.secret_key] + + if fallbacks := app.config["SECRET_KEY_FALLBACKS"]: + keys.extend(fallbacks) + + return URLSafeTimedSerializer( + keys, # type: ignore[arg-type] + salt=self.salt, + serializer=self.serializer, + signer_kwargs={ + "key_derivation": self.key_derivation, + "digest_method": self.digest_method, + }, + ) + + 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) + partitioned = self.get_cookie_partitioned(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, + partitioned=partitioned, + 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[union-attr] + response.set_cookie( + name, + val, + expires=expires, + httponly=httponly, + domain=domain, + path=path, + secure=secure, + partitioned=partitioned, + samesite=samesite, + ) + response.vary.add("Cookie") diff --git a/UIKatabatic/Lib/site-packages/flask/signals.py b/UIKatabatic/Lib/site-packages/flask/signals.py new file mode 100644 index 00000000..444fda99 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/templating.py b/UIKatabatic/Lib/site-packages/flask/templating.py new file mode 100644 index 00000000..618a3b35 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/flask/testing.py b/UIKatabatic/Lib/site-packages/flask/testing.py new file mode 100644 index 00000000..602b773b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/testing.py @@ -0,0 +1,297 @@ +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: + path = f"{path}?{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/UIKatabatic/Lib/site-packages/flask/typing.py b/UIKatabatic/Lib/site-packages/flask/typing.py new file mode 100644 index 00000000..e7234e96 --- /dev/null +++ b/UIKatabatic/Lib/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, + 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, list[str], tuple[str, ...]] + +# the possible types for HTTP headers +HeadersValue = t.Union[ + "Headers", + t.Mapping[str, HeaderValue], + t.Sequence[tuple[str, HeaderValue]], +] + +# The possible types returned by a route function. +ResponseReturnValue = t.Union[ + ResponseValue, + tuple[ResponseValue, HeadersValue], + tuple[ResponseValue, int], + 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[[], 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[[], dict[str, t.Any]], + t.Callable[[], t.Awaitable[dict[str, t.Any]]], +] +TemplateFilterCallable = t.Callable[..., t.Any] +TemplateGlobalCallable = t.Callable[..., t.Any] +TemplateTestCallable = t.Callable[..., bool] +URLDefaultCallable = t.Callable[[str, dict[str, t.Any]], None] +URLValuePreprocessorCallable = t.Callable[ + [t.Optional[str], t.Optional[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/UIKatabatic/Lib/site-packages/flask/views.py b/UIKatabatic/Lib/site-packages/flask/views.py new file mode 100644 index 00000000..53fe976d --- /dev/null +++ b/UIKatabatic/Lib/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[..., t.Any]]] = [] + + #: 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) # pyright: ignore + + 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/UIKatabatic/Lib/site-packages/flask/wrappers.py b/UIKatabatic/Lib/site-packages/flask/wrappers.py new file mode 100644 index 00000000..bab61029 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/flask/wrappers.py @@ -0,0 +1,257 @@ +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 + + _max_content_length: int | None = None + _max_form_memory_size: int | None = None + _max_form_parts: int | None = None + + @property + def max_content_length(self) -> int | None: + """The maximum number of bytes that will be read during this request. If + this limit is exceeded, a 413 :exc:`~werkzeug.exceptions.RequestEntityTooLarge` + error is raised. If it is set to ``None``, no limit is enforced at the + Flask application level. However, if it is ``None`` and the request has + no ``Content-Length`` header and the WSGI server does not indicate that + it terminates the stream, then no data is read to avoid an infinite + stream. + + Each request defaults to the :data:`MAX_CONTENT_LENGTH` config, which + defaults to ``None``. It can be set on a specific ``request`` to apply + the limit to that specific view. This should be set appropriately based + on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This can be set per-request. + + .. versionchanged:: 0.6 + This is configurable through Flask config. + """ + if self._max_content_length is not None: + return self._max_content_length + + if not current_app: + return super().max_content_length + + return current_app.config["MAX_CONTENT_LENGTH"] # type: ignore[no-any-return] + + @max_content_length.setter + def max_content_length(self, value: int | None) -> None: + self._max_content_length = value + + @property + def max_form_memory_size(self) -> int | None: + """The maximum size in bytes any non-file form field may be in a + ``multipart/form-data`` body. If this limit is exceeded, a 413 + :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it + is set to ``None``, no limit is enforced at the Flask application level. + + Each request defaults to the :data:`MAX_FORM_MEMORY_SIZE` config, which + defaults to ``500_000``. It can be set on a specific ``request`` to + apply the limit to that specific view. This should be set appropriately + based on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This is configurable through Flask config. + """ + if self._max_form_memory_size is not None: + return self._max_form_memory_size + + if not current_app: + return super().max_form_memory_size + + return current_app.config["MAX_FORM_MEMORY_SIZE"] # type: ignore[no-any-return] + + @max_form_memory_size.setter + def max_form_memory_size(self, value: int | None) -> None: + self._max_form_memory_size = value + + @property # type: ignore[override] + def max_form_parts(self) -> int | None: + """The maximum number of fields that may be present in a + ``multipart/form-data`` body. If this limit is exceeded, a 413 + :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it + is set to ``None``, no limit is enforced at the Flask application level. + + Each request defaults to the :data:`MAX_FORM_PARTS` config, which + defaults to ``1_000``. It can be set on a specific ``request`` to apply + the limit to that specific view. This should be set appropriately based + on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This is configurable through Flask config. + """ + if self._max_form_parts is not None: + return self._max_form_parts + + if not current_app: + return super().max_form_parts + + return current_app.config["MAX_FORM_PARTS"] # type: ignore[no-any-return] + + @max_form_parts.setter + def max_form_parts(self, value: int | None) -> None: + self._max_form_parts = value + + @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 # type: ignore[no-any-return] + + 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 ebr: + if current_app and current_app.debug: + raise + + raise BadRequest() from ebr + + +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/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/LICENSE b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/METADATA b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/METADATA new file mode 100644 index 00000000..392e0d6e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/METADATA @@ -0,0 +1,133 @@ +Metadata-Version: 2.2 +Name: importlib_metadata +Version: 8.6.1 +Summary: Read metadata from Python packages +Author-email: "Jason R. Coombs" +Project-URL: Source, https://github.com/python/importlib_metadata +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Requires-Python: >=3.9 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: zipp>=3.20 +Requires-Dist: typing-extensions>=3.6.4; python_version < "3.8" +Provides-Extra: test +Requires-Dist: pytest!=8.1.*,>=6; extra == "test" +Requires-Dist: importlib_resources>=1.3; python_version < "3.9" and extra == "test" +Requires-Dist: packaging; extra == "test" +Requires-Dist: pyfakefs; extra == "test" +Requires-Dist: flufl.flake8; extra == "test" +Requires-Dist: pytest-perf>=0.9.2; extra == "test" +Requires-Dist: jaraco.test>=5.4; extra == "test" +Provides-Extra: doc +Requires-Dist: sphinx>=3.5; extra == "doc" +Requires-Dist: jaraco.packaging>=9.3; extra == "doc" +Requires-Dist: rst.linker>=1.9; extra == "doc" +Requires-Dist: furo; extra == "doc" +Requires-Dist: sphinx-lint; extra == "doc" +Requires-Dist: jaraco.tidelift>=1.4; extra == "doc" +Provides-Extra: perf +Requires-Dist: ipython; extra == "perf" +Provides-Extra: check +Requires-Dist: pytest-checkdocs>=2.4; extra == "check" +Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "check" +Provides-Extra: cover +Requires-Dist: pytest-cov; extra == "cover" +Provides-Extra: enabler +Requires-Dist: pytest-enabler>=2.2; extra == "enabler" +Provides-Extra: type +Requires-Dist: pytest-mypy; extra == "type" + +.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg + :target: https://pypi.org/project/importlib_metadata + +.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg + +.. image:: https://github.com/python/importlib_metadata/actions/workflows/main.yml/badge.svg + :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22 + :alt: tests + +.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json + :target: https://github.com/astral-sh/ruff + :alt: Ruff + +.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest + :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest + +.. image:: https://img.shields.io/badge/skeleton-2024-informational + :target: https://blog.jaraco.com/skeleton + +.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata + :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme + +Library to access the metadata for a Python package. + +This package supplies third-party access to the functionality of +`importlib.metadata `_ +including improvements added to subsequent Python versions. + + +Compatibility +============= + +New features are introduced in this third-party library and later merged +into CPython. The following table indicates which versions of this library +were contributed to different versions in the standard library: + +.. list-table:: + :header-rows: 1 + + * - importlib_metadata + - stdlib + * - 7.0 + - 3.13 + * - 6.5 + - 3.12 + * - 4.13 + - 3.11 + * - 4.6 + - 3.10 + * - 1.4 + - 3.8 + + +Usage +===== + +See the `online documentation `_ +for usage details. + +`Finder authors +`_ can +also add support for custom package installers. See the above documentation +for details. + + +Caveats +======= + +This project primarily supports third-party packages installed by PyPA +tools (or other conforming packages). It does not support: + +- Packages in the stdlib. +- Packages installed without metadata. + +Project details +=============== + + * Project home: https://github.com/python/importlib_metadata + * Report bugs at: https://github.com/python/importlib_metadata/issues + * Code hosting: https://github.com/python/importlib_metadata + * Documentation: https://importlib-metadata.readthedocs.io/ + +For Enterprise +============== + +Available as part of the Tidelift Subscription. + +This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. + +`Learn more `_. diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/RECORD b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/RECORD new file mode 100644 index 00000000..4fbf8d98 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/RECORD @@ -0,0 +1,31 @@ +importlib_metadata-8.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +importlib_metadata-8.6.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358 +importlib_metadata-8.6.1.dist-info/METADATA,sha256=F24ATbamOm1kp40IQGodtMLWMrH-fVEksdySlZk_KAY,4738 +importlib_metadata-8.6.1.dist-info/RECORD,, +importlib_metadata-8.6.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91 +importlib_metadata-8.6.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19 +importlib_metadata/__init__.py,sha256=-Sk7aVqfmzLecdjSOpLKo1P_PegQanR__HsMMyEq0PI,35853 +importlib_metadata/__pycache__/__init__.cpython-39.pyc,, +importlib_metadata/__pycache__/_adapters.cpython-39.pyc,, +importlib_metadata/__pycache__/_collections.cpython-39.pyc,, +importlib_metadata/__pycache__/_compat.cpython-39.pyc,, +importlib_metadata/__pycache__/_functools.cpython-39.pyc,, +importlib_metadata/__pycache__/_itertools.cpython-39.pyc,, +importlib_metadata/__pycache__/_meta.cpython-39.pyc,, +importlib_metadata/__pycache__/_text.cpython-39.pyc,, +importlib_metadata/__pycache__/diagnose.cpython-39.pyc,, +importlib_metadata/_adapters.py,sha256=9Y3FAlZuoo8pOMVLnKXm5Xx6hKgsdUQOXF5SkiDGqWo,3784 +importlib_metadata/_collections.py,sha256=CJ0OTCHIjWA0ZIVS4voORAsn2R4R2cQBEtPsZEJpASY,743 +importlib_metadata/_compat.py,sha256=VC5ZDLlT-BcshauCShdFJvMNLntJJfZzNK1meGa-enw,1313 +importlib_metadata/_functools.py,sha256=bSbAqC9-2niWM9364FYBx9GWtetnJEfo4mdLv8uMl7c,2895 +importlib_metadata/_itertools.py,sha256=nMvp9SfHAQ_JYwK4L2i64lr3GRXGlYlikGTVzWbys_E,5351 +importlib_metadata/_meta.py,sha256=JzuqMG4za5MoaBPCPv61c26fUBdQPZ4by3pbaQA_E_o,1823 +importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166 +importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +importlib_metadata/compat/__pycache__/__init__.cpython-39.pyc,, +importlib_metadata/compat/__pycache__/py311.cpython-39.pyc,, +importlib_metadata/compat/__pycache__/py39.cpython-39.pyc,, +importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608 +importlib_metadata/compat/py39.py,sha256=cPkMv6-0ilK-0Jw_Tkn0xYbOKJZc4WJKQHow0c2T44w,1102 +importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379 +importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/WHEEL new file mode 100644 index 00000000..505164bc --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.8.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/top_level.txt b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/top_level.txt new file mode 100644 index 00000000..bbb07547 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata-8.6.1.dist-info/top_level.txt @@ -0,0 +1 @@ +importlib_metadata diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__init__.py b/UIKatabatic/Lib/site-packages/importlib_metadata/__init__.py new file mode 100644 index 00000000..46a14e64 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/__init__.py @@ -0,0 +1,1132 @@ +""" +APIs exposing metadata from third-party Python packages. + +This codebase is shared between importlib.metadata in the stdlib +and importlib_metadata in PyPI. See +https://github.com/python/importlib_metadata/wiki/Development-Methodology +for more detail. +""" + +from __future__ import annotations + +import abc +import collections +import email +import functools +import itertools +import operator +import os +import pathlib +import posixpath +import re +import sys +import textwrap +import types +from contextlib import suppress +from importlib import import_module +from importlib.abc import MetaPathFinder +from itertools import starmap +from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast + +from . import _meta +from ._collections import FreezableDefaultDict, Pair +from ._compat import ( + NullFinder, + install, +) +from ._functools import method_cache, pass_none +from ._itertools import always_iterable, bucket, unique_everseen +from ._meta import PackageMetadata, SimplePath +from .compat import py39, py311 + +__all__ = [ + 'Distribution', + 'DistributionFinder', + 'PackageMetadata', + 'PackageNotFoundError', + 'SimplePath', + 'distribution', + 'distributions', + 'entry_points', + 'files', + 'metadata', + 'packages_distributions', + 'requires', + 'version', +] + + +class PackageNotFoundError(ModuleNotFoundError): + """The package was not found.""" + + def __str__(self) -> str: + return f"No package metadata was found for {self.name}" + + @property + def name(self) -> str: # type: ignore[override] # make readonly + (name,) = self.args + return name + + +class Sectioned: + """ + A simple entry point config parser for performance + + >>> for item in Sectioned.read(Sectioned._sample): + ... print(item) + Pair(name='sec1', value='# comments ignored') + Pair(name='sec1', value='a = 1') + Pair(name='sec1', value='b = 2') + Pair(name='sec2', value='a = 2') + + >>> res = Sectioned.section_pairs(Sectioned._sample) + >>> item = next(res) + >>> item.name + 'sec1' + >>> item.value + Pair(name='a', value='1') + >>> item = next(res) + >>> item.value + Pair(name='b', value='2') + >>> item = next(res) + >>> item.name + 'sec2' + >>> item.value + Pair(name='a', value='2') + >>> list(res) + [] + """ + + _sample = textwrap.dedent( + """ + [sec1] + # comments ignored + a = 1 + b = 2 + + [sec2] + a = 2 + """ + ).lstrip() + + @classmethod + def section_pairs(cls, text): + return ( + section._replace(value=Pair.parse(section.value)) + for section in cls.read(text, filter_=cls.valid) + if section.name is not None + ) + + @staticmethod + def read(text, filter_=None): + lines = filter(filter_, map(str.strip, text.splitlines())) + name = None + for value in lines: + section_match = value.startswith('[') and value.endswith(']') + if section_match: + name = value.strip('[]') + continue + yield Pair(name, value) + + @staticmethod + def valid(line: str): + return line and not line.startswith('#') + + +class EntryPoint: + """An entry point as defined by Python packaging conventions. + + See `the packaging docs on entry points + `_ + for more information. + + >>> ep = EntryPoint( + ... name=None, group=None, value='package.module:attr [extra1, extra2]') + >>> ep.module + 'package.module' + >>> ep.attr + 'attr' + >>> ep.extras + ['extra1', 'extra2'] + """ + + pattern = re.compile( + r'(?P[\w.]+)\s*' + r'(:\s*(?P[\w.]+)\s*)?' + r'((?P\[.*\])\s*)?$' + ) + """ + A regular expression describing the syntax for an entry point, + which might look like: + + - module + - package.module + - package.module:attribute + - package.module:object.attribute + - package.module:attr [extra1, extra2] + + Other combinations are possible as well. + + The expression is lenient about whitespace around the ':', + following the attr, and following any extras. + """ + + name: str + value: str + group: str + + dist: Optional[Distribution] = None + + def __init__(self, name: str, value: str, group: str) -> None: + vars(self).update(name=name, value=value, group=group) + + def load(self) -> Any: + """Load the entry point from its definition. If only a module + is indicated by the value, return that module. Otherwise, + return the named object. + """ + match = cast(Match, self.pattern.match(self.value)) + module = import_module(match.group('module')) + attrs = filter(None, (match.group('attr') or '').split('.')) + return functools.reduce(getattr, attrs, module) + + @property + def module(self) -> str: + match = self.pattern.match(self.value) + assert match is not None + return match.group('module') + + @property + def attr(self) -> str: + match = self.pattern.match(self.value) + assert match is not None + return match.group('attr') + + @property + def extras(self) -> List[str]: + match = self.pattern.match(self.value) + assert match is not None + return re.findall(r'\w+', match.group('extras') or '') + + def _for(self, dist): + vars(self).update(dist=dist) + return self + + def matches(self, **params): + """ + EntryPoint matches the given parameters. + + >>> ep = EntryPoint(group='foo', name='bar', value='bing:bong [extra1, extra2]') + >>> ep.matches(group='foo') + True + >>> ep.matches(name='bar', value='bing:bong [extra1, extra2]') + True + >>> ep.matches(group='foo', name='other') + False + >>> ep.matches() + True + >>> ep.matches(extras=['extra1', 'extra2']) + True + >>> ep.matches(module='bing') + True + >>> ep.matches(attr='bong') + True + """ + self._disallow_dist(params) + attrs = (getattr(self, param) for param in params) + return all(map(operator.eq, params.values(), attrs)) + + @staticmethod + def _disallow_dist(params): + """ + Querying by dist is not allowed (dist objects are not comparable). + >>> EntryPoint(name='fan', value='fav', group='fag').matches(dist='foo') + Traceback (most recent call last): + ... + ValueError: "dist" is not suitable for matching... + """ + if "dist" in params: + raise ValueError( + '"dist" is not suitable for matching. ' + "Instead, use Distribution.entry_points.select() on a " + "located distribution." + ) + + def _key(self): + return self.name, self.value, self.group + + def __lt__(self, other): + return self._key() < other._key() + + def __eq__(self, other): + return self._key() == other._key() + + def __setattr__(self, name, value): + raise AttributeError("EntryPoint objects are immutable.") + + def __repr__(self): + return ( + f'EntryPoint(name={self.name!r}, value={self.value!r}, ' + f'group={self.group!r})' + ) + + def __hash__(self) -> int: + return hash(self._key()) + + +class EntryPoints(tuple): + """ + An immutable collection of selectable EntryPoint objects. + """ + + __slots__ = () + + def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override] # Work with str instead of int + """ + Get the EntryPoint in self matching name. + """ + try: + return next(iter(self.select(name=name))) + except StopIteration: + raise KeyError(name) + + def __repr__(self): + """ + Repr with classname and tuple constructor to + signal that we deviate from regular tuple behavior. + """ + return '%s(%r)' % (self.__class__.__name__, tuple(self)) + + def select(self, **params) -> EntryPoints: + """ + Select entry points from self that match the + given parameters (typically group and/or name). + """ + return EntryPoints(ep for ep in self if py39.ep_matches(ep, **params)) + + @property + def names(self) -> Set[str]: + """ + Return the set of all names of all entry points. + """ + return {ep.name for ep in self} + + @property + def groups(self) -> Set[str]: + """ + Return the set of all groups of all entry points. + """ + return {ep.group for ep in self} + + @classmethod + def _from_text_for(cls, text, dist): + return cls(ep._for(dist) for ep in cls._from_text(text)) + + @staticmethod + def _from_text(text): + return ( + EntryPoint(name=item.value.name, value=item.value.value, group=item.name) + for item in Sectioned.section_pairs(text or '') + ) + + +class PackagePath(pathlib.PurePosixPath): + """A reference to a path in a package""" + + hash: Optional[FileHash] + size: int + dist: Distribution + + def read_text(self, encoding: str = 'utf-8') -> str: + return self.locate().read_text(encoding=encoding) + + def read_binary(self) -> bytes: + return self.locate().read_bytes() + + def locate(self) -> SimplePath: + """Return a path-like object for this path""" + return self.dist.locate_file(self) + + +class FileHash: + def __init__(self, spec: str) -> None: + self.mode, _, self.value = spec.partition('=') + + def __repr__(self) -> str: + return f'' + + +class Distribution(metaclass=abc.ABCMeta): + """ + An abstract Python distribution package. + + Custom providers may derive from this class and define + the abstract methods to provide a concrete implementation + for their environment. Some providers may opt to override + the default implementation of some properties to bypass + the file-reading mechanism. + """ + + @abc.abstractmethod + def read_text(self, filename) -> Optional[str]: + """Attempt to load metadata file given by the name. + + Python distribution metadata is organized by blobs of text + typically represented as "files" in the metadata directory + (e.g. package-1.0.dist-info). These files include things + like: + + - METADATA: The distribution metadata including fields + like Name and Version and Description. + - entry_points.txt: A series of entry points as defined in + `the entry points spec `_. + - RECORD: A record of files according to + `this recording spec `_. + + A package may provide any set of files, including those + not listed here or none at all. + + :param filename: The name of the file in the distribution info. + :return: The text if found, otherwise None. + """ + + @abc.abstractmethod + def locate_file(self, path: str | os.PathLike[str]) -> SimplePath: + """ + Given a path to a file in this distribution, return a SimplePath + to it. + + This method is used by callers of ``Distribution.files()`` to + locate files within the distribution. If it's possible for a + Distribution to represent files in the distribution as + ``SimplePath`` objects, it should implement this method + to resolve such objects. + + Some Distribution providers may elect not to resolve SimplePath + objects within the distribution by raising a + NotImplementedError, but consumers of such a Distribution would + be unable to invoke ``Distribution.files()``. + """ + + @classmethod + def from_name(cls, name: str) -> Distribution: + """Return the Distribution for the given package name. + + :param name: The name of the distribution package to search for. + :return: The Distribution instance (or subclass thereof) for the named + package, if found. + :raises PackageNotFoundError: When the named package's distribution + metadata cannot be found. + :raises ValueError: When an invalid value is supplied for name. + """ + if not name: + raise ValueError("A distribution name is required.") + try: + return next(iter(cls._prefer_valid(cls.discover(name=name)))) + except StopIteration: + raise PackageNotFoundError(name) + + @classmethod + def discover( + cls, *, context: Optional[DistributionFinder.Context] = None, **kwargs + ) -> Iterable[Distribution]: + """Return an iterable of Distribution objects for all packages. + + Pass a ``context`` or pass keyword arguments for constructing + a context. + + :context: A ``DistributionFinder.Context`` object. + :return: Iterable of Distribution objects for packages matching + the context. + """ + if context and kwargs: + raise ValueError("cannot accept context and kwargs") + context = context or DistributionFinder.Context(**kwargs) + return itertools.chain.from_iterable( + resolver(context) for resolver in cls._discover_resolvers() + ) + + @staticmethod + def _prefer_valid(dists: Iterable[Distribution]) -> Iterable[Distribution]: + """ + Prefer (move to the front) distributions that have metadata. + + Ref python/importlib_resources#489. + """ + buckets = bucket(dists, lambda dist: bool(dist.metadata)) + return itertools.chain(buckets[True], buckets[False]) + + @staticmethod + def at(path: str | os.PathLike[str]) -> Distribution: + """Return a Distribution for the indicated metadata path. + + :param path: a string or path-like object + :return: a concrete Distribution instance for the path + """ + return PathDistribution(pathlib.Path(path)) + + @staticmethod + def _discover_resolvers(): + """Search the meta_path for resolvers (MetadataPathFinders).""" + declared = ( + getattr(finder, 'find_distributions', None) for finder in sys.meta_path + ) + return filter(None, declared) + + @property + def metadata(self) -> _meta.PackageMetadata: + """Return the parsed metadata for this Distribution. + + The returned object will have keys that name the various bits of + metadata per the + `Core metadata specifications `_. + + Custom providers may provide the METADATA file or override this + property. + """ + # deferred for performance (python/cpython#109829) + from . import _adapters + + opt_text = ( + self.read_text('METADATA') + or self.read_text('PKG-INFO') + # This last clause is here to support old egg-info files. Its + # effect is to just end up using the PathDistribution's self._path + # (which points to the egg-info file) attribute unchanged. + or self.read_text('') + ) + text = cast(str, opt_text) + return _adapters.Message(email.message_from_string(text)) + + @property + def name(self) -> str: + """Return the 'Name' metadata for the distribution package.""" + return self.metadata['Name'] + + @property + def _normalized_name(self): + """Return a normalized version of the name.""" + return Prepared.normalize(self.name) + + @property + def version(self) -> str: + """Return the 'Version' metadata for the distribution package.""" + return self.metadata['Version'] + + @property + def entry_points(self) -> EntryPoints: + """ + Return EntryPoints for this distribution. + + Custom providers may provide the ``entry_points.txt`` file + or override this property. + """ + return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self) + + @property + def files(self) -> Optional[List[PackagePath]]: + """Files in this distribution. + + :return: List of PackagePath for this distribution or None + + Result is `None` if the metadata file that enumerates files + (i.e. RECORD for dist-info, or installed-files.txt or + SOURCES.txt for egg-info) is missing. + Result may be empty if the metadata exists but is empty. + + Custom providers are recommended to provide a "RECORD" file (in + ``read_text``) or override this property to allow for callers to be + able to resolve filenames provided by the package. + """ + + def make_file(name, hash=None, size_str=None): + result = PackagePath(name) + result.hash = FileHash(hash) if hash else None + result.size = int(size_str) if size_str else None + result.dist = self + return result + + @pass_none + def make_files(lines): + # Delay csv import, since Distribution.files is not as widely used + # as other parts of importlib.metadata + import csv + + return starmap(make_file, csv.reader(lines)) + + @pass_none + def skip_missing_files(package_paths): + return list(filter(lambda path: path.locate().exists(), package_paths)) + + return skip_missing_files( + make_files( + self._read_files_distinfo() + or self._read_files_egginfo_installed() + or self._read_files_egginfo_sources() + ) + ) + + def _read_files_distinfo(self): + """ + Read the lines of RECORD. + """ + text = self.read_text('RECORD') + return text and text.splitlines() + + def _read_files_egginfo_installed(self): + """ + Read installed-files.txt and return lines in a similar + CSV-parsable format as RECORD: each file must be placed + relative to the site-packages directory and must also be + quoted (since file names can contain literal commas). + + This file is written when the package is installed by pip, + but it might not be written for other installation methods. + Assume the file is accurate if it exists. + """ + text = self.read_text('installed-files.txt') + # Prepend the .egg-info/ subdir to the lines in this file. + # But this subdir is only available from PathDistribution's + # self._path. + subdir = getattr(self, '_path', None) + if not text or not subdir: + return + + paths = ( + py311.relative_fix((subdir / name).resolve()) + .relative_to(self.locate_file('').resolve(), walk_up=True) + .as_posix() + for name in text.splitlines() + ) + return map('"{}"'.format, paths) + + def _read_files_egginfo_sources(self): + """ + Read SOURCES.txt and return lines in a similar CSV-parsable + format as RECORD: each file name must be quoted (since it + might contain literal commas). + + Note that SOURCES.txt is not a reliable source for what + files are installed by a package. This file is generated + for a source archive, and the files that are present + there (e.g. setup.py) may not correctly reflect the files + that are present after the package has been installed. + """ + text = self.read_text('SOURCES.txt') + return text and map('"{}"'.format, text.splitlines()) + + @property + def requires(self) -> Optional[List[str]]: + """Generated requirements specified for this Distribution""" + reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs() + return reqs and list(reqs) + + def _read_dist_info_reqs(self): + return self.metadata.get_all('Requires-Dist') + + def _read_egg_info_reqs(self): + source = self.read_text('requires.txt') + return pass_none(self._deps_from_requires_text)(source) + + @classmethod + def _deps_from_requires_text(cls, source): + return cls._convert_egg_info_reqs_to_simple_reqs(Sectioned.read(source)) + + @staticmethod + def _convert_egg_info_reqs_to_simple_reqs(sections): + """ + Historically, setuptools would solicit and store 'extra' + requirements, including those with environment markers, + in separate sections. More modern tools expect each + dependency to be defined separately, with any relevant + extras and environment markers attached directly to that + requirement. This method converts the former to the + latter. See _test_deps_from_requires_text for an example. + """ + + def make_condition(name): + return name and f'extra == "{name}"' + + def quoted_marker(section): + section = section or '' + extra, sep, markers = section.partition(':') + if extra and markers: + markers = f'({markers})' + conditions = list(filter(None, [markers, make_condition(extra)])) + return '; ' + ' and '.join(conditions) if conditions else '' + + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + + for section in sections: + space = url_req_space(section.value) + yield section.value + space + quoted_marker(section.name) + + @property + def origin(self): + return self._load_json('direct_url.json') + + def _load_json(self, filename): + # Deferred for performance (python/importlib_metadata#503) + import json + + return pass_none(json.loads)( + self.read_text(filename), + object_hook=lambda data: types.SimpleNamespace(**data), + ) + + +class DistributionFinder(MetaPathFinder): + """ + A MetaPathFinder capable of discovering installed distributions. + + Custom providers should implement this interface in order to + supply metadata. + """ + + class Context: + """ + Keyword arguments presented by the caller to + ``distributions()`` or ``Distribution.discover()`` + to narrow the scope of a search for distributions + in all DistributionFinders. + + Each DistributionFinder may expect any parameters + and should attempt to honor the canonical + parameters defined below when appropriate. + + This mechanism gives a custom provider a means to + solicit additional details from the caller beyond + "name" and "path" when searching distributions. + For example, imagine a provider that exposes suites + of packages in either a "public" or "private" ``realm``. + A caller may wish to query only for distributions in + a particular realm and could call + ``distributions(realm="private")`` to signal to the + custom provider to only include distributions from that + realm. + """ + + name = None + """ + Specific name for which a distribution finder should match. + A name of ``None`` matches all distributions. + """ + + def __init__(self, **kwargs): + vars(self).update(kwargs) + + @property + def path(self) -> List[str]: + """ + The sequence of directory path that a distribution finder + should search. + + Typically refers to Python installed package paths such as + "site-packages" directories and defaults to ``sys.path``. + """ + return vars(self).get('path', sys.path) + + @abc.abstractmethod + def find_distributions(self, context=Context()) -> Iterable[Distribution]: + """ + Find distributions. + + Return an iterable of all Distribution instances capable of + loading the metadata for packages matching the ``context``, + a DistributionFinder.Context instance. + """ + + +class FastPath: + """ + Micro-optimized class for searching a root for children. + + Root is a path on the file system that may contain metadata + directories either as natural directories or within a zip file. + + >>> FastPath('').children() + ['...'] + + FastPath objects are cached and recycled for any given root. + + >>> FastPath('foobar') is FastPath('foobar') + True + """ + + @functools.lru_cache() # type: ignore[misc] + def __new__(cls, root): + return super().__new__(cls) + + def __init__(self, root): + self.root = root + + def joinpath(self, child): + return pathlib.Path(self.root, child) + + def children(self): + with suppress(Exception): + return os.listdir(self.root or '.') + with suppress(Exception): + return self.zip_children() + return [] + + def zip_children(self): + # deferred for performance (python/importlib_metadata#502) + from zipp.compat.overlay import zipfile + + zip_path = zipfile.Path(self.root) + names = zip_path.root.namelist() + self.joinpath = zip_path.joinpath + + return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names) + + def search(self, name): + return self.lookup(self.mtime).search(name) + + @property + def mtime(self): + with suppress(OSError): + return os.stat(self.root).st_mtime + self.lookup.cache_clear() + + @method_cache + def lookup(self, mtime): + return Lookup(self) + + +class Lookup: + """ + A micro-optimized class for searching a (fast) path for metadata. + """ + + def __init__(self, path: FastPath): + """ + Calculate all of the children representing metadata. + + From the children in the path, calculate early all of the + children that appear to represent metadata (infos) or legacy + metadata (eggs). + """ + + base = os.path.basename(path.root).lower() + base_is_egg = base.endswith(".egg") + self.infos = FreezableDefaultDict(list) + self.eggs = FreezableDefaultDict(list) + + for child in path.children(): + low = child.lower() + if low.endswith((".dist-info", ".egg-info")): + # rpartition is faster than splitext and suitable for this purpose. + name = low.rpartition(".")[0].partition("-")[0] + normalized = Prepared.normalize(name) + self.infos[normalized].append(path.joinpath(child)) + elif base_is_egg and low == "egg-info": + name = base.rpartition(".")[0].partition("-")[0] + legacy_normalized = Prepared.legacy_normalize(name) + self.eggs[legacy_normalized].append(path.joinpath(child)) + + self.infos.freeze() + self.eggs.freeze() + + def search(self, prepared: Prepared): + """ + Yield all infos and eggs matching the Prepared query. + """ + infos = ( + self.infos[prepared.normalized] + if prepared + else itertools.chain.from_iterable(self.infos.values()) + ) + eggs = ( + self.eggs[prepared.legacy_normalized] + if prepared + else itertools.chain.from_iterable(self.eggs.values()) + ) + return itertools.chain(infos, eggs) + + +class Prepared: + """ + A prepared search query for metadata on a possibly-named package. + + Pre-calculates the normalization to prevent repeated operations. + + >>> none = Prepared(None) + >>> none.normalized + >>> none.legacy_normalized + >>> bool(none) + False + >>> sample = Prepared('Sample__Pkg-name.foo') + >>> sample.normalized + 'sample_pkg_name_foo' + >>> sample.legacy_normalized + 'sample__pkg_name.foo' + >>> bool(sample) + True + """ + + normalized = None + legacy_normalized = None + + def __init__(self, name: Optional[str]): + self.name = name + if name is None: + return + self.normalized = self.normalize(name) + self.legacy_normalized = self.legacy_normalize(name) + + @staticmethod + def normalize(name): + """ + PEP 503 normalization plus dashes as underscores. + """ + return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') + + @staticmethod + def legacy_normalize(name): + """ + Normalize the package name as found in the convention in + older packaging tools versions and specs. + """ + return name.lower().replace('-', '_') + + def __bool__(self): + return bool(self.name) + + +@install +class MetadataPathFinder(NullFinder, DistributionFinder): + """A degenerate finder for distribution packages on the file system. + + This finder supplies only a find_distributions() method for versions + of Python that do not have a PathFinder find_distributions(). + """ + + @classmethod + def find_distributions( + cls, context=DistributionFinder.Context() + ) -> Iterable[PathDistribution]: + """ + Find distributions. + + Return an iterable of all Distribution instances capable of + loading the metadata for packages matching ``context.name`` + (or all names if ``None`` indicated) along the paths in the list + of directories ``context.path``. + """ + found = cls._search_paths(context.name, context.path) + return map(PathDistribution, found) + + @classmethod + def _search_paths(cls, name, paths): + """Find metadata directories in paths heuristically.""" + prepared = Prepared(name) + return itertools.chain.from_iterable( + path.search(prepared) for path in map(FastPath, paths) + ) + + @classmethod + def invalidate_caches(cls) -> None: + FastPath.__new__.cache_clear() + + +class PathDistribution(Distribution): + def __init__(self, path: SimplePath) -> None: + """Construct a distribution. + + :param path: SimplePath indicating the metadata directory. + """ + self._path = path + + def read_text(self, filename: str | os.PathLike[str]) -> Optional[str]: + with suppress( + FileNotFoundError, + IsADirectoryError, + KeyError, + NotADirectoryError, + PermissionError, + ): + return self._path.joinpath(filename).read_text(encoding='utf-8') + + return None + + read_text.__doc__ = Distribution.read_text.__doc__ + + def locate_file(self, path: str | os.PathLike[str]) -> SimplePath: + return self._path.parent / path + + @property + def _normalized_name(self): + """ + Performance optimization: where possible, resolve the + normalized name from the file system path. + """ + stem = os.path.basename(str(self._path)) + return ( + pass_none(Prepared.normalize)(self._name_from_stem(stem)) + or super()._normalized_name + ) + + @staticmethod + def _name_from_stem(stem): + """ + >>> PathDistribution._name_from_stem('foo-3.0.egg-info') + 'foo' + >>> PathDistribution._name_from_stem('CherryPy-3.0.dist-info') + 'CherryPy' + >>> PathDistribution._name_from_stem('face.egg-info') + 'face' + >>> PathDistribution._name_from_stem('foo.bar') + """ + filename, ext = os.path.splitext(stem) + if ext not in ('.dist-info', '.egg-info'): + return + name, sep, rest = filename.partition('-') + return name + + +def distribution(distribution_name: str) -> Distribution: + """Get the ``Distribution`` instance for the named package. + + :param distribution_name: The name of the distribution package as a string. + :return: A ``Distribution`` instance (or subclass thereof). + """ + return Distribution.from_name(distribution_name) + + +def distributions(**kwargs) -> Iterable[Distribution]: + """Get all ``Distribution`` instances in the current environment. + + :return: An iterable of ``Distribution`` instances. + """ + return Distribution.discover(**kwargs) + + +def metadata(distribution_name: str) -> _meta.PackageMetadata: + """Get the metadata for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: A PackageMetadata containing the parsed metadata. + """ + return Distribution.from_name(distribution_name).metadata + + +def version(distribution_name: str) -> str: + """Get the version string for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: The version string for the package as defined in the package's + "Version" metadata key. + """ + return distribution(distribution_name).version + + +_unique = functools.partial( + unique_everseen, + key=py39.normalized_name, +) +""" +Wrapper for ``distributions`` to return unique distributions by name. +""" + + +def entry_points(**params) -> EntryPoints: + """Return EntryPoint objects for all installed packages. + + Pass selection parameters (group or name) to filter the + result to entry points matching those properties (see + EntryPoints.select()). + + :return: EntryPoints for all installed packages. + """ + eps = itertools.chain.from_iterable( + dist.entry_points for dist in _unique(distributions()) + ) + return EntryPoints(eps).select(**params) + + +def files(distribution_name: str) -> Optional[List[PackagePath]]: + """Return a list of files for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: List of files composing the distribution. + """ + return distribution(distribution_name).files + + +def requires(distribution_name: str) -> Optional[List[str]]: + """ + Return a list of requirements for the named package. + + :return: An iterable of requirements, suitable for + packaging.requirement.Requirement. + """ + return distribution(distribution_name).requires + + +def packages_distributions() -> Mapping[str, List[str]]: + """ + Return a mapping of top-level packages to their + distributions. + + >>> import collections.abc + >>> pkgs = packages_distributions() + >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values()) + True + """ + pkg_to_dist = collections.defaultdict(list) + for dist in distributions(): + for pkg in _top_level_declared(dist) or _top_level_inferred(dist): + pkg_to_dist[pkg].append(dist.metadata['Name']) + return dict(pkg_to_dist) + + +def _top_level_declared(dist): + return (dist.read_text('top_level.txt') or '').split() + + +def _topmost(name: PackagePath) -> Optional[str]: + """ + Return the top-most parent as long as there is a parent. + """ + top, *rest = name.parts + return top if rest else None + + +def _get_toplevel_name(name: PackagePath) -> str: + """ + Infer a possibly importable module name from a name presumed on + sys.path. + + >>> _get_toplevel_name(PackagePath('foo.py')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo.pyc')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo/__init__.py')) + 'foo' + >>> _get_toplevel_name(PackagePath('foo.pth')) + 'foo.pth' + >>> _get_toplevel_name(PackagePath('foo.dist-info')) + 'foo.dist-info' + """ + # Defer import of inspect for performance (python/cpython#118761) + import inspect + + return _topmost(name) or inspect.getmodulename(name) or str(name) + + +def _top_level_inferred(dist): + opt_names = set(map(_get_toplevel_name, always_iterable(dist.files))) + + def importable_name(name): + return '.' not in name + + return filter(importable_name, opt_names) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4bf10c28b1cd8d406b5907d9810a8c01f74192a3 GIT binary patch literal 41884 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 aC$L02ZDqff8yp+w)!2qYcA_w`?f(MxwcPLk literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_adapters.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_adapters.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cca03f63c823534fe6afc5451542f027474fbfd6 GIT binary patch literal 4623 zcmai2TW{RP73PrKi&iVi7p0C}Bca{a(jwN{jaw%$Tp_7swTb1mD#dBL*?^{YMiM11 zNzZU4Yas(gWgzZD9{TJSkox9-(w|W9wLpP9_stJYzcbvcWjkEWkaIm}&iT$|ez?=Q8bz~nKN4aC;m_4x$*mIoWz71_NvDFY4LX8wbr>eUk0uJq8J^gFO%v9 zq+7imL`^SH^Z3Z7R?IXXOR?cUPRH=(e$z`t$GqiK@@at>S0YaB?Z^+)Vj>+;2pe@oo5f^+Q1X%=ksZHI4L`6-5 z<=KVr?ObPal<6AwEV?f3=elXhbz2c{2lQQb-A8RN$VTKjY%xSZ3!L_qq>(WcMJOsV z-9CY^9LDHT2dD-Jt6RbrIg#HqxcLuuXdbe9K@_*gwoBal8~euCU>fjcKw5*mUey+-Bofy0Q>*Y^tcb7k_-I*U*v*b&aICN?!+Q7=8v(R=u9@hlKz<+q& z8_7g%nQZCxmqzGA7?o;fJF}Il6mj4+#q7+`J~LMx%+ZUwf`v@Gik}rN&kw4t3?uG_ zj9M<)VYoTlQ$S^8=~pvD>YDjl?>h5l88pJT9J~=W!lj{eHNu$;VSQ9?MeTq)Qouz> zN9>Bw@i%(NgFF)tIO}0<2s<$jkkA1#)<^Mi0v9Lo@H!j}9UEACyV85>-*R>>xFIF! zc5mIVP+mLn)rFN(T3R6c^*4MWJCpa66YS$MNUcFdS@V6GW282Rj+YR5vR z1-Ndp2XAffdQzqNc8tg+DpqPW10~DEtfeDw2bpRpQ%LIO?4U3XI? z&{+#8FWwdVcZfLQhKa8#@*4X7h>~SLr7|nx*Eu@?QGeGF91(^nThSW*Ek3e5 z_%DXeEG%w6Ehd2bA>+C8#vSilP zPDY|59>~tsMO2$O&DYZn^9dORdj>Cd$TrNsnvan84_JZIGOO293z*TI!a#q4#RJ<+ zOSc0!?`G7B=VKZnGw*!xgDehK$qH7a<3o`vH7YrInR<(EHw#PiumS|wbQ}ojcaEz; z1EQp}rG>6f%UJvfT{`oYv-sLVQFK)>Sg~*c$@dvnVx4nuV0J`)PnOVT3tiitIl zJEpvzm`4`b*Dx_9XiK+gmwh5b zvNH`TpfWArrDf--x`2u@3?4P%do5UiT&8{^A{S{erz22WXl3cL{4tGOqUtJD z6ig*KVr>$V;FlI-89}|tzNEw>o#>_|O%VjW)I{@qg_aS|dQ+`sN@t49{;A36m;ayn zz5ULQaz(prm8Xi6Wy@rGZl#<~j6_DcLX^r`UuHFOiFVfhF{f`;*`Yo`Z+-j@T>-Lx kc4W5nJDRM|rdb&x;#36qe?P?Ra-nnufNJ9@IPK@mj_nUJ4|N>uuSs8o|9dX`QSSjkilE4e0bQkARD+XU7#MW2wO`wn8s zSmLbZ$<_|Snv|jkKu2?;fK>}PO7E=Jm1YlUe zaICCKUkbxyT{&-Ci9vUmYvti8&TS%JqN>)G)d2u#8`BK?(R(x+F{RjjcGV3ArgXm8 z@Z10H*-$i%uGHZ6?(NN;;T##zgUz-5-Dfd&fAxo{jIIVst(tgY+DJj9 z;RYB{ejvaXy;p>T=z)ZE{80$z`V6}3!SIT_A#c%Uh4i&ODX2xKb87K( zvRgQ8!w`D+j9AQ+7<~z|f1s1)-K(UruJ`bssiiP(1jZ^3knz~|It~#xS`oan63G{^ zbwSLn{{b($p~rb87Mk7f)spi_y8RTu!_KYMHae?jnDrD DW1o48 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_compat.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58b72bac51e77a349ac984fe6e8211fd198bcc48 GIT binary patch literal 1881 zcmZuyTW=dh6rP#&W#cAMsS;6@i-uH+u+$orJ|Iw4wIphV04GuuAuOY1yfd~pp1pKt z9I%x>IX|R*n;qg>z<&6H`W>+1 zKd!d`KAu3gU&0`Xq?+`qC+$(mWH4eqCTo&il3pO|vH{Q9b0V8ExFj-IuwGq;asy@? zlAe%u>rb#lx@9xTtP@(7t?pFoXGtcNi7Bov8@{9S1L*cP433=9SL}i;$ZJZ83l@Zu z3j!wT{I?c|cA$l|T&g%X!sUh!p)b7%m*g3TpPkuGs+@=l;l`boKlfBh%iUPMtTV}Ail?fpahI>3-6A@{;5^Q z_A{k)(LYpn;_{+@`W5`X7ETNRleqs)GU(gHsrv=QE=J1slN2F<>qY2U!p={kI8Onu zPBAkKY&VgS1`H(JrVSe7+rJIhSFG*9hXj#al9#~V1#$F@E!ZLXA$&K5=!X&APXP!w2I?m6PNwN_~^6n3WRT3dzQDwcE!HlPQHc>N($;D&b zkK|Th@uTQyN&AUX{O;!uyzw+Q75yWVPc!M~Kt!H5g}QO$#Bw`PU~pD>QDbqQoTt?844#Zap0+0}t9hym%%;TB|dz6JqL7^E$^pzmU!Z2oZp#pg*1+ z&z1@JU2Z1gD&Out{PeR5=dy;o0K>4*!a*5N%iUrIQTe>kDpeUqnrE;jI2XFtOl(xl zpggUMuH3{)DE0mV4=^4iiZnK<`4FD%rg;w@Ud0F_{2c+r7`vCIN6K%!W_N{S89u7S V^B7fNH(>~A$ig7p3U6)S_y_Ki=f(g4 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_functools.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_functools.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9faa0948b01365c12a9215348f41fc15a22e45ed GIT binary patch literal 3137 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 Xb5?zj3xcr6_5>XO8?W}p()<4cj@t>= literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_meta.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/__pycache__/_meta.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed1a8dd1d1bbee0291d7e423da5119307e3f44c0 GIT binary patch literal 3225 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 tB`x!S0>> msg_text = textwrap.dedent(''' + ... Name: Foo + ... Version: 3.0 + ... License: blah + ... de-blah + ... + ... First line of description. + ... Second line of description. + ... + ... Fourth line! + ... ''').lstrip().replace('', '') + >>> msg = Message(email.message_from_string(msg_text)) + >>> msg['Description'] + 'First line of description.\nSecond line of description.\n\nFourth line!\n' + + Message should render even if values contain newlines. + + >>> print(msg) + Name: Foo + Version: 3.0 + License: blah + de-blah + Description: First line of description. + Second line of description. + + Fourth line! + + + """ + + multiple_use_keys = set( + map( + FoldedCase, + [ + 'Classifier', + 'Obsoletes-Dist', + 'Platform', + 'Project-URL', + 'Provides-Dist', + 'Provides-Extra', + 'Requires-Dist', + 'Requires-External', + 'Supported-Platform', + 'Dynamic', + ], + ) + ) + """ + Keys that may be indicated multiple times per PEP 566. + """ + + def __new__(cls, orig: email.message.Message): + res = super().__new__(cls) + vars(res).update(vars(orig)) + return res + + def __init__(self, *args, **kwargs): + self._headers = self._repair_headers() + + # suppress spurious error from mypy + def __iter__(self): + return super().__iter__() + + def __getitem__(self, item): + """ + Override parent behavior to typical dict behavior. + + ``email.message.Message`` will emit None values for missing + keys. Typical mappings, including this ``Message``, will raise + a key error for missing keys. + + Ref python/importlib_metadata#371. + """ + res = super().__getitem__(item) + if res is None: + raise KeyError(item) + return res + + def _repair_headers(self): + def redent(value): + "Correct for RFC822 indentation" + indent = ' ' * 8 + if not value or '\n' + indent not in value: + return value + return textwrap.dedent(indent + value) + + headers = [(key, redent(value)) for key, value in vars(self)['_headers']] + if self._payload: + headers.append(('Description', self.get_payload())) + self.set_payload('') + return headers + + def as_string(self): + return super().as_string(policy=RawPolicy()) + + @property + def json(self): + """ + Convert PackageMetadata to a JSON-compatible format + per PEP 0566. + """ + + def transform(key): + value = self.get_all(key) if key in self.multiple_use_keys else self[key] + if key == 'Keywords': + value = re.split(r'\s+', value) + tk = key.lower().replace('-', '_') + return tk, value + + return dict(map(transform, map(FoldedCase, self))) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_collections.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_collections.py new file mode 100644 index 00000000..cf0954e1 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_collections.py @@ -0,0 +1,30 @@ +import collections + + +# from jaraco.collections 3.3 +class FreezableDefaultDict(collections.defaultdict): + """ + Often it is desirable to prevent the mutation of + a default dict after its initial construction, such + as to prevent mutation during iteration. + + >>> dd = FreezableDefaultDict(list) + >>> dd[0].append('1') + >>> dd.freeze() + >>> dd[1] + [] + >>> len(dd) + 1 + """ + + def __missing__(self, key): + return getattr(self, '_frozen', super().__missing__)(key) + + def freeze(self): + self._frozen = lambda key: self.default_factory() + + +class Pair(collections.namedtuple('Pair', 'name value')): + @classmethod + def parse(cls, text): + return cls(*map(str.strip, text.split("=", 1))) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_compat.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_compat.py new file mode 100644 index 00000000..01356d69 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_compat.py @@ -0,0 +1,56 @@ +import platform +import sys + +__all__ = ['install', 'NullFinder'] + + +def install(cls): + """ + Class decorator for installation on sys.meta_path. + + Adds the backport DistributionFinder to sys.meta_path and + attempts to disable the finder functionality of the stdlib + DistributionFinder. + """ + sys.meta_path.append(cls()) + disable_stdlib_finder() + return cls + + +def disable_stdlib_finder(): + """ + Give the backport primacy for discovering path-based distributions + by monkey-patching the stdlib O_O. + + See #91 for more background for rationale on this sketchy + behavior. + """ + + def matches(finder): + return getattr( + finder, '__module__', None + ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions') + + for finder in filter(matches, sys.meta_path): # pragma: nocover + del finder.find_distributions + + +class NullFinder: + """ + A "Finder" (aka "MetaPathFinder") that never finds any modules, + but may find distributions. + """ + + @staticmethod + def find_spec(*args, **kwargs): + return None + + +def pypy_partial(val): + """ + Adjust for variable stacklevel on partial under PyPy. + + Workaround for #327. + """ + is_pypy = platform.python_implementation() == 'PyPy' + return val + is_pypy diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_functools.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_functools.py new file mode 100644 index 00000000..5dda6a21 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_functools.py @@ -0,0 +1,104 @@ +import functools +import types + + +# from jaraco.functools 3.3 +def method_cache(method, cache_wrapper=None): + """ + Wrap lru_cache to support storing the cache data in the object instances. + + Abstracts the common paradigm where the method explicitly saves an + underscore-prefixed protected property on first call and returns that + subsequently. + + >>> class MyClass: + ... calls = 0 + ... + ... @method_cache + ... def method(self, value): + ... self.calls += 1 + ... return value + + >>> a = MyClass() + >>> a.method(3) + 3 + >>> for x in range(75): + ... res = a.method(x) + >>> a.calls + 75 + + Note that the apparent behavior will be exactly like that of lru_cache + except that the cache is stored on each instance, so values in one + instance will not flush values from another, and when an instance is + deleted, so are the cached values for that instance. + + >>> b = MyClass() + >>> for x in range(35): + ... res = b.method(x) + >>> b.calls + 35 + >>> a.method(0) + 0 + >>> a.calls + 75 + + Note that if method had been decorated with ``functools.lru_cache()``, + a.calls would have been 76 (due to the cached value of 0 having been + flushed by the 'b' instance). + + Clear the cache with ``.cache_clear()`` + + >>> a.method.cache_clear() + + Same for a method that hasn't yet been called. + + >>> c = MyClass() + >>> c.method.cache_clear() + + Another cache wrapper may be supplied: + + >>> cache = functools.lru_cache(maxsize=2) + >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) + >>> a = MyClass() + >>> a.method2() + 3 + + Caution - do not subsequently wrap the method with another decorator, such + as ``@property``, which changes the semantics of the function. + + See also + http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ + for another implementation and additional justification. + """ + cache_wrapper = cache_wrapper or functools.lru_cache() + + def wrapper(self, *args, **kwargs): + # it's the first call, replace the method with a cached, bound method + bound_method = types.MethodType(method, self) + cached_method = cache_wrapper(bound_method) + setattr(self, method.__name__, cached_method) + return cached_method(*args, **kwargs) + + # Support cache clear even before cache has been created. + wrapper.cache_clear = lambda: None + + return wrapper + + +# From jaraco.functools 3.3 +def pass_none(func): + """ + Wrap func so it's not called if its first param is None + + >>> print_text = pass_none(print) + >>> print_text('text') + text + >>> print_text(None) + """ + + @functools.wraps(func) + def wrapper(param, *args, **kwargs): + if param is not None: + return func(param, *args, **kwargs) + + return wrapper diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_itertools.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_itertools.py new file mode 100644 index 00000000..79d37198 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_itertools.py @@ -0,0 +1,171 @@ +from collections import defaultdict, deque +from itertools import filterfalse + + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +# copied from more_itertools 8.8 +def always_iterable(obj, base_type=(str, bytes)): + """If *obj* is iterable, return an iterator over its items:: + + >>> obj = (1, 2, 3) + >>> list(always_iterable(obj)) + [1, 2, 3] + + If *obj* is not iterable, return a one-item iterable containing *obj*:: + + >>> obj = 1 + >>> list(always_iterable(obj)) + [1] + + If *obj* is ``None``, return an empty iterable: + + >>> obj = None + >>> list(always_iterable(None)) + [] + + By default, binary and text strings are not considered iterable:: + + >>> obj = 'foo' + >>> list(always_iterable(obj)) + ['foo'] + + If *base_type* is set, objects for which ``isinstance(obj, base_type)`` + returns ``True`` won't be considered iterable. + + >>> obj = {'a': 1} + >>> list(always_iterable(obj)) # Iterate over the dict's keys + ['a'] + >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit + [{'a': 1}] + + Set *base_type* to ``None`` to avoid any special handling and treat objects + Python considers iterable as iterable: + + >>> obj = 'foo' + >>> list(always_iterable(obj, base_type=None)) + ['f', 'o', 'o'] + """ + if obj is None: + return iter(()) + + if (base_type is not None) and isinstance(obj, base_type): + return iter((obj,)) + + try: + return iter(obj) + except TypeError: + return iter((obj,)) + + +# Copied from more_itertools 10.3 +class bucket: + """Wrap *iterable* and return an object that buckets the iterable into + child iterables based on a *key* function. + + >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3'] + >>> s = bucket(iterable, key=lambda x: x[0]) # Bucket by 1st character + >>> sorted(list(s)) # Get the keys + ['a', 'b', 'c'] + >>> a_iterable = s['a'] + >>> next(a_iterable) + 'a1' + >>> next(a_iterable) + 'a2' + >>> list(s['b']) + ['b1', 'b2', 'b3'] + + The original iterable will be advanced and its items will be cached until + they are used by the child iterables. This may require significant storage. + + By default, attempting to select a bucket to which no items belong will + exhaust the iterable and cache all values. + If you specify a *validator* function, selected buckets will instead be + checked against it. + + >>> from itertools import count + >>> it = count(1, 2) # Infinite sequence of odd numbers + >>> key = lambda x: x % 10 # Bucket by last digit + >>> validator = lambda x: x in {1, 3, 5, 7, 9} # Odd digits only + >>> s = bucket(it, key=key, validator=validator) + >>> 2 in s + False + >>> list(s[2]) + [] + + """ + + def __init__(self, iterable, key, validator=None): + self._it = iter(iterable) + self._key = key + self._cache = defaultdict(deque) + self._validator = validator or (lambda x: True) + + def __contains__(self, value): + if not self._validator(value): + return False + + try: + item = next(self[value]) + except StopIteration: + return False + else: + self._cache[value].appendleft(item) + + return True + + def _get_values(self, value): + """ + Helper to yield items from the parent iterator that match *value*. + Items that don't match are stored in the local cache as they + are encountered. + """ + while True: + # If we've cached some items that match the target value, emit + # the first one and evict it from the cache. + if self._cache[value]: + yield self._cache[value].popleft() + # Otherwise we need to advance the parent iterator to search for + # a matching item, caching the rest. + else: + while True: + try: + item = next(self._it) + except StopIteration: + return + item_value = self._key(item) + if item_value == value: + yield item + break + elif self._validator(item_value): + self._cache[item_value].append(item) + + def __iter__(self): + for item in self._it: + item_value = self._key(item) + if self._validator(item_value): + self._cache[item_value].append(item) + + yield from self._cache.keys() + + def __getitem__(self, value): + if not self._validator(value): + return iter(()) + + return self._get_values(value) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_meta.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_meta.py new file mode 100644 index 00000000..0942bbd9 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_meta.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +import os +from typing import ( + Any, + Dict, + Iterator, + List, + Optional, + Protocol, + TypeVar, + Union, + overload, +) + +_T = TypeVar("_T") + + +class PackageMetadata(Protocol): + def __len__(self) -> int: ... # pragma: no cover + + def __contains__(self, item: str) -> bool: ... # pragma: no cover + + def __getitem__(self, key: str) -> str: ... # pragma: no cover + + def __iter__(self) -> Iterator[str]: ... # pragma: no cover + + @overload + def get( + self, name: str, failobj: None = None + ) -> Optional[str]: ... # pragma: no cover + + @overload + def get(self, name: str, failobj: _T) -> Union[str, _T]: ... # pragma: no cover + + # overload per python/importlib_metadata#435 + @overload + def get_all( + self, name: str, failobj: None = None + ) -> Optional[List[Any]]: ... # pragma: no cover + + @overload + def get_all(self, name: str, failobj: _T) -> Union[List[Any], _T]: + """ + Return all values associated with a possibly multi-valued key. + """ + + @property + def json(self) -> Dict[str, Union[str, List[str]]]: + """ + A JSON-compatible form of the metadata. + """ + + +class SimplePath(Protocol): + """ + A minimal subset of pathlib.Path required by Distribution. + """ + + def joinpath( + self, other: Union[str, os.PathLike[str]] + ) -> SimplePath: ... # pragma: no cover + + def __truediv__( + self, other: Union[str, os.PathLike[str]] + ) -> SimplePath: ... # pragma: no cover + + @property + def parent(self) -> SimplePath: ... # pragma: no cover + + def read_text(self, encoding=None) -> str: ... # pragma: no cover + + def read_bytes(self) -> bytes: ... # pragma: no cover + + def exists(self) -> bool: ... # pragma: no cover diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/_text.py b/UIKatabatic/Lib/site-packages/importlib_metadata/_text.py new file mode 100644 index 00000000..c88cfbb2 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/_text.py @@ -0,0 +1,99 @@ +import re + +from ._functools import method_cache + + +# from jaraco.text 3.5 +class FoldedCase(str): + """ + A case insensitive string class; behaves just like str + except compares equal when the only variation is case. + + >>> s = FoldedCase('hello world') + + >>> s == 'Hello World' + True + + >>> 'Hello World' == s + True + + >>> s != 'Hello World' + False + + >>> s.index('O') + 4 + + >>> s.split('O') + ['hell', ' w', 'rld'] + + >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) + ['alpha', 'Beta', 'GAMMA'] + + Sequence membership is straightforward. + + >>> "Hello World" in [s] + True + >>> s in ["Hello World"] + True + + You may test for set inclusion, but candidate and elements + must both be folded. + + >>> FoldedCase("Hello World") in {s} + True + >>> s in {FoldedCase("Hello World")} + True + + String inclusion works as long as the FoldedCase object + is on the right. + + >>> "hello" in FoldedCase("Hello World") + True + + But not if the FoldedCase object is on the left: + + >>> FoldedCase('hello') in 'Hello World' + False + + In that case, use in_: + + >>> FoldedCase('hello').in_('Hello World') + True + + >>> FoldedCase('hello') > FoldedCase('Hello') + False + """ + + def __lt__(self, other): + return self.lower() < other.lower() + + def __gt__(self, other): + return self.lower() > other.lower() + + def __eq__(self, other): + return self.lower() == other.lower() + + def __ne__(self, other): + return self.lower() != other.lower() + + def __hash__(self): + return hash(self.lower()) + + def __contains__(self, other): + return super().lower().__contains__(other.lower()) + + def in_(self, other): + "Does self appear in other?" + return self in FoldedCase(other) + + # cache lower since it's likely to be called frequently. + @method_cache + def lower(self): + return super().lower() + + def index(self, sub): + return self.lower().index(sub.lower()) + + def split(self, splitter=' ', maxsplit=0): + pattern = re.compile(re.escape(splitter), re.I) + return pattern.split(self, maxsplit) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__init__.py b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a62b4311f1130ad1065a311565831428419f69e5 GIT binary patch literal 184 zcmYe~<>g`k0%Nsj=^*+sh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o11@*(xTqIJKxa zCNDKLry#~9wK%&ZzaS>m6NtPMOA?b3OEQyVd@_?_iZe@6bqf-cvlG)(i(@i#3-XIf yax#s<1_OzOXB183My}L*yQG?l;)(`fvo)u#0&r@axoPE literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py311.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py311.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cea98f4f44ae9aa5f684e1d20b87714220ddc828 GIT binary patch literal 1020 zcmY*Y&ubGw6rS1LB(*=Rs3=}!PQrpsC{Zb;7PTU%r3keMOCZkf%qEk}?kqF2O(XSI z(2M_phxXWiX|ICNvo}w^*@O}&dGlr_?|t8!?@j31+A@OCee`?q*+b};+bj+^LodM0 zE0`E!SfXg=afIu=7kRb!BcFN9KSNQ#y-|Y&W2B$)AaAk;Yr<)h;X@R*t^fxeB-pw6 za2x@c4`v?1#4z)I;%_L$%xA&b@>gup2%los_~9^`^gg676BwVA9#gH#oRL&%GPJfZ z+nvrp*kKvB6P0y}sU51klgzy^rsSrx_2g-Ht46SjP{v41lktRVMj)r4R>VRIJFP({ zRF3;)@%*DMdArVenG=3OvqEx0)08KcGg1Hm9dIHHVbqK_B#rrr<+%|me@rGrkqk*` zxTyg~C6vSU#w+wRJ;FzUWKU&9IU&RaW50y zxb17l8hTgmm0r1+Yjt6boWjob!0MD!bcnQzt&yQA_+-XW6V)6`JCbHGqr3MY><<{y zt}kIryFO`0T=`~d^i8*Q^wsJys0%NuFY;7HtJk+p#UlD5MW$FO`L3(Yxa%$9`r|LH F{{zG71NQ&` literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py39.cpython-39.pyc b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/__pycache__/py39.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27858cfc1a327219c1daec32cd6c16f169d3b53e GIT binary patch literal 1183 zcmZ8hPjAyO6t@#M$+`~E7za4z1j>O9X%|2U0cB#-P?^Lgw5X7}wP~{@arEMXQjHUw z`2-w5;=)(*6$xoyffLW!R$y+P^Zfq%{a(sfR@wyD#?4=oJ|pC(J^Z^|JUl|G-ry!k zOav89Msp{2ayNE!7Bfnu16|C3hV@Vq42cwQFEFGtdG^C@M6`S^Ep`qSYX`xZa z1nP_jQqQ0mQycbdS?49B9#XZ1+dMcXhvXG`Nf^_MT{6C*P77(mCE8Z}}F*wyyJ97R#E)_By4wG{)DH0oHIP5lYp@r2()C9XAOAb;PX4QSe`uK|c_{v33bLp`@ z%_cVi6c_?_F3i#*gYhR)b2KtRj*Q@%M-BvN)L8x?u!{WegWmnYekGwA6jEm8;Hj*R zv?>St+xYCD(+F=k9z0J+gDTbXcFD&_d?KqsnwJW6mX4D1@ayAd7S_vp<6gI{&E-Wc zr?e{kQ&H~=R^P-`vwxKRqSwHF+KS_idCyDWNU8cnZ?AHOdrGS4MXJvSn tvt=3=XSV^vu#r+(6XrDOh4jILT!~pGAKEXk>fpxMn!}t`Cvev~e*jKTDQ*A& literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py311.py b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py311.py new file mode 100644 index 00000000..3a532743 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py311.py @@ -0,0 +1,22 @@ +import os +import pathlib +import sys +import types + + +def wrap(path): # pragma: no cover + """ + Workaround for https://github.com/python/cpython/issues/84538 + to add backward compatibility for walk_up=True. + An example affected package is dask-labextension, which uses + jupyter-packaging to install JupyterLab javascript files outside + of site-packages. + """ + + def relative_to(root, *, walk_up=False): + return pathlib.Path(os.path.relpath(path, root)) + + return types.SimpleNamespace(relative_to=relative_to) + + +relative_fix = wrap if sys.version_info < (3, 12) else lambda x: x diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py39.py b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py39.py new file mode 100644 index 00000000..1f15bd97 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/compat/py39.py @@ -0,0 +1,36 @@ +""" +Compatibility layer with Python 3.8/3.9 +""" + +from typing import TYPE_CHECKING, Any, Optional + +if TYPE_CHECKING: # pragma: no cover + # Prevent circular imports on runtime. + from .. import Distribution, EntryPoint +else: + Distribution = EntryPoint = Any + + +def normalized_name(dist: Distribution) -> Optional[str]: + """ + Honor name normalization for distributions that don't provide ``_normalized_name``. + """ + try: + return dist._normalized_name + except AttributeError: + from .. import Prepared # -> delay to prevent circular imports. + + return Prepared.normalize(getattr(dist, "name", None) or dist.metadata['Name']) + + +def ep_matches(ep: EntryPoint, **params) -> bool: + """ + Workaround for ``EntryPoint`` objects without the ``matches`` method. + """ + try: + return ep.matches(**params) + except AttributeError: + from .. import EntryPoint # -> delay to prevent circular imports. + + # Reconstruct the EntryPoint object to make sure it is compatible. + return EntryPoint(ep.name, ep.value, ep.group).matches(**params) diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/diagnose.py b/UIKatabatic/Lib/site-packages/importlib_metadata/diagnose.py new file mode 100644 index 00000000..e405471a --- /dev/null +++ b/UIKatabatic/Lib/site-packages/importlib_metadata/diagnose.py @@ -0,0 +1,21 @@ +import sys + +from . import Distribution + + +def inspect(path): + print("Inspecting", path) + dists = list(Distribution.discover(path=[path])) + if not dists: + return + print("Found", len(dists), "packages:", end=' ') + print(', '.join(dist.name for dist in dists)) + + +def run(): + for path in sys.path: + inspect(path) + + +if __name__ == '__main__': + run() diff --git a/UIKatabatic/Lib/site-packages/importlib_metadata/py.typed b/UIKatabatic/Lib/site-packages/importlib_metadata/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..7b190ca6 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2011 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA new file mode 100644 index 00000000..ddf54648 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: itsdangerous +Version: 2.2.0 +Summary: Safely pass data to untrusted environments and back. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/itsdangerous/ + +# ItsDangerous + +... so better sign this + +Various helpers to pass data to untrusted environments and to get it +back safe and sound. Data is cryptographically signed to ensure that a +token has not been tampered with. + +It's possible to customize how data is serialized. Data is compressed as +needed. A timestamp can be added and verified automatically while +loading a token. + + +## A Simple Example + +Here's how you could generate a token for transmitting a user's id and +name between web requests. + +```python +from itsdangerous import URLSafeSerializer +auth_s = URLSafeSerializer("secret key", "auth") +token = auth_s.dumps({"id": 5, "name": "itsdangerous"}) + +print(token) +# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg + +data = auth_s.loads(token) +print(data["name"]) +# itsdangerous +``` + + +## Donate + +The Pallets organization develops and supports ItsDangerous and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +[please donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD new file mode 100644 index 00000000..fcb4cb94 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD @@ -0,0 +1,22 @@ +itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475 +itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924 +itsdangerous-2.2.0.dist-info/RECORD,, +itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427 +itsdangerous/__pycache__/__init__.cpython-39.pyc,, +itsdangerous/__pycache__/_json.cpython-39.pyc,, +itsdangerous/__pycache__/encoding.cpython-39.pyc,, +itsdangerous/__pycache__/exc.cpython-39.pyc,, +itsdangerous/__pycache__/serializer.cpython-39.pyc,, +itsdangerous/__pycache__/signer.cpython-39.pyc,, +itsdangerous/__pycache__/timed.cpython-39.pyc,, +itsdangerous/__pycache__/url_safe.cpython-39.pyc,, +itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473 +itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409 +itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201 +itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601 +itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647 +itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083 +itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL new file mode 100644 index 00000000..3b5e64b5 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__init__.py b/UIKatabatic/Lib/site-packages/itsdangerous/__init__.py new file mode 100644 index 00000000..ea55256e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/__init__.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import typing as t + +from .encoding import base64_decode as base64_decode +from .encoding import base64_encode as base64_encode +from .encoding import want_bytes as want_bytes +from .exc import BadData as BadData +from .exc import BadHeader as BadHeader +from .exc import BadPayload as BadPayload +from .exc import BadSignature as BadSignature +from .exc import BadTimeSignature as BadTimeSignature +from .exc import SignatureExpired as SignatureExpired +from .serializer import Serializer as Serializer +from .signer import HMACAlgorithm as HMACAlgorithm +from .signer import NoneAlgorithm as NoneAlgorithm +from .signer import Signer as Signer +from .timed import TimedSerializer as TimedSerializer +from .timed import TimestampSigner as TimestampSigner +from .url_safe import URLSafeSerializer as URLSafeSerializer +from .url_safe import URLSafeTimedSerializer as URLSafeTimedSerializer + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " ItsDangerous 2.3. Use feature detection or" + " 'importlib.metadata.version(\"itsdangerous\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("itsdangerous") + + raise AttributeError(name) diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb2775dc946a7bf30903e3897d87c20c0ba54cfd GIT binary patch literal 1443 zcmai!&u`l{6vsu$mSkIU94B>ttOudnn)xsfYl|L=VQ7{VXt6FR<^}@@0|IR_E*t6x zNII#5^s?=`)2=(L$NfvX4j7R8PTOUVtQ|PpVUqFmd0$db?~#utaolv^`uy%6)1T{( z^Sg0YFAto@j)T;n0MwyKI2pnS8Fqz>J?hb#sAY9r2hF2(U?2OIec%8GmID!H4cxFC z0ylBfas#-9Tb7%^5soakfMXn6j)2>^Z8;WeSqFD4x5awa#a+v5z#DkOatC-5Z(3d# zx3V7YS?&UF;VsJ>VmsTxJC-+rckwRpE!v}7zqoXp?)+H8A5eGb^mnh!dh}7%B6(hD zqIr?4qbu}YjK@T=hYwQ9CIw|MYbmgNAvDiPuG8^cGX=xJSA-rCO#mB!PZ^<1g3|=& z1(}P2Q1Bw~hJ2b6J(DJA2mF^jV>h&G=gFIrOJ?3{4w>Xc@CzF=e)`S+!M>OllIvF) z497=B&Q=BA#ISSMOn7?Zbt@@NvhsS?`ti5VhvbCanAcl~|B6s~O3RD79_;7yzFXCD zlCjE{3`)u;X7!erX)$O$=fJetV}MI&vr|_-pe}WU^A_1Bdh1@guU+bCXgFH`$wSU1 zdR_aqPW^Xi=xG1a`2l^8r~_LT9969}J!4YAUZtrtU%Pns@)b+=R^+{eXf648rdh&O zLRl%O1$i6% z-yHcNJpOud@Mr|(N;S$E6XocTsZ(8)qvL1r`x@#S!^xP8p7ZfYam_w0p#(BzYP4Fw zXKBiFuG4f-&dnB0VQnCZG~I?zs7){q3eD}-kn6d~{o4;BSAGn7|8~_()03Gw5wN9Z zsVZO3OQ^d-x(e-i14q_iM4En*zM12(Hxn5cH#DYUjQPuxEn^}uu-@0FM#dmuU)f_J z+h)p|F&!hZta;b z=%JOk@JZ|y35j3mi5Ul>fLJ^0*_YjU@6D{(-5oF-PwxMieFMh6(_(vgxHw=8%m@R? zB+S_YQUHqioTpy*_0!-rlb-ainDj4s+LQcM>#>VQhG4aJ|X_diaYP1?67O&&!5|LG4M=z>n z!d<@+%XuxN>uF_MT@_fVKZ9bb(wHnzF)h1+HM<3r1QR?RDoLRCz9D%4DTAQdBdA*39FM zVAL#iA9Iof!*ODKwYOc6Q76E8Xfg4eS5MDe@BBjOnbFjOzf942(s@Xx9$>JB8*IMh zw;VPx_Jv{#XMD|0phWZwd?wSu#6_wytyZ}(MOnUb1EU(Dg{`$o_#HgFgMCzhsFmtO zv~#O_NZ|t6E*jjShq%%aO;n`Kv_sJzPWSLu3+e`>}2_doqSmvup~q1#z3ls&CwSH+HMi@p=mX`o(Hox5I#;ByXp9tTZ0@*>+w qi4wql+SyDxnOWH$ zXjU5}NMHE{Ez;(Zf5LC@D-u$kdFu;3$CE&cK;TX6b3FF(`Mz_Bn#~%4asBFV!|zLk z{EEu?;eqlIAyoYW0wP+k6)Ex^VUyPYKM;r-aY_JncDD~q6Y_(jk!@ynnuadwY%ubd#pE;aQi zO*0+oI7`*$2`x6uw<3N!($Vu$u6I`6H=fcm9_Vo$R)6C6542Fm0mYQ8+;t6ArXtco z#^ZEoJRxN!mGPv|xl9KRK6W}#cHw^mIlTyiCKICR5tE$>nX(C;uw!-zd*CJA>^i0v zt2k9UN(Vxg;XGK!cSP5bRZt~{Pu5}jnaCMfo`1ISL2pY5sd}jp$*6Z*s7E>*^|tQ7 z-zNa84{!&)yK%p#Vl7ri(cn=u6si|%#iMj6WR|OU&cLjW4ovOaDAl2biVrEw3F6df zgUMNtx~yO*9m)o%17z`Rpp1|$+$9hY?h!o%$N-ic)2YMhF$J(}{PnF!iS;$Vz~@Ik z(w+|eY^R{y&!n%#W4-F%-xa+_0n;QyWy%EG~w{;RV=I7*FC>s9c2g zCHM?BFhCamE(i#pQ_i^aqk~cAuBJ#xo$ykJERgreAsII`n>t9&1IPlGXjhkZ*g>C? zL#VrPM|<2mq7(W9dqBP-ynIN%qbXDmuGh#l*a12#<4;fN$S3g#k zG|O$lpD9IZ5XZ)ghiN87m;IG`avq?aAPwV7chYa7B<6lW(@H@T_cn^g$mx zE8z`^i8y9AKOeuUS2v<0iTa6n_|RhAe%sgi2-G;$+uO#01@hZT^Zoxw?iScAl6y+e zQhL+o92Q731Vf?DiYhW*a+YGR!L`4GX`DZM9S$hWBSPg>n88@tdaC6=djws)$TuVy zJwkstbd@8@on`DR?&e7azRA~dvONzSv_{cIc-@rbUamBhz?*mm`^vczXq-R#E_^%l z?=6raM(BaWCed9swJ_Ytp$m#Il!(HHy@(>V)qJ3hrw>NhHmNp_cs#I?ws~Uf$%f4| zZSIAM&>A|M@pwFhb|sPYpdFr;WR#3{qrL!(_pIf>vcA3+o<8JatCMfQ9pern1?TeA zZgtTyBv&GWb8sziTlSR?_cNX+;wJK?uE5k_6>5L1;gUZ()pn)bT4FWo(U#M8UjPJ4 B%ZUI0 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-39.pyc b/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b29513535e08e9e2eced8febffe38eb16b3267de GIT binary patch literal 3325 zcmbVOTaVjB6!zH8b+fynrO=j}L4Xw028zl{RH4#~pnxJo+m|Skch)nzYwFlx#%a6J zzMxj>58$;A^l@MKL4HL-;x7~)_|Di)yu0a2Fp4L0W<1Ap&i9>jhOe);Ewn2i|GE21 z$Flw)q1s#s*DZ_brx*xJu*jOQ5o0vABYWiF--+CbJ93%zwIy6pduoZAtUYl?b;xzm zfZULE$PLI%(SqEP4aiN%ZLtPD8QuMuhd!hF5OZOypXxaAAb`s_BDDvdvKu(PbSm&vCC)Kxjyem~Q)1Ht!VJvmO zZMO9L-b1N0%;iEzF&KEC^{;$kmNG}D>X2oPiPW0!%D^@T=N*lm{9*bH3{vZf^&2~2 zF972KJFt9PSa+>MHtacBP0yxMWli4?<1qDo)xd_How-^@J4V1~TD~7dTx;Jyv|fI9 zb1=TIaj+JmtXy98r(MREyHoPvM9D zbYBq}H}Gf!8SAilxA1$vJQ0wtE1Awz95B3DHX74&lW?wMaA5ret5g$1MRJd+H5!xp zyxYVmYxq8V=lf?MXyZ0E-&}svto0h?keE-T?`Lh_pCn=y(YWLLKhJnntU#4W0{D!q zP_L2p^}ZnztBcumefS`wIhx}5ezBDIHr@+LeD_WDCb-+S3f`(J_C2i`D= zWzRMY$Qo0=A0=D_M60qD6eFswpqX9L%mC7JR15oZM_s@O69yb|grW&$9Ax}uyhJXg z`H~oo`MIi56?O~{>x#fsXQ_Lgx^vVSP>B93QFs#zv}p7L1zXX~t1-BQ)gu_Ratx3? z9D@R7kSYr8jF@~6>1m0?b`=TAT$d?7hzcl_IpT*r3M+X8pv|^T{F&HC?im?7H2ZRKUa zK!SIc5K`$FAo&^aj`PaonX8^(ajDsFoTH3k*)Fk)K~Z9tkhIx686yhJsrOg?j$Y zY$H+OZW!~(mr5lnC=#%7AB`z89P;G57_5ql0~fJ@8&Xk*faEgkdDx@gN7t(z50J&u zswnvuTTH328XIoiou63%vJ4Pscv^(eX>X7g%7}=NHX?*se=C|l!IuADblN!B4|$#7 zR}pGewiNZF!jpm;xHd&#k>Lg1u;|WIyj;c(6&^56NIk`M0{5;3)fQy9x%6C9*`+&uc1r;)-4*1i|4=9T|>TV-KB|D zl#`e*>#jRLyTogoOz?#o!J$fB&Z y2vc(-G9}rha+BE%VU4azAy_2Cta&ZJrhN(SStiAI>?Z3t-OcVs_k6eBz4$LmB<0Ki literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/serializer.cpython-39.pyc b/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/serializer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9b323e44f307bac955efde74b1027798f3b69d7 GIT binary patch literal 11352 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/signer.cpython-39.pyc b/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/signer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a106ad9f032f638dd6feed20761761accbb1054 GIT binary patch literal 8806 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-39.pyc b/UIKatabatic/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..748cbfa09d5a5b26ec0a6ecfbd6697d0b1935c54 GIT binary patch literal 6391 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/_json.py b/UIKatabatic/Lib/site-packages/itsdangerous/_json.py new file mode 100644 index 00000000..fc23feaa --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/_json.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +import json as _json +import typing as t + + +class _CompactJSON: + """Wrapper around json module that strips whitespace.""" + + @staticmethod + def loads(payload: 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/UIKatabatic/Lib/site-packages/itsdangerous/encoding.py b/UIKatabatic/Lib/site-packages/itsdangerous/encoding.py new file mode 100644 index 00000000..f5ca80f9 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/encoding.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +import base64 +import string +import struct +import typing as t + +from .exc import BadData + + +def want_bytes( + s: str | bytes, encoding: str = "utf-8", errors: str = "strict" +) -> bytes: + if isinstance(s, str): + s = s.encode(encoding, errors) + + return s + + +def base64_encode(string: str | bytes) -> bytes: + """Base64 encode a string of bytes or text. The resulting bytes are + safe to use in URLs. + """ + string = want_bytes(string) + return base64.urlsafe_b64encode(string).rstrip(b"=") + + +def base64_decode(string: str | bytes) -> bytes: + """Base64 decode a URL-safe string of bytes or text. The result is + bytes. + """ + string = want_bytes(string, encoding="ascii", errors="ignore") + string += b"=" * (-len(string) % 4) + + try: + return base64.urlsafe_b64decode(string) + except (TypeError, ValueError) as e: + raise BadData("Invalid base64-encoded data") from e + + +# The alphabet used by base64.urlsafe_* +_base64_alphabet = f"{string.ascii_letters}{string.digits}-_=".encode("ascii") + +_int64_struct = struct.Struct(">Q") +_int_to_bytes = _int64_struct.pack +_bytes_to_int = t.cast("t.Callable[[bytes], tuple[int]]", _int64_struct.unpack) + + +def int_to_bytes(num: int) -> bytes: + return _int_to_bytes(num).lstrip(b"\x00") + + +def bytes_to_int(bytestr: bytes) -> int: + return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/exc.py b/UIKatabatic/Lib/site-packages/itsdangerous/exc.py new file mode 100644 index 00000000..a75adcd5 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/exc.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime + + +class BadData(Exception): + """Raised if bad data of any sort was encountered. This is the base + for all exceptions that ItsDangerous defines. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str): + super().__init__(message) + self.message = message + + def __str__(self) -> str: + return self.message + + +class BadSignature(BadData): + """Raised if a signature does not match.""" + + def __init__(self, message: str, payload: t.Any | None = None): + super().__init__(message) + + #: The payload that failed the signature test. In some + #: situations you might still want to inspect this, even if + #: you know it was tampered with. + #: + #: .. versionadded:: 0.14 + self.payload: t.Any | None = payload + + +class BadTimeSignature(BadSignature): + """Raised if a time-based signature is invalid. This is a subclass + of :class:`BadSignature`. + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + date_signed: datetime | None = None, + ): + super().__init__(message, payload) + + #: If the signature expired this exposes the date of when the + #: signature was created. This can be helpful in order to + #: tell the user how long a link has been gone stale. + #: + #: .. versionchanged:: 2.0 + #: The datetime value is timezone-aware rather than naive. + #: + #: .. versionadded:: 0.14 + self.date_signed = date_signed + + +class SignatureExpired(BadTimeSignature): + """Raised if a signature timestamp is older than ``max_age``. This + is a subclass of :exc:`BadTimeSignature`. + """ + + +class BadHeader(BadSignature): + """Raised if a signed header is invalid in some form. This only + happens for serializers that have a header that goes with the + signature. + + .. versionadded:: 0.24 + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + header: t.Any | None = None, + original_error: Exception | None = None, + ): + super().__init__(message, payload) + + #: If the header is actually available but just malformed it + #: might be stored here. + self.header: t.Any | None = header + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error + + +class BadPayload(BadData): + """Raised if a payload is invalid. This could happen if the payload + is loaded despite an invalid signature, or if there is a mismatch + between the serializer and deserializer. The original exception + that occurred during loading is stored on as :attr:`original_error`. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str, original_error: Exception | None = None): + super().__init__(message) + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/py.typed b/UIKatabatic/Lib/site-packages/itsdangerous/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/serializer.py b/UIKatabatic/Lib/site-packages/itsdangerous/serializer.py new file mode 100644 index 00000000..5ddf3871 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/serializer.py @@ -0,0 +1,406 @@ +from __future__ import annotations + +import collections.abc as cabc +import json +import typing as t + +from .encoding import want_bytes +from .exc import BadPayload +from .exc import BadSignature +from .signer import _make_keys_list +from .signer import Signer + +if t.TYPE_CHECKING: + import typing_extensions as te + + # This should be either be str or bytes. To avoid having to specify the + # bound type, it falls back to a union if structural matching fails. + _TSerialized = te.TypeVar( + "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] + ) +else: + # Still available at runtime on Python < 3.13, but without the default. + _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) + + +class _PDataSerializer(t.Protocol[_TSerialized]): + def loads(self, payload: _TSerialized, /) -> t.Any: ... + # A signature with additional arguments is not handled correctly by type + # checkers right now, so an overload is used below for serializers that + # don't match this strict protocol. + def dumps(self, obj: t.Any, /) -> _TSerialized: ... + + +# Use TypeIs once it's available in typing_extensions or 3.13. +def is_text_serializer( + serializer: _PDataSerializer[t.Any], +) -> te.TypeGuard[_PDataSerializer[str]]: + """Checks whether a serializer generates text or binary.""" + return isinstance(serializer.dumps({}), str) + + +class Serializer(t.Generic[_TSerialized]): + """A serializer wraps a :class:`~itsdangerous.signer.Signer` to + enable serializing and securely signing data other than bytes. It + can unsign to verify that the data hasn't been changed. + + The serializer provides :meth:`dumps` and :meth:`loads`, similar to + :mod:`json`, and by default uses :mod:`json` internally to serialize + the data to bytes. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param serializer: An object that provides ``dumps`` and ``loads`` + methods for serializing data to a string. Defaults to + :attr:`default_serializer`, which defaults to :mod:`json`. + :param serializer_kwargs: Keyword arguments to pass when calling + ``serializer.dumps``. + :param signer: A ``Signer`` class to instantiate when signing data. + Defaults to :attr:`default_signer`, which defaults to + :class:`~itsdangerous.signer.Signer`. + :param signer_kwargs: Keyword arguments to pass when instantiating + the ``Signer`` class. + :param fallback_signers: List of signer parameters to try when + unsigning with the default signer fails. Each item can be a dict + of ``signer_kwargs``, a ``Signer`` class, or a tuple of + ``(signer, signer_kwargs)``. Defaults to + :attr:`default_fallback_signers`. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 2.0 + Removed the default SHA-512 fallback signer from + ``default_fallback_signers``. + + .. versionchanged:: 1.1 + Added support for ``fallback_signers`` and configured a default + SHA-512 fallback. This fallback is for users who used the yanked + 1.0.0 release which defaulted to SHA-512. + + .. versionchanged:: 0.14 + The ``signer`` and ``signer_kwargs`` parameters were added to + the constructor. + """ + + #: The default serialization module to use to serialize data to a + #: string internally. The default is :mod:`json`, but can be changed + #: to any object that provides ``dumps`` and ``loads`` methods. + default_serializer: _PDataSerializer[t.Any] = json + + #: The default ``Signer`` class to instantiate when signing data. + #: The default is :class:`itsdangerous.signer.Signer`. + default_signer: type[Signer] = Signer + + #: The default fallback signers to try when unsigning fails. + default_fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = [] + + # Serializer[str] if no data serializer is provided, or if it returns str. + @t.overload + def __init__( + self: Serializer[str], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: None | _PDataSerializer[str] = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer positional argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer keyword argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a positional argument. If the strict signature of + # _PDataSerializer doesn't match, fall back to a union, requiring the user + # to specify the type. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a keyword argument. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: t.Any | None = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + + if salt is not None: + salt = want_bytes(salt) + # if salt is None then the signer's default is used + + self.salt = salt + + if serializer is None: + serializer = self.default_serializer + + self.serializer: _PDataSerializer[_TSerialized] = serializer + self.is_text_serializer: bool = is_text_serializer(serializer) + + if signer is None: + signer = self.default_signer + + self.signer: type[Signer] = signer + self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} + + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers) + + self.fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = fallback_signers + self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def load_payload( + self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None + ) -> t.Any: + """Loads the encoded object. This function raises + :class:`.BadPayload` if the payload is not valid. The + ``serializer`` parameter can be used to override the serializer + stored on the class. The encoded ``payload`` should always be + bytes. + """ + if serializer is None: + use_serializer = self.serializer + is_text = self.is_text_serializer + else: + use_serializer = serializer + is_text = is_text_serializer(serializer) + + try: + if is_text: + return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] + + return use_serializer.loads(payload) # type: ignore[arg-type] + except Exception as e: + raise BadPayload( + "Could not load the payload because an exception" + " occurred on unserializing the data.", + original_error=e, + ) from e + + def dump_payload(self, obj: t.Any) -> bytes: + """Dumps the encoded object. The return value is always bytes. + If the internal serializer returns text, the value will be + encoded as UTF-8. + """ + return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) + + def make_signer(self, salt: str | bytes | None = None) -> Signer: + """Creates a new instance of the signer to be used. The default + implementation uses the :class:`.Signer` base class. + """ + if salt is None: + salt = self.salt + + return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) + + def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: + """Iterates over all signers to be tried for unsigning. Starts + with the configured signer, then constructs each signer + specified in ``fallback_signers``. + """ + if salt is None: + salt = self.salt + + yield self.make_signer(salt) + + for fallback in self.fallback_signers: + if isinstance(fallback, dict): + kwargs = fallback + fallback = self.signer + elif isinstance(fallback, tuple): + fallback, kwargs = fallback + else: + kwargs = self.signer_kwargs + + for secret_key in self.secret_keys: + yield fallback(secret_key, salt=salt, **kwargs) + + def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: + """Returns a signed string serialized with the internal + serializer. The return value can be either a byte or unicode + string depending on the format of the internal serializer. + """ + payload = want_bytes(self.dump_payload(obj)) + rv = self.make_signer(salt).sign(payload) + + if self.is_text_serializer: + return rv.decode("utf-8") # type: ignore[return-value] + + return rv # type: ignore[return-value] + + def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: + """Like :meth:`dumps` but dumps into a file. The file handle has + to be compatible with what the internal serializer expects. + """ + f.write(self.dumps(obj, salt)) + + def loads( + self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any + ) -> t.Any: + """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the + signature validation fails. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + return self.load_payload(signer.unsign(s)) + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: + """Like :meth:`loads` but loads from a file.""" + return self.loads(f.read(), salt) + + def loads_unsafe( + self, s: str | bytes, salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads` but without verifying the signature. This + is potentially very dangerous to use depending on how your + serializer works. The return value is ``(signature_valid, + payload)`` instead of just the payload. The first item will be a + boolean that indicates if the signature is valid. This function + never fails. + + Use it for debugging only and if you know that your serializer + module is not exploitable (for example, do not use it with a + pickle serializer). + + .. versionadded:: 0.15 + """ + return self._loads_unsafe_impl(s, salt) + + def _loads_unsafe_impl( + self, + s: str | bytes, + salt: str | bytes | None, + load_kwargs: dict[str, t.Any] | None = None, + load_payload_kwargs: dict[str, t.Any] | None = None, + ) -> tuple[bool, t.Any]: + """Low level helper function to implement :meth:`loads_unsafe` + in serializer subclasses. + """ + if load_kwargs is None: + load_kwargs = {} + + try: + return True, self.loads(s, salt=salt, **load_kwargs) + except BadSignature as e: + if e.payload is None: + return False, None + + if load_payload_kwargs is None: + load_payload_kwargs = {} + + try: + return ( + False, + self.load_payload(e.payload, **load_payload_kwargs), + ) + except BadPayload: + return False, None + + def load_unsafe( + self, f: t.IO[t.Any], salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads_unsafe` but loads from a file. + + .. versionadded:: 0.15 + """ + return self.loads_unsafe(f.read(), salt=salt) diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/signer.py b/UIKatabatic/Lib/site-packages/itsdangerous/signer.py new file mode 100644 index 00000000..e324dc03 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/signer.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +import collections.abc as cabc +import hashlib +import hmac +import typing as t + +from .encoding import _base64_alphabet +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import want_bytes +from .exc import BadSignature + + +class SigningAlgorithm: + """Subclasses must implement :meth:`get_signature` to provide + signature generation functionality. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + """Returns the signature for the given key and value.""" + raise NotImplementedError() + + def verify_signature(self, key: bytes, value: bytes, sig: bytes) -> bool: + """Verifies the given signature matches the expected + signature. + """ + return hmac.compare_digest(sig, self.get_signature(key, value)) + + +class NoneAlgorithm(SigningAlgorithm): + """Provides an algorithm that does not perform any signing and + returns an empty signature. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + return b"" + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class HMACAlgorithm(SigningAlgorithm): + """Provides signature generation using HMACs.""" + + #: The digest method to use with the MAC algorithm. This defaults to + #: SHA1, but can be changed to any other function in the hashlib + #: module. + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + def __init__(self, digest_method: t.Any = None): + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + def get_signature(self, key: bytes, value: bytes) -> bytes: + mac = hmac.new(key, msg=value, digestmod=self.digest_method) + return mac.digest() + + +def _make_keys_list( + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], +) -> list[bytes]: + if isinstance(secret_key, (str, bytes)): + return [want_bytes(secret_key)] + + return [want_bytes(s) for s in secret_key] # pyright: ignore + + +class Signer: + """A signer securely signs bytes, then unsigns them to verify that + the value hasn't been changed. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param sep: Separator between the signature and value. + :param key_derivation: How to derive the signing key from the secret + key and salt. Possible values are ``concat``, ``django-concat``, + or ``hmac``. Defaults to :attr:`default_key_derivation`, which + defaults to ``django-concat``. + :param digest_method: Hash function to use when generating the HMAC + signature. Defaults to :attr:`default_digest_method`, which + defaults to :func:`hashlib.sha1`. Note that the security of the + hash alone doesn't apply when used intermediately in HMAC. + :param algorithm: A :class:`SigningAlgorithm` instance to use + instead of building a default :class:`HMACAlgorithm` with the + ``digest_method``. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 0.18 + ``algorithm`` was added as an argument to the class constructor. + + .. versionchanged:: 0.14 + ``key_derivation`` and ``digest_method`` were added as arguments + to the class constructor. + """ + + #: The default digest method to use for the signer. The default is + #: :func:`hashlib.sha1`, but can be changed to any :mod:`hashlib` or + #: compatible object. Note that the security of the hash alone + #: doesn't apply when used intermediately in HMAC. + #: + #: .. versionadded:: 0.14 + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + #: The default scheme to use to derive the signing key from the + #: secret key and salt. The default is ``django-concat``. Possible + #: values are ``concat``, ``django-concat``, and ``hmac``. + #: + #: .. versionadded:: 0.14 + default_key_derivation: str = "django-concat" + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous.Signer", + sep: str | bytes = b".", + key_derivation: str | None = None, + digest_method: t.Any | None = None, + algorithm: SigningAlgorithm | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + self.sep: bytes = want_bytes(sep) + + if self.sep in _base64_alphabet: + raise ValueError( + "The given separator cannot be used because it may be" + " contained in the signature itself. ASCII letters," + " digits, and '-_=' must not be used." + ) + + if salt is not None: + salt = want_bytes(salt) + else: + salt = b"itsdangerous.Signer" + + self.salt = salt + + if key_derivation is None: + key_derivation = self.default_key_derivation + + self.key_derivation: str = key_derivation + + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + if algorithm is None: + algorithm = HMACAlgorithm(self.digest_method) + + self.algorithm: SigningAlgorithm = algorithm + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def derive_key(self, secret_key: str | bytes | None = None) -> bytes: + """This method is called to derive the key. The default key + derivation choices can be overridden here. Key derivation is not + intended to be used as a security method to make a complex key + out of a short password. Instead you should use large random + secret keys. + + :param secret_key: A specific secret key to derive from. + Defaults to the last item in :attr:`secret_keys`. + + .. versionchanged:: 2.0 + Added the ``secret_key`` parameter. + """ + if secret_key is None: + secret_key = self.secret_keys[-1] + else: + secret_key = want_bytes(secret_key) + + if self.key_derivation == "concat": + return t.cast(bytes, self.digest_method(self.salt + secret_key).digest()) + elif self.key_derivation == "django-concat": + return t.cast( + bytes, self.digest_method(self.salt + b"signer" + secret_key).digest() + ) + elif self.key_derivation == "hmac": + mac = hmac.new(secret_key, digestmod=self.digest_method) + mac.update(self.salt) + return mac.digest() + elif self.key_derivation == "none": + return secret_key + else: + raise TypeError("Unknown key derivation method") + + def get_signature(self, value: str | bytes) -> bytes: + """Returns the signature for the given value.""" + value = want_bytes(value) + key = self.derive_key() + sig = self.algorithm.get_signature(key, value) + return base64_encode(sig) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string.""" + value = want_bytes(value) + return value + self.sep + self.get_signature(value) + + def verify_signature(self, value: str | bytes, sig: str | bytes) -> bool: + """Verifies the signature for the given value.""" + try: + sig = base64_decode(sig) + except Exception: + return False + + value = want_bytes(value) + + for secret_key in reversed(self.secret_keys): + key = self.derive_key(secret_key) + + if self.algorithm.verify_signature(key, value, sig): + return True + + return False + + def unsign(self, signed_value: str | bytes) -> bytes: + """Unsigns the given string.""" + signed_value = want_bytes(signed_value) + + if self.sep not in signed_value: + raise BadSignature(f"No {self.sep!r} found in value") + + value, sig = signed_value.rsplit(self.sep, 1) + + if self.verify_signature(value, sig): + return value + + raise BadSignature(f"Signature {sig!r} does not match", payload=value) + + def validate(self, signed_value: str | bytes) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid. + """ + try: + self.unsign(signed_value) + return True + except BadSignature: + return False diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/timed.py b/UIKatabatic/Lib/site-packages/itsdangerous/timed.py new file mode 100644 index 00000000..73843755 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/timed.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import collections.abc as cabc +import time +import typing as t +from datetime import datetime +from datetime import timezone + +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import bytes_to_int +from .encoding import int_to_bytes +from .encoding import want_bytes +from .exc import BadSignature +from .exc import BadTimeSignature +from .exc import SignatureExpired +from .serializer import _TSerialized +from .serializer import Serializer +from .signer import Signer + + +class TimestampSigner(Signer): + """Works like the regular :class:`.Signer` but also records the time + of the signing and can be used to expire signatures. The + :meth:`unsign` method can raise :exc:`.SignatureExpired` if the + unsigning failed because the signature is expired. + """ + + def get_timestamp(self) -> int: + """Returns the current timestamp. The function must return an + integer. + """ + return int(time.time()) + + def timestamp_to_datetime(self, ts: int) -> datetime: + """Convert the timestamp from :meth:`get_timestamp` into an + aware :class`datetime.datetime` in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + return datetime.fromtimestamp(ts, tz=timezone.utc) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string and also attaches time information.""" + value = want_bytes(value) + timestamp = base64_encode(int_to_bytes(self.get_timestamp())) + sep = want_bytes(self.sep) + value = value + sep + timestamp + return value + sep + self.get_signature(value) + + # Ignore overlapping signatures check, return_timestamp is the only + # parameter that affects the return type. + + @t.overload + def unsign( # type: ignore[overload-overlap] + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[False] = False, + ) -> bytes: ... + + @t.overload + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[True] = True, + ) -> tuple[bytes, datetime]: ... + + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + ) -> tuple[bytes, datetime] | bytes: + """Works like the regular :meth:`.Signer.unsign` but can also + validate the time. See the base docstring of the class for + the general behavior. If ``return_timestamp`` is ``True`` the + timestamp of the signature will be returned as an aware + :class:`datetime.datetime` object in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + try: + result = super().unsign(signed_value) + sig_error = None + except BadSignature as e: + sig_error = e + result = e.payload or b"" + + sep = want_bytes(self.sep) + + # If there is no timestamp in the result there is something + # seriously wrong. In case there was a signature error, we raise + # that one directly, otherwise we have a weird situation in + # which we shouldn't have come except someone uses a time-based + # serializer on non-timestamp data, so catch that. + if sep not in result: + if sig_error: + raise sig_error + + raise BadTimeSignature("timestamp missing", payload=result) + + value, ts_bytes = result.rsplit(sep, 1) + ts_int: int | None = None + ts_dt: datetime | None = None + + try: + ts_int = bytes_to_int(base64_decode(ts_bytes)) + except Exception: + pass + + # Signature is *not* okay. Raise a proper error now that we have + # split the value and the timestamp. + if sig_error is not None: + if ts_int is not None: + try: + ts_dt = self.timestamp_to_datetime(ts_int) + except (ValueError, OSError, OverflowError) as exc: + # Windows raises OSError + # 32-bit raises OverflowError + raise BadTimeSignature( + "Malformed timestamp", payload=value + ) from exc + + raise BadTimeSignature(str(sig_error), payload=value, date_signed=ts_dt) + + # Signature was okay but the timestamp is actually not there or + # malformed. Should not happen, but we handle it anyway. + if ts_int is None: + raise BadTimeSignature("Malformed timestamp", payload=value) + + # Check timestamp is not older than max_age + if max_age is not None: + age = self.get_timestamp() - ts_int + + if age > max_age: + raise SignatureExpired( + f"Signature age {age} > {max_age} seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if age < 0: + raise SignatureExpired( + f"Signature age {age} < 0 seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if return_timestamp: + return value, self.timestamp_to_datetime(ts_int) + + return value + + def validate(self, signed_value: str | bytes, max_age: int | None = None) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid.""" + try: + self.unsign(signed_value, max_age=max_age) + return True + except BadSignature: + return False + + +class TimedSerializer(Serializer[_TSerialized]): + """Uses :class:`TimestampSigner` instead of the default + :class:`.Signer`. + """ + + default_signer: type[TimestampSigner] = TimestampSigner + + def iter_unsigners( + self, salt: str | bytes | None = None + ) -> cabc.Iterator[TimestampSigner]: + return t.cast("cabc.Iterator[TimestampSigner]", super().iter_unsigners(salt)) + + # TODO: Signature is incompatible because parameters were added + # before salt. + + def loads( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + salt: str | bytes | None = None, + ) -> t.Any: + """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the + signature validation fails. If a ``max_age`` is provided it will + ensure the signature is not older than that time in seconds. In + case the signature is outdated, :exc:`.SignatureExpired` is + raised. All arguments are forwarded to the signer's + :meth:`~TimestampSigner.unsign` method. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + base64d, timestamp = signer.unsign( + s, max_age=max_age, return_timestamp=True + ) + payload = self.load_payload(base64d) + + if return_timestamp: + return payload, timestamp + + return payload + except SignatureExpired: + # The signature was unsigned successfully but was + # expired. Do not try the next signer. + raise + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def loads_unsafe( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + salt: str | bytes | None = None, + ) -> tuple[bool, t.Any]: + return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/UIKatabatic/Lib/site-packages/itsdangerous/url_safe.py b/UIKatabatic/Lib/site-packages/itsdangerous/url_safe.py new file mode 100644 index 00000000..56a07933 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/itsdangerous/url_safe.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import typing as t +import zlib + +from ._json import _CompactJSON +from .encoding import base64_decode +from .encoding import base64_encode +from .exc import BadPayload +from .serializer import _PDataSerializer +from .serializer import Serializer +from .timed import TimedSerializer + + +class URLSafeSerializerMixin(Serializer[str]): + """Mixed in with a regular serializer it will attempt to zlib + compress the string to make it shorter if necessary. It will also + base64 encode the string so that it can safely be placed in a URL. + """ + + default_serializer: _PDataSerializer[str] = _CompactJSON + + def load_payload( + self, + payload: bytes, + *args: t.Any, + serializer: t.Any | None = None, + **kwargs: t.Any, + ) -> t.Any: + decompress = False + + if payload.startswith(b"."): + payload = payload[1:] + decompress = True + + try: + json = base64_decode(payload) + except Exception as e: + raise BadPayload( + "Could not base64 decode the payload because of an exception", + original_error=e, + ) from e + + if decompress: + try: + json = zlib.decompress(json) + except Exception as e: + raise BadPayload( + "Could not zlib decompress the payload before decoding the payload", + original_error=e, + ) from e + + return super().load_payload(json, *args, **kwargs) + + def dump_payload(self, obj: t.Any) -> bytes: + json = super().dump_payload(obj) + is_compressed = False + compressed = zlib.compress(json) + + if len(compressed) < (len(json) - 1): + json = compressed + is_compressed = True + + base64d = base64_encode(json) + + if is_compressed: + base64d = b"." + base64d + + return base64d + + +class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]): + """Works like :class:`.Serializer` but dumps and loads into a URL + safe string consisting of the upper and lowercase character of the + alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ + + +class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]): + """Works like :class:`.TimedSerializer` but dumps and loads into a + URL safe string consisting of the upper and lowercase character of + the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA new file mode 100644 index 00000000..ffef2ff3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA @@ -0,0 +1,84 @@ +Metadata-Version: 2.4 +Name: Jinja2 +Version: 3.1.6 +Summary: A very fast and expressive template engine. +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Typing :: Typed +License-File: LICENSE.txt +Requires-Dist: MarkupSafe>=2.0 +Requires-Dist: Babel>=2.7 ; extra == "i18n" +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/jinja/ +Provides-Extra: i18n + +# Jinja + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +## In A Nutshell + +```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 + +## Contributing + +See our [detailed contributing documentation][contrib] for many ways to +contribute, including reporting issues, requesting features, asking or answering +questions, and making PRs. + +[contrib]: https://palletsprojects.com/contributing/ + diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD new file mode 100644 index 00000000..4dc97f4b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD @@ -0,0 +1,57 @@ +jinja2-3.1.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2-3.1.6.dist-info/METADATA,sha256=aMVUj7Z8QTKhOJjZsx7FDGvqKr3ZFdkh8hQ1XDpkmcg,2871 +jinja2-3.1.6.dist-info/RECORD,, +jinja2-3.1.6.dist-info/WHEEL,sha256=_2ozNFCLWc93bK4WKHCO-eDUENDlo-dgc9cU3qokYO4,82 +jinja2-3.1.6.dist-info/entry_points.txt,sha256=OL85gYU1eD8cuPlikifFngXpeBjaxl6rIJ8KkC_3r-I,58 +jinja2-3.1.6.dist-info/licenses/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +jinja2/__init__.py,sha256=xxepO9i7DHsqkQrgBEduLtfoz2QCuT6_gbL4XSN1hbU,1928 +jinja2/__pycache__/__init__.cpython-39.pyc,, +jinja2/__pycache__/_identifier.cpython-39.pyc,, +jinja2/__pycache__/async_utils.cpython-39.pyc,, +jinja2/__pycache__/bccache.cpython-39.pyc,, +jinja2/__pycache__/compiler.cpython-39.pyc,, +jinja2/__pycache__/constants.cpython-39.pyc,, +jinja2/__pycache__/debug.cpython-39.pyc,, +jinja2/__pycache__/defaults.cpython-39.pyc,, +jinja2/__pycache__/environment.cpython-39.pyc,, +jinja2/__pycache__/exceptions.cpython-39.pyc,, +jinja2/__pycache__/ext.cpython-39.pyc,, +jinja2/__pycache__/filters.cpython-39.pyc,, +jinja2/__pycache__/idtracking.cpython-39.pyc,, +jinja2/__pycache__/lexer.cpython-39.pyc,, +jinja2/__pycache__/loaders.cpython-39.pyc,, +jinja2/__pycache__/meta.cpython-39.pyc,, +jinja2/__pycache__/nativetypes.cpython-39.pyc,, +jinja2/__pycache__/nodes.cpython-39.pyc,, +jinja2/__pycache__/optimizer.cpython-39.pyc,, +jinja2/__pycache__/parser.cpython-39.pyc,, +jinja2/__pycache__/runtime.cpython-39.pyc,, +jinja2/__pycache__/sandbox.cpython-39.pyc,, +jinja2/__pycache__/tests.cpython-39.pyc,, +jinja2/__pycache__/utils.cpython-39.pyc,, +jinja2/__pycache__/visitor.cpython-39.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=vK-PdsuorOMnWSnEkT3iUJRIkTnYgO2T6MnGxDgHI5o,2834 +jinja2/bccache.py,sha256=gh0qs9rulnXo0PhX5jTJy2UHzI8wFnQ63o_vw7nhzRg,14061 +jinja2/compiler.py,sha256=9RpCQl5X88BHllJiPsHPh295Hh0uApvwFJNQuutULeM,74131 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=CnHqCDHd-BVGvti_8ZsTolnXNhA3ECsY-6n_2pwU8Hw,6297 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=9nhrP7Ch-NbGX00wvyr4yy-uhNHq2OCc60ggGrni_fk,61513 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=5PF5eHfh8mXAIxXHHRB2xXbXohi8pE3nHSOxa66uS7E,31875 +jinja2/filters.py,sha256=PQ_Egd9n9jSgtnGQYyF4K5j2nYwhUIulhPnyimkdr-k,55212 +jinja2/idtracking.py,sha256=-ll5lIp73pML3ErUYiIJj7tdmWxcH_IlDv3yA_hiZYo,10555 +jinja2/lexer.py,sha256=LYiYio6br-Tep9nPcupWXsPEtjluw3p1mU-lNBVRUfk,29786 +jinja2/loaders.py,sha256=wIrnxjvcbqh5VwW28NSkfotiDq8qNCxIOSFbGUiSLB4,24055 +jinja2/meta.py,sha256=OTDPkaFvU2Hgvx-6akz7154F8BIWaRmvJcBFvwopHww,4397 +jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 +jinja2/nodes.py,sha256=m1Duzcr6qhZI8JQ6VyJgUNinjAf5bQzijSmDnMsvUx8,34579 +jinja2/optimizer.py,sha256=rJnCRlQ7pZsEEmMhsQDgC_pKyDHxP5TPS6zVPGsgcu8,1651 +jinja2/parser.py,sha256=lLOFy3sEmHc5IaEHRiH1sQVnId2moUQzhyeJZTtdY30,40383 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=gDk-GvdriJXqgsGbHgrcKTP0Yp6zPXzhzrIpCFH3jAU,34249 +jinja2/sandbox.py,sha256=Mw2aitlY2I8la7FYhcX2YG9BtUYcLnD0Gh3d29cDWrY,15009 +jinja2/tests.py,sha256=VLsBhVFnWg-PxSBz1MhRnNWgP1ovXk3neO1FLQMeC9Q,5926 +jinja2/utils.py,sha256=rRp3o9e7ZKS4fyrWRbELyLcpuGVTFcnooaOa1qx_FIk,24129 +jinja2/visitor.py,sha256=EcnL1PIwf_4RVCOMxsRNuR8AXHbS1qfAdMOE2ngKJz4,3557 diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL new file mode 100644 index 00000000..23d2d7e9 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.11.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt new file mode 100644 index 00000000..abc3eae3 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2=jinja2.ext:babel_extract[i18n] + diff --git a/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/UIKatabatic/Lib/site-packages/jinja2/__init__.py b/UIKatabatic/Lib/site-packages/jinja2/__init__.py new file mode 100644 index 00000000..1a423a3e --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/__init__.py @@ -0,0 +1,38 @@ +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" + +from .bccache import BytecodeCache as BytecodeCache +from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache +from .environment import Environment as Environment +from .environment import Template as Template +from .exceptions import TemplateAssertionError as TemplateAssertionError +from .exceptions import TemplateError as TemplateError +from .exceptions import TemplateNotFound as TemplateNotFound +from .exceptions import TemplateRuntimeError as TemplateRuntimeError +from .exceptions import TemplatesNotFound as TemplatesNotFound +from .exceptions import TemplateSyntaxError as TemplateSyntaxError +from .exceptions import UndefinedError as UndefinedError +from .loaders import BaseLoader as BaseLoader +from .loaders import ChoiceLoader as ChoiceLoader +from .loaders import DictLoader as DictLoader +from .loaders import FileSystemLoader as FileSystemLoader +from .loaders import FunctionLoader as FunctionLoader +from .loaders import ModuleLoader as ModuleLoader +from .loaders import PackageLoader as PackageLoader +from .loaders import PrefixLoader as PrefixLoader +from .runtime import ChainableUndefined as ChainableUndefined +from .runtime import DebugUndefined as DebugUndefined +from .runtime import make_logging_undefined as make_logging_undefined +from .runtime import StrictUndefined as StrictUndefined +from .runtime import Undefined as Undefined +from .utils import clear_caches as clear_caches +from .utils import is_undefined as is_undefined +from .utils import pass_context as pass_context +from .utils import pass_environment as pass_environment +from .utils import pass_eval_context as pass_eval_context +from .utils import select_autoescape as select_autoescape + +__version__ = "3.1.6" diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/__init__.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39bf790d81590e6f78c4c951e20b80d093d71b45 GIT binary patch literal 1593 zcmbu9%WmT~6ozHTj%``KJ9h3-lDQy@anTOYMNt&fNhZKdlR?llKtUJ~XoOqEC;1%m2Ji;iuv`Exkb>o6Tue5}rsYlG5-C|O#pR?zDwfN@ zE^#eafUBfx*#-89XSoVoBQ?t&aGlgG*MJ+OVYwbRlNM=NZUDDQ+j0}QLpqjQz+KX{ z+y>qvTb4V(J<_w>1@4o+t?^SOA9%!Ilq;lo@#FQCujj(h znQtc4_0V8|Eng@b9An_cH!gYo;)% zH%du`OJ_Zq(aenZ(p<`^h#;t&dEZZk;R(xPTbZxdf;*XcYd0&4t>1}={RA5oWsdur zYIY@Q#4r)>d?IK_`xuBz%Ewh7E>KAM@9j`mRgx<3tmSd=yaR8h0_#_b9xHSqAT@S9TH@q-rR0Z~p zX?#qs|1;i8sn$U#g<&%T{Y~3ms}k^9kKO}~*8*Fb#Vj-dof^q>NK^K)_;T?1;LG=C z&lja2h-4T9q%;cc(hAQcwSiIqSyb0nP(`#i(RSG^WVUFvf|JcrWt0jE9(k&Y;-S<) z7Nyv}J+10!HBg!;EtED&2c?U$1wu;dv4B($tv<>&$_~md$f7tkJl1LtjeV2@ltYvw z6dz vL(L6)kv`Uk9)7?R;)~CMfD3MdV35ui<*yT4P2b>0s$YQ=ieB!2{PO<*4_3Pt literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecfc9e027d2ade4139279fe8d1da39a67e736ee3 GIT binary patch literal 2068 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 XFcNFeeQteWRTqC_@mBM9jpqLXP1qAi literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/compiler.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/compiler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef486a34b354e1aa229a3fde136c0bcbdf5ce650 GIT binary patch literal 54863 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/constants.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/constants.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6ac9820a6988579650f53439e281d9b64ebcff9 GIT binary patch literal 1529 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 F{{T?FY$X5y literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/defaults.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/defaults.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe6614fa5d6d462b2e39da47cd0ab04c1a56edf1 GIT binary patch literal 1329 zcmY*ZTW{Mo6qaOLzQ^}8X}d04mIVej58Gabp%~^mN~^|kJX_v{^Ps6F>Zeif)%WK3R1C#Q=aChP+C<0r@f4?qiljRUe3>>e1dhr1yo3I7H|<26PyEFLM2rp z>Y_}4PrUA+3eKY{E}$ANqB<_21}>u}-a##_qFqovAba}?*~gWq5CwX;#Z-Z*p-0dk z<2w2PH$c@)xF_U8azF|sPl}|3TW@vr5#GfQunKJt`aa%uRb0al-{#QA;PH^`f&JuC zOLlrBcN#10$2V|#WpJZ{ZL1=CYW6K-GzOTljIkww-doK)LIE}BBp}q`#P&i;eA|uK z(wB;tp$iLu@&m^wEOKTf*4`Y&+R-(PZ({9Qj)$>!cr99eb70tGt7{qO#=x?NBjeQk zSu_&5cX7T&o(i=PKjEa)cRB3q{dznNjz2p%p3=>D{F|r_jGt~@8b3^oLC$A|0T*yGj zVKdjY8K-e!Nj*0v9ZI~oyvE$2bHd~1dP@G})Uny@4+0s9E1WKa8Kkb`5%Stu#f=3E zgAQK$5wkC0iMwGC*S5&3*Wi!ERq)eszx*cXaO(O#!J>L%oOUOD$lOKW?3u>6eI#_g zirio>R4%fYt_Rs-GzBL?m5q3Pu_D6>knjx4YvDXrde#^7Ybw0`W4%An)YWr)U0<{eYjj5nYMZE8E0KHZhj{6c@8pAJFTfPEl6u!PUCpJ^>V2!L^<-93(-}>@ PYwz{q9R^lcwRisk6nAv0 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/environment.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/environment.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..978334a16ebc481815f7e2f87e60512e129953e1 GIT binary patch literal 53173 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 b1$V6?Up1W8+{qVOFSK57Ra<_`ZTbHLWJwDn literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/ext.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/ext.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b96f4594253cbe8ea794ca316540d011beb7efa0 GIT binary patch literal 25686 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

;K?H6l*SYs3`i=vAFoNRU>Lo+;X~lRGpF>G5 zq(&h=&@NZicH|sI+VA4g$g!|RG=ZGtAaWx0cON-Xidx2(5e8V(2Vfxj=G$>&z(5|f zd#s>5q}>Dg91;ccQ;5WnA6!V8ouQu@82nCiRKQPgM?d12kAVL?BE8fA_!&2Q)>c$d zG}%n8r$cm{20GF}N4l5pr34+xIgO50RHpSuoM^J2sP;Gn{VTiSD$I$o=_52aad9;-!lKn+uLOL;jFgB)qq}P}^_>=x2!TS!V zVPsOELBTPv8n9KS#FStP!f2~3z*c$G$+(#nm=&PxPdZts>vK*X>h-+y&_MbSRQv^J z80kaKF{H!X0F(c)7^daT9d?T_?MEq6pL`$Y!kjO8G-{x==o@}zMLB4{_%=)u&M4X$ zaWZ({g?8!WV3kMRT}uYO8$(OuD-&VMyWL@_aS}OuTo^s11Y6MQd+;uCN50@!p(%bh zMmp*2K}&m`z4F!g%0B$vkJ@2u5aY)_v`&`@t9-ych}K#AeNyu* zMxosE{54pG!x~HZAO!$Hzx+5lE218Z;*HiKB$yyA5OpA=g-r#+Q49hBq|34RHSQP; z&vDQ2Vb}{rz5R0Qc_aBSJibPI(kMd>|T*Nr~G@3YAU*d&T`gJw!~&ffgG%;DM6!1ai!E zOL9;aIVp)F7jaG#3Z@nWA?_(tZ>GX&lAbGPJ0UX4xlSZ`Xj?65CM5UU_%o1TiQ59V zkpt$~brubGgcyT2>YI75*0>q;F+%UB*wNTn3&#Sto~bT$LG=fEa^SX>b$ot1Oe?rPkiDzXgCt1Ph9N;jxf`be+!ZO#T>;vp2yQR1Fob}?4P)cis zh}0^Le34mk{oB#hL$1w{aZjDVh9GO^&1`ZkiA{QPGO4MM2L(~)} z&Gy0{<9uXUEFuDwB|3&01*O0?zd~&yHn-{%WIYh@3~X^t{DnX$<(`V=@RYoN!pDXR z`CI~EO;`rpcyR$3Z$eotPE{ti-u*7d04in0s-teA8?v*M9f=6XB6O)WW;}%;0(HNV zt*G1%YU1b&LCp^mSqS+0A4SRNx!XPYV*)v5G$1yD;(Lfq60M~02vmt)$9OjJ`UIdR z(A)sgaS{}$uLFuu6MPv(KxAphl0gQ^cB_p9v2L-6AbHJQ+dit#BV(SUk~N4Cb*DaL z1TkBr(eq=hcUQ#LBgc%86mbO6k8wUS8XFOE72g0EoWyv{jU0kwGJ}CXHi2i8p#GrsjBY0@6Os(aQAAgQm9%4BOTwY})m~P8R%*yNDQzu9ZCNM1X{hE~#`RajybNm3_wo?u zvNsZH1F1PD%lEIEPVQ?-#7sXA_K~E$HEdxBMD^QIZ<)R^vg7bU z{C(Es6i~B{4PP_YbJx!{_xgp6VaY3QnuA|*r9#R$>lb@Neqm+gwu!M^U}@|QP*xNs zVLM124Rb~}&E61l(@m>4gfeV(7uw2PKO2tIA`Aeh0$?`m@4B5>FG4jl2Ki=e)4XD? zkF1aOM$p!;_KF+hy%B+!^o42C+Y!1(g?-R*X+c9}W5Su(G~P1RXPq(BA7XLuIIh7_h2wy_3FFwcUKnVdW7);AH1mV0&n8~C z*T;Hez&TrQ$oR%MHsEmVOyVu`dZRb|mg)T*AOkS^`p;_5;5oBN?rY`T8xspfRpmC^xt5|H+Y zjdm8Tmot2?)R%&kI2pmMRGZx38nV`gN3wehK4^Y9<6Wz_S`f!M~t zs*dpkcw{YsHAfGHuOKQ0gdlxRfTJjU!QEDWB;Xg8iH2M#<4A#F;%GJMwYuvCqX1NW zwE|Zo{}PdeSukOIf-I0u^|ybc*m@L_*nnUg!fhe9BIdj4 zOc8Gru)845+>39D$dUZJX^XY6F3U(KN3o5e&1Dp|ur7&7En!V5=29Pw(9FZp74@2F z`3mpI;rDn@U!B>#7g5@CM3fNuzV>}jDL~b{= z{*ODOO}h7(b9W3I>n;iBC$1`0kHr&Kt-irv8^itur2P>AY$5^=sp${y>h_rkfq>I2 z7{MHA-3-x>C3|o8xk_RgmSP^QsdyldPlqjskcGz zu4A(neqn*bez~8+^bO(T;QlFSr;|O+(^01bl_$K*GG7aQqNHS&^mCxT+%@vi(XBN~ z-%@DlUq}6F!iktlREHe?_aG&lY)<2?fVV&End*<30uGRMhJ~k$A+LzMA4!_#namyS zrO~5Zx<_Fza%le{DL1D32B~8Fw(&&+`AL6>+Vmx&dZK$uQ}zx#DjM2_0<_B(Qo^$+ zLIFYdm+Lp&rgp;&EPBq~F^=9bj~*=-Bhpw|beHQPtv8QObZ1AhW3qv%}GeNw8_{TI(_LZhE)gNTcEyhTHMO+!iKcREuAW5 zva(vQdedIGV=Q#{!(`cjCnmfh`dT5~o9^zq)+sjNQ^A8UHk4pEic`>x6%KqLX$W+jWpUeF~{Kt5v#LA{cNy9LvH*Gy4yqYe3> zSa;K)X#8toGYk54Hx2qIl+NrP{}5s@z`n38+>h4vF_j~X)foIk1i=Vq6KPt+64XCp zmJm29QKMfG5x&ph@g^}Ky$@T@_R`*oUKWqB0V)AW--LOXQlc5ZgHEjHe0n{Kxf`-N z)Il9XE%frBA}Pti%BMUAN|1wpDI{#jYb^8AP9{#tZ=|IxXihJ+q$y8wBZIUoWc4g0 zzx*-}LDH-;guO!mdX?KuKvFyosj{#>+{>un=;2@i*86W<|3+_UCBHF*uM3dmhBYO- z{*C5Iqzpq6H&BO#6`#jDCHdsWh#XI#X;f;xjnQDV%o*(sE#nPqztDa3IeG-cd510} z+Vv-N6~aDEh=KUX!$a`~yl|aq_0IuP_0Je^Zyl<(zQlLY=KO8OD1U7+ZzYjHs!dr% z4ED>w$m{ztPG}bBZ;A){20#iJ`J3i-3wugVP4EQrsj_vcT3118hCWD8p_$Vs)!#t6 ztdDJMD9E3o^A?29_Sso*BH1jb⋙wnGczQu^iObiS?^0?HbTk{3_dK$J93w1Ziw~ zak5Tznerlof57AvWUN(Bd&&F?Q?DQ>Pw)iaiL^h+JT z-SJCBEqcA*Qc%CfDrNfLW@|Za=tV9HqjXnNwBNrksMObyJ3<(pK_oGh#d4;g5{X6- zcp&UhMA;7^X%vEyY3xl?K;iO+z+QfAeryx5YdZq>0%kK3K#mUf< z2OEYUHQ#|7pQ6S=y~d!-fC8fkIzi?Vw1Kb%sb65y27`aY;4=(UONI7duDLL( zR0ihdPqGL-EK~=>bU3 z*dmSOb^5OPqr%XU?m>`exB#6pkxG#ire$K~|417(RKMlN75EGukAS(?Ug_YN95orR z!s(Nhneb%gF1jvV_E-Jc$W^eb&e7CWwHKTgoNpl?L{={CZ^<(v9^Ck@MNY`zd0?p^ zG292(D{xR2uReV$r0+2cH!L19fp=o)Gbh@o*dB_HHYnQ;)XO=@?~~#DMd=F^N8!UMJlB+ zE%@b}dBsFeL}`UhL*Ae(?lurkOTBYobkr3N9GUAc0HH3w%Uqd;{bnR4ZT${%=c2YS zGpw|!m{!BH!V(=N2uF`Xz0QaDrJLgRPe_^>q+!G z(x%XW6H54p>F|X&$o6l7o8b-UjowOdNci{oPJ1(E22e|(N+UjXp8b}MEyzjO^DQ|3 z$1K|ievIPs@&0?r{mcN~VMkC* zy9e)F7SG`Eo1lBtendpn z)2HpL{%Yf4@mB3S5TAiwFMeB$vGy92;?D{|@$3m#!v(Fr>E_!f= zK1M4P|KezQ?J6ViA*{o$kA1Pc(eqpi)Nm%xXOeSlpvu8sv&Z(aj>1tFdS|mNUc!p# zml{{Wmz%2EW|3Q~@EJfKULUCSm|#r0`M}dGbVdS+J}u!{CY+UMWISO?sO8(ahq`|) z2LrH=c>qyWAmD}UT2i5hXf88`lb`xF0(rq^2|ZkorvQ#xQf~&A4A;RVdTjdCsp*q4 zzk-y^*!LkiB)WWrmvGUD8UP0QO)(Kbbhco!gegA#|q!MskY|2 zdCr5=(j0u0p}~SmDk4V0V%|mrTB*i1%cCSfn42$0n;Y#SOz{Fn%t;nLAAfNKF?aV$BGkeUNQmF{N3`3+wfuK4eONp3_p;v}@7(KcjqL!7k>hKV&rB7Lg&ywBhlNQyvlFmJ$6Yl-LfK|A@3V2pI9p zgx;-a6rtVgPHqEDh^)EN2as(7M~i;XGR7LU9Lh!p8t${}KS0KEgch*tiL^PER!p6T zYjzSQF)@P$LyOf#w*f~=xXj$E`y$U_+ciAidkCQ22U>Vq4?D;2!>s{6A8^)$WeWB> z==@hKa7E*Wp-x=q2?Tggu4GX13HXXYr-gD^lv`kYCFkcE$BuD`Z=yANl5bo9&~816 zZwvUg2#r-gRUvhlb_4Zy`l(1OO4=_Cq?z7t`6HYfZ(vvYEG7`_#+hEm`|kBZ^N>GE zjTCHY(0al4mV#v?)6DuK;`K@Aid}d(mdsM}RmjNK3u2c@SAP?t7I+gKk8E*+hN~9O zZc%C3#6>DJIEq-Q^;fY#LLD&l zFBM5V+}sSC6hZ?D56d6K8Im$i^kPTAznHuvuJJ)9tw+-GE|0r;_QD)ATlyq=czjtj zOrCw7vw~8U9MHybC72{`lHF351u>=pr5JnS+w~<$VmgE-(=JEn{UK%DG#=-@- zd$|h&EPe7>&Rg?%5k?Xr4+WvR>jMblLR^amUbTV4*&aTC;YS}hrp}HMy9ex^<3v>d-6)Wtw6>} zV^14O6wRnY2SPb_O#nBl&?Cr9jo=ubnmT*-te(YMK#2~-&u+W(fW>gs*nZj`$eGed zsF=qIk4zNN#DD78=RRjoRi+LvwOWTuC+x};g2)+6r=GA6FILsz6ZR92l}h&d`mug( zRI*HgU5UeAWYnKx8zo)nGgGI)s4Ha9Xy6#?juWOz(Oc9UN=->Iltznq8*?&(5U`G>a47NyAxz%p*1z+DC*K9|Bv4+g2jTHS5vt?Hkh4= z7nqip!W)Q6l#e+lPhic$niV4UID}~Z9r97J9AE6LE@CEyN4=QK`w8?4VSd=1o1hia zCEX5diip-gU07~WO$!U*lt*?{k_tb^o&v!@%`$8p%@eYTMJ-3UiCq*C8tS5Bl&I`W zYp{qyAx~V32rr)=hp@S@5DvKC2VLI@IbNw@z#i#T4nf7e(RUf37F$~!;n&cJIe~_ARI-@YI%YgM7 z(lv<)=R)`zd-jt2MQ42VH4(Uwgws&!3M*o-pww^`?!}M;rcnb?<)osp1K=>Ed^T5u zsyhBr9;1xp@u3#K(z+`fPZRG(34?ZC&5mBz|AD&KS{nrZc?C_BX@Es92}J;lbL&wPE8ud>^I zfU#d;@JR;GGoXn9q99jAki@1$L}92z{wp)zWboe@u;L&S&KHPDYFT`ogCrQ>wjrvY zMcJRFh(*`m#KWUz;VzC`yk}Y_{>#IVQG}_MW>)Um@egL!F`8~^?&U6;-&3&K@}so% z3?6R@!Qd_$*XE?~KyQM5b5{GhOIj9QE0A*Dh6wDyjkFApb)@HArl+yH&Nx}54h^LC zFB2-rC2@tISeeli@B#qts_u6_fh)&A7xY$D!~oH@=t)XD70hNl<<6yrv*4JvGq7)w znab26-l9pYm)%wlh=quwt`4XBOHhu=x(R2g{+?2lP@^YEsWj;k-YPwig)G^puy`Tt z&^8w8@${+cju$EdaOFxk+o8!%OP^uJ3frpi9QnOcFP8!EsyAi_5rO9!F3EtWAv_j& z&j;@JU3aW9j`l+Z#u)#qW%kkJ#^wtEKys&}KnR$<0*H_$i!}xJ~K(vsbWz zTBm#Pc$0jTsX`KAM3+h{UvhLcM(Jy0S*Co>N&T{1r1Rm z4>t!8;M+lo%OXI#L(F>b5|RZJOTeIO8Hb@Im^8WvcY;~;NojaTHKu4Vzr_ZBivh8t zx58XL+LR*w{sCWQKim&Qq55aY_~WQM*coRI@`Q7Ca#S$~m%veT;I^czKF7oHj(@3%n>;Is*p(94C331^vM!o`w1MEAxG6Ivbo^`@>*I&l2t zX81PF++2sZf6v0!`GTZcxc%)uABu86<7cQO$KR|E2hX>0762rjr{mICx;WH@;};n} zC+!XS`4u=yO1yx0A&d_r4l}N#7ZIl`Ap19h_(&KZMVyY7Oovlp`?v9qZ7|;8($W4y zyul#^Esi5Lemg1g3B)IEClT(J_uYt1;(d>7uP0&N+4JTI4dM81uQ+=?v{h^#1G-QpYNO8)DMA7 z9RiuM-!j&|q6rlo4h`>TzLr?NC2L!F~G9F5lpWJf4+<2h3t@&ZF1?#YUEq*#GSu5(+)pQ)7mB^n z^c8m5@B0a1x8XY)CI^kW`RgO0-gu)*wO=PXjFm&&!Ki!n{SeUDdZ4i69Ye5VmZcDR{6YVf`2&_XJw0kFJW+ zWU!Omna3Lqc+6mTqCW(zQC{Nu3Z=d|UV?*N z#22MRHF9fm#13T)Bi!UpKdN zFW4VF86l)nhaO(-6Sf+%6*kCQ$Y@HyDg^kk@ay^xt`Ol+9YwctX|2a;E%f5k@ER%T zrEK2)h`sR^9RXp6Wv6c_J`t^BFV++cTs9=oo9a^_%Gbo*Y8zK-hJMA3HQj!Y2N?-( z$qW*Aj1zMgaQNm&V1wcY5@bR>=gu-V<(|uAne^?UW|`+cc>V`06HJm)smRx7$!mk; z8a#@PQ}8s#(hAI069Rn_%SgC?kb)PdtDuyR8&{y>gA#yjOR4Lp+woILGz%dB@<{iP zR_KHTvA-t`i^41*t8TtLrd`?KT@c?!T^`kGu(yPl5tMgF)<+}^6daF}2g*)FGj2=K zu_$$*gLb@w&bZPS0fjxU#atp{t+ zI~X&_*W|WE4=biT#A`%goS@6Qc)zQ^3vkKtsQ|8&puMP|o9g&Wk33Z}E|iWaocK(r zzhI$%%7EgYxQEDf5<%ugxEbOTEv@|`Gt&%+-16A@7halqzH)i~+{^O_U%oi^TzOQd z&CWd=rR;w7+{+iwoqu6=Yr*k2d7$jX%u6r6I6KGM2I?G(QU^-ze&OPr)HpvYA6$BQ z_QJ(am&YYJDjy~ep=&Qzq+^%M!!NL>m!j9vx!F(Ys%HP%E3VcO!k#gnzsKN!9wP8atycT#_m9^(!QZ}^rM3PD%G z9G+3c?n>=KS4*?nLF>Pu4cxwnLk!r;ar$rrP|mN)&Ga5T+vL&|MdOrAC9NvrK?Ipz zq)@zq7F5-f0}leraz<%KR`Frg_Ou~3gy{@(yq>zlOc~oTy_JqnW6DTNz8fW0{zI$1`#Boxpdjn4Ig#bVOMuUQEq( zW;*3MQS6%Q&UDLl64yPM9=Yx)uA1x3^vZP#*Q+zD<+>BseVIO7cRAg~JLdW`{c_!d z>ou7*a=i-IYcp%*x);}XX6}^h)x~vlcV+I9>%QXpxw|uW%k>?_4RiNo?vd+$TyM;5 zlwAh1%{`oXI2w66;%s#8y%=%sbsv}=z7Wf7 zLyc+YKBU{7`;qRLvhI#J_S;rwr<=Hvb~as&W_HQd0Iqhs_~&eX$8sKU9=sUOJn|XN z&=!>Y5I&E(kGYSt{N03;cedlRV>-&T>HZGM(el*U`cA?bbcQY_G9O00)@{}s);7ZS z?v6-L9(pJ4JnRgk&X3^kawwU%0d8j-`j&RKqi=hh9qwxB>rQ7Ee(yCo6SMo!PtzlO ze-xi5!aHa;hTc6UC3icIpyYn{KJ+K%dKKtBV?r!$Yy<5`6>{9}Pxr^E3{Oof+iZTb?*zD8J6G)$N z_G3;D2_$hq(%g$@(efxp>VWf=Qn$fNBi0`+{=>Gx36ZFG?kyEzXO`$-FJ|;v993VPwXg;{weQ$=_k} zFVFpw^D^pw#d%e7zv%Y6FJ6eEg%nC;+Sad2oN!J`iKDF9In_4j$D9d3l67+E>oI|& zb455lCU8tTd8u_=a(CS%x8t~y`#9k3=IR0zyPavw#f($HSiK}O)*~}UOykPY7}SKf zn7>(!!D*)`wY`incv;3^m6Rmjykbggj5X`y26fFjC8_IGK-P zjbo3Y9^Uc4ITE<$h&rEoC*{25T#_E=(f%DWGLN#?vdW03k2&9iG5%iX(}2K{+3g37 z;>h5c)T~$a_rKHOe8%|!smqmoYl3`!`>gG6Am0x;KP>sC1pXfZ{L`#a=)jLUKZc&o z0GhSZ-^bC?b*ObI3b~ymvX*(B98GzuKC zt;gDWTzV~7X>$FN^UKnoGRohL^{vbQ3d;X&=T}jF9``qJR-OL=Fn8FTmVJO4niei1XH_nUv{{2$0y#cw?$|EKeh@cT74K3fa!{a?;M zmQqW+ixys#7QPzX)qN+1@76n^8I6WJQsVz+iOdpLCvpG>B;Vb(=IsXr48*C|HibgwGKl2FP;Bap#8)$Xm4Csd-(qqY9sugz&w8(^L%5N z!d@Br?66n=I)I4u@kP_`9nMSg^xrtYFYta6EqszK2(C-doIj8p|JM2cB*z;Jber0-)dX_ zKRACXIW7q;zhCw+_D}OotDXM{to$?QKgs&KEF=5`$H=+ga75oDcq|x<`ypqjar!@_ z^q)I_0lfd-+bs)9zr4P00EfQmTt|JMHnVjb(141)Ij$3eFbx+~>qI31m)jtxcYvD{=HU%k_AC0D7a2@hWd-bv(Va)lBuI;K^5VSaKEmr2*l z=jPpOxOzUPPA|;kUdk&^RZvX53wR>9u`1^+mhuy4bE=RlRdAy#w@@ih(QHPzDn6e<`E8tMoy*B;B2oXPTe*J&t`=U6xX#qi?^e7p@v+z90E zNXBv@ZNEb~EC#HKJMm+Yp+vponVk2``16MWT2i@{1y#y(l>I+m^D~N%7f0emjzz9T z$F3o%$33?=r8eWPB-am(j+{L10W(gPT(>xX@__4|u9W9b9zTTt&*dt)NzVMq!-dI{ z9_DJ>d@g@FH|=^SXA7m-+^+2guhR32_0+@!=U`%DkPTZ%BGGD}fi>+v976|?vy_{2 zCnoA$6BBb~XQ9aJo(T+cu4tabfIMoe4`&Fm+QNJHBjH17CKZ+6_2|JgrX?|1UMM;B z=yUbxOG8#YfmvB_)h1+KHcAQHlu^157nMjYQi)!$)P{<6C02>oB3BYuBUiDgY8bzv zX!ZQTvf}!&bDo{E=gVGYUX}B%=ixSR#U7bjDCI}8bGg&*1Xm3f50E>Xwt)#}T~+aH zbg599_PT8RRmyg;e9l$*9BV8&ww_7PE@NRTyRta%q8V>n!AlP%>s^*D-F)OP+#NLAOOY6pI`j8(n6FkLDucY-bL#B(o+Bogb2_F3vt=D!CCW~IAf zRn$A#gTmxO#jSTYbhX}r6_;BmR`h@pyZk>6CO4RzARF>#fLJ z(YLI(VpDO!>7J!{jW`{ze(k6rGDkL_D;9H;MHdt*SHU2aPlIgD3%!~yoOMff0Gd6e z%5!#3#*=Fpq^&$T>*gyVg;T&SjOmmVZ|Gp!whxpsB{_xBFLL-Ce_C>RPHNbS6c5_; zQ1TF{$uuTuKF3)FnVrv7W~45ugCGMGzzj?&=)7K99$mBQaV(>`<@m_;!r@!P;d=tf zCF?-s)Rv{_rRWu4U@dypT8do4T3(2%cqIy4wScSfOOd6>nfRrc+~0F4R*PJSE(yk} z0aP*+1EqE=(j@0z-NBod+JmopobX?Zs}Vk+`mdgl9;pxW#%3m5Y#`MEHb0HuUN4eJ zG!^Z!`lCrJ6-`;y%`I4;-cu}N9=(0(uqpx1N1cewd)^TwL|mZ+ z>uS*}P;T63ax5ms60}a{(>uwL_1p`~Lo`k3^#=E)vOt=U_te0A3(wZ<|7HS); zm+a%d$JQ$@B zdw|zFhnemg7&brCg;L2?JJUP#ef@J+dIvJNmAqc0*Q3KtTLqUU5#$&VWG#|uEU;5O zOHobXe!w~d8Yaj&6je{+Iaaxq-XV*ul^A#JVb?If^ZRCz^Uv^!REGqS=Rj5q4Le7; zhQc!HBgo$b9EmwULN{K*g%g2S$iU9unN#ULrr2uw^Z+ROJKx^nrbgv97<|> zk|3G!>d```H<$)l-kBtyOcc~Uqioa_F8?>I0#Iy5ScFP zrUS)h^|lL`gx<+!negU|1z-W{RHI1h@xx>+mr^-EFEuE^DhT93T~7*Mim(MCkI>Kz5oDNGkC^%%A&YzZXo z_2~H)gjLVr_NVYshmcfZ1P#j*YkfW?^bC7U=Wz~Ef7oOOtVkt~} zS9Gl<_p5hS(#K1Ma_I!vonhNBl&6|Tp=nrIBZtz_+#G4RRRbq?C3Y3NWhGuoaF^te z4#ldYPnE#DzK)TGWUXRyV*NoW0SlhI;sybX&!)juT!27ICSOTi!6F8!#IFXdj-FnI_yuo z;L)>q>f?^LPOhxk*ageGk8CVED)$m#7_jg~>E_5YJ7ERF$>Q&48^l%$<;Q%_$GF4Z~J96~hm=lrKAOR$$B7P613G zGK0=2&WV9zgd6Cb-YrJ#1MCa7J83j+?>GFop5#ea-*-@#0t;DOL=J(4+CPDtUvB8S0SJ55_5mB%S1MNwP-&p& z_z`df3X+6pSCk9Zn7JT1NbLg;?m9SNyJr>(*k>Wu0$Y8)G;JT6vKPw>HY7a9@1$4E zc{8pzECLNA4ygp{0I+ApT;3f--2j7?vS(V#GZ3fKHi5u`%)xTvjEva3(vL~`>(MPu zNE!oPb`X>K(Zuf5Aoii?k_Ci>fa^rxwmuti_zSy_{`I-oOAuerfbfynjSodLNi2+s zGv4*+-Z8ZvRe`8zVs*M6J=?mFI`>SwCHMTi+V_iWRn|$gdOwy|fHV!X%FjELYM@gr zQ%@Z-sHE=Z&p0ta9hOVZEC{B^TD;Q=LQi93e*+o3J|vO;b>Nh{qFokgoArUpvFJu5 zAQ~wb(>9T>oUcc{daPV@>ami04(b-H93yLyP4)kH&5x{pg^L=j@!UlmY~{7cY{VPZ zWd8~zubOoMY(On`AzF)H#h_MV7;I99XK@wdl^VwttfRO$4vGQN2>Or$nUpIs!MJ8E ziLjQTcA3s}TmnmZUFpX%A6-&q~ zFJRXp4Z{KwWr}`8YV+D__P{ePq*D9kvMM?Q;i{CoT$xXo%g*GYJ1}G~ElJxf$G>g+ zZ1YSPZmu=QKQ%qmP-TwQIa|v!_!_o%wX0A+)u}EoO^&_$0sdrnql$t`JH2~p6-9^X zw0ao`s$~1?#1+`CN#4jaahSMFrkHFF67J#kE-WNd$=}9r(Tqj<$s8o38)B&sEGzZC z6-)i4mFTikmLfxqbtx5Z!gUiZB8R|*J&KPoZQK$sM6X1zYVFRwMoVMoG(qP^vB2$% zYLhgoCG7Qt+=8M-8rh6n8fF1E#dXgj|D0{Gv52MSkbcL21ezir5cLSERb-W0$BaNo z_TR%pABa*rAY#19Osq>71oBJ0j?XS=7Gj_RRn3Ly8_+mVANCZe^fRE(%rz9ty?|c& zB%q{sUnr98GByZV8_V`c5fMlya`qg!1F~8gL$lfQHF>BPnXGc?2)TdaQCc1iVlRT6 zc0TXUSL_0J;PaAOun{bVRt95Fw4wH{U9V+U_ChlO(NJZT2XL4uJWArQRuRZ5hX39`(adGZDMfJLSn(b?YbwRmdx3IZoo7VXd^f&mRNmMfIjlotENq zt9LxFajM=q4*jXv31rW1%W`w22wMGX6xD*qon4?UJ=mtz8QiOOoH*%i-?#S^waQb) z+_X0ibS$#_;RTE4pb5lT;iX#KBpI8>`JoILE#)MQw&$|Si)8ObI1>d zsmDoNN!1`NE+uQ0dcBrZuRDoa@~#MeM`k4G*hKLwiKUy&eJ&38$VUR>O7^j* zpFh0)6-Yo7T|_bGbH|gQe}aBo4l-U^4j{G|41DOJm#Ad-9(qXQG9pp}Sj(R63qIvI>UvO=iQ3&OlQ;@ZEu1Dj zEqE(1SnN^A3GD%?mwxOWFuj1dka8nred$LdDIr}bGMKd0Q+{5@=aso8s ziUIKg(}~T&Uq>=b*m3yV>_q-11$^^+wonqhU?xwqvLe&E*xI;pO##<@X*Z;)u+o;M zMKl9dO+OM$$aBONLBekntp(YG>SUc`p&0{8h)qU5YzAX@P%Z>R7MWO1MA!`~;+&6F zA3RhNq_t6zsDZg68YmP^g(G&=+Bd!WIgG*IhCKO zcZJKZo}`YVoyU>C(K3ku8OQ0^SaJt;^qavB?32B+RUOYATOnq&BQ!$?Hw`T&)# z3i7i9e?}@_aRoi@oA48+m~mG`D`26%;4CYuI>#{Tr};zp`GdUL93&JfME`n(gUt4l zmKBY^U)_i)kO67XWRP}=Sph6c7Fl6y<7iAwy3;UupobHp1jjNEJ*I4P!fZZklx7+Zy+fmtA!P^K*Z@qa}C10E2<+#X#(TiS`hFnzD;a7nu z0;rLcLA{9t zvKf`0Vson}#up$VYtvhj*#e|+Mza2PYzbl;Y@|?)Ix(Rs@!U2PIwmy5XhUc(()JNeK(>0mK|_y2 zHe{NbSn&4iKVP6$qh#Z|;CeMy(Ygj3x#lJzT!@u1h?oU9VhgMeL@uyE+y&`mJ*#Q_Z6r`>+$8`XbSWpW~ zfv|^;2mxRod=pIJX?K_$s1%fv<7Cn~Ct%FMe_-y1DH~A5BkZl_hh?u&E(9LziDuI% zPe}!E@1!1yN^YozxSf;57KxJTa8ye}G-MxX0t?qG5W&!2R9z@Z9RvUa#jR>;3c4!n zL=C`mI%J>1eBBo68JSyTZ;g3_LA84aWE_Tq;o~$5b~f!7m^5Fxuy+6oFetBEwyYZ? zFQl#<<$G1hFUa;PohIUm{g7L*w%t(+hq2-fk2*xEp}_44cmW7NQ##O~%4Tny!1pA~ z`CS|+bXz0MZT7vLY_}`D6OJswpcDJD*#K&&B0@=#`;6dob6>GEK^(E#gGz$p7#=qb zJ2+Q~4>MPY5>xG0t|eXAXzvHfnEHNH8Eg>H3v*X6P9U-`Utr_mhS12Iav$V|kjKY+ z7Kv;Ku%tC@2yy7~BGBx?mVW91XxieUaqFl-S9dn5>{{YVtkywoT`eg_PTSFH^nV0U zwWvdUG;;!lR{;iNqjMA8Cox)^$%XL_4c(ZK8*U%3*(bJ6mCIDtOy(57@XK5sESI0e zy;C*aUQL>BP~~zl!>Y7G1*bGdaLSwDCE*fo8WNk~k7X@tCK*V8z7*g%EB3w6T!y@Y zMeM2HM_H$+M$}xsuEb#C3ft1S7|2_8AhYvmCtPX;!JcE^q8gKZG*tyFV8lKsZs*3Q z)F@6&CxzXE`UR9lRBu5kgVyS8;0Q#q1NahruE#tVzBWL8*qTE|BtW@(QadiuL)$HB zHchyx&8$HZVT5|cj~*zl0r_+NBB!^AtGOSDB?t(fpi9AaNPF{v!pe(8o93-m&=wV)zXj7pbK?& zfecrq!;1EQpne2b)&5F)6eOE_=n3o!!!~%izz^u9Vf(mm?P=oc>TxozH)8C#j`*N!yzbo+E$eogaI++ zoDX$~m$0hG;mJ^`uQ~>ge3>`emv9`x?|X<{iqqAESU-vz;Xu?aIC>>yv8nIlla|@& zo`7j;0&W&_x$|EOP^u#ZeM1la_2FA6=ue^SGBn}b$#|0E7rID)1ENO)V-U^t1=LM% z$#a-k7uycj_nh`+^>K2-zkt#&C8teu)N{gqOPr(vKX@U3p= zgh)t))>45PX(14h#5k7q7;>r~##QT#B(Xm5>^dida$e*PbrtDt5B}=r!7sx4|J@z? z-1#y~CVCx-|<#N%@ zm9)oa3_1KiUh^}GkEnw+A%(9^KkRhtY7tKyZ1o|NTozejlOj&(J^*!s^^O&zm7Cg5 zAi0baxPe9&(iRx8JfAB-_6ch<<_F*MvVygwRrq|3)?vR)%``Pg3y^=4>^4nq#sm+2 z2^a|3RYhtMjcj?L0*hTUFxhNFCE!?%IV7kS^igUt^}@7;z9{KbHhUugXja2G`pP)X zQ^2ExlAu1pqU|7lOGf0P8`c6%qTn?|10*$wS-w)1O0bJd7nT`gP$Em^RQ8q!b?eq} zEICD5d=B>nuxVP`<&R~1wtJ_xn}dTnRDpV-R6fVUNugv|E=?7t7r>6OjS;bXjbvY! zIo_3SIFSZ7Oy8-2+)zu#Q3{ycj)R>y%R!<%DivqVu=>t|)Wx5c5kqB=$4a0&*#80v zmx5?O6V2#Tt!gZ=4M;ERK%)VwGQ6aSegZJi$|mbXIS^9L2;4)$?ghYVTdQWyKzjoV z5kwB*Q$CN?ss1LD%|Rmk77aS4YXhVQ!l>NS4?h9*1?2R-nWPdi6t$NhX!jsHB~;*x zxPT&>HvSD2sH|b1=WYpQ(giq2;#bUj1Y8EJ{#O!sPLDi`77=h57MyV`@5f;M7X_aa zgK|5?Yf2pOD@ZIQ$%inPnswrE>_3X~u=`U{1!w-FwYd6JrIU3pSx}=(D@#_*x&o<1 z+UN?}?eg0lO5`@9?}0JKN7R`Dj))jR8}pXO!YKtlFd;^ZtrkDc`q8Y9cJDK4AaK!> zZsi;p-w;8#XZnsjra`z?NgZZBh65ukZot`AlSgy3HE`t%gy36VmnQokXj~lB#z9XkN84_> z7gX4IHQfWqdyUGMt$aq6O#__{X-nwU+bqxrtF=+F&??T0H{ikXp>A+Cxp~c?inKEW zoLA!hp5@icNa}Hln(8_J=CTr-ly7uxUQii|3)(XT=M|juZO_*9_@WUzJ<7#uqt?jA zRJ1>qjIND$K~+pkY!?*9z0hdWX|OA%eja(2u~oMv`mhEOeZU+{^12!LR+2&m1wmXQ zi1Rt6`ab9W+x;M^Wl%z;1M(-p%R?z1PBEdxEM{N)$}NIe&Qt_ zG7)s#pAy>^amnZqqy^uju%3ht7{x#w1$ufV+Tn`^1;M_$83WUhWu>7( zR0F98Bx$Bx$h-BfL(q7f*Y2FMNV#A^sD7Q@Znt1bsB|5_7K~L)t1{GYv8?9$>d8s) zv}$oV#p2=(DAw2ULsMBWN>SD4&;rP_lu>vi#BdD;O>J?g48kd4wZrMa6__$L;&kE) zY?M0SbmOWAS7Xj9T=nAW6=yZB`fxSr+<~k9=@brcSk4-FIaHjrIPeFi@N`6d50xq6 z>UrnqKnt<(-~tME?{UrU)nafYU3V7@!Bj%kI#A*VanD*Csdd~FaqjwT+*w~sem3&C zm<46lvB;Sfo*s)hcZ1|?sD9(1xaTzpYGU!q*;{88=5nQNP^~%?1h#_G!uaIT6=|?Q z_nV!&?bAuI>nYBn$(G?|cE;Ao|Nq70$!3 zMXfQI6S!bJ4~3bo>gfWm)b6w7D8n)*E_Oh+11=H0GN|aQrjIBHVvCqg94Q6S^@Z!SeO&w3Q(f-3 zlMB=ENt#ZpbtvA}HJj^qUTXO_gqZE&D8+9ht*-yr;E9vx(hqMt_1doCrIEqyL$B=^ z-nBIJ0LE;R^>N_py-@Pc@x&K=ROg`jOqI%0WrlgEC*ccApQ%!3f{NGT*K_+6_lwG^l$h1HL;l z|A@}RyG~sEw^J8DTjviu3D}9^P6DU4K8CzWxNbmBliv!zJ5YAsNzq#yOWj`Ttfa1V z);i%C&Jt(g%iZ}|%jwjf;b+cPx_MX|t_ZB7>+Qr+7a;9XU#_gGbpgJvS{Ej$JGTRD z_NdtzagI|9W*7rV)z~HT*g#KnWn)(>o%T=H8?&=GJi&7(U!E>;#Y+}S<8)O85vV|I z0wx4I^KlOj&_%c!;fM#~j>z((DO(|65j??Q^VY}+W)nNW0;3Gj>c!YWPWfC3HBTxK zWvq4HhFpk@x)Rw9jDGlKa0O!K&SqySmHCnFaMPxHHh*}*uXE?lrS*OI`4ubW5&od+ zfqs9+Agp}=aE#YJ%x-H|17QaW=;E|J4}*f~n>`2tv`}_H%fyVz?_!yr&zi)5c$L7O zdagGlZ9pF=P8Cg6AlQ=l8`82L<~G9=3@-pYpD!**adNy3Riy2w2s@3a^j!ea6lVe0 zv5;Sn_6!;Zl@*3x(^Tr_8Y&;;LUeW51Wjb2h|>dPs(r#dO{1qD&FA;>cwghaY!*aQ zx^499qNN$JUr;zxE+^=SR^&a5f2E)skc@cKWN&L;sc=c5fgg$h<2#4FfG3W%5=ff> zffqR9I$fD*s>fg9Bldm=wn7YAHj6dB*S`<#Vj#h?9zo!y8Z>2SEU)j}yd>IbEQX&q zFVjSNM(m@(%F-i62awQ*mHmP0(hw>ccPbsICU6`$13|%tF0s@8);j4zYgs^0FZ+Pj zcLGne29pJ|S;WFg&*M}>9*#sO20$sXsMAd_4V>a)IVVaUQ!DF$f-z`c^7~MQhMP9- z->q&6O)X)t0xgZGKhY`IxyAaP)1L(&p(9}}P+?2xreM4q zh=x!Y5X$^%7w$el1kzfuaQlQi)aXE2YK{Z!N|L}ZicP+8vjUf$`&&R;OQI{p4Takj6B6DRo@?UcBIIcJ!Vfx)SP zfN{_Ou(KKf0fkVge~Bd1iJt3#ML0_!OoOWN;pQL_eF51QJrd;gyfmIhwx?i4rOs(x zv|s%H$$){?65Fa3HUHjArsQ0}@1w-KV$)6Nqo$&c`AOUbJBR~>r!}v_9R45q6nMzr^kKmGS5m$5F$`&=yo9jLXdSBIOq|5I14*A zkXZ0p>wF|5cXt^g(f}h;aQkblz>u@%9Zb|=Blg(B+$1(nC?@pb6gf@>x*={Ou*j56 zO#q~6_Ye@MwkT}{-UC;PIsazd?Dp zk%iRxNg~%Rj~wa4QRw`^0cygg2U)tx9ne2Nk3q|3&0XDlp&#{Vmv}|zfeOJNR*c~A zZhU(@C4yK>>*QobKQIXR#85USLW=z&6m!>*} zWCBY>WQurHj#B7+p+j>JLBc;^`Y=n9R0xf!cgaZ#nHG9a&qHOM=fhx)s(*{0^$r9w zU?w3E2+>Du)R26gxdTd}oBuF@;=M>e_0#aUhIqzvLiD{}3rc~w5j;cmK@U!2;N;LB zBj>vxAh{lce+)cEV%X6Ij(SpaNA=Frh+e}(AP6Y||6bmA&*hA^Bgv-BAIU~woccU| z=%cBspW=>VK{UYvh86;Phtmn~(Pw%5RDSXJX$=uPK8GhbA)as&czzhqleGlyLTkYj z8dMZgIJqlwI;yhtNe6MM@o-q=}$<*R^VM3SRNBka~Je(=C~oD3DuQ+Gp|9>zyzmh%IvXfhYPw+1V#EMpn5P`IMzja4|msKEJEsc6Q801xJBCVi^QjjP&wxZ zYJMGqA8r>JgZVjz(o<4Hm;rB8$FMyv2WOVMSDI3{QQ6L&D?!xMgIfe`Cybs4d6*RH zZ2$o+_l_G?FK|lLYwY8~~nr_J@RTCDQJ|41qs)Z3G#Wip-8h zG1Yi1IQDcAUaC+g=uKk`mI|}V)4HkZ8Xc;HlGgtq@Ful^&GKV$NrkTCczk0Q5ne>|$#nALd|*_kvwp4Pm}O2hSSpI z%zuhF$1{ub)T(H9u#u+oI$#G!@PlVoijm9KB`B$&LW1MbZ1i&cQv6B~l=ZFn6j(YZ z4(3f1Tbh9bvzEwR$FBS`+P8DQmx>WL^(Dt%$IqsS_KqinI<;MFmKQ2&KKqu=6qxT6X(}1@H7=^ z9pMoP1|VlhiK!fVps*o#hOHX5rBtw{K<#pQ1#cV8GPS8coTJA2jbg;J&HTwZ5t_3w z9)f&93oBO7j%jp&&O}Hm$5UJggllf>czY$l2=yT&*#;M&w3#@Z+00wY_2O)befzf$8dDVnp9I_6=XGqp~Hz*UN zl?j{_^6LF2(9r}GE>QPNT#;|0a`he(*t)X#s>cbX`Wh~;B~UJMQa~O{znZ8y8(Ng!j zsM$ZO5zsIVpa8=@Xo$$Mh9~;`CV!mZ_2E(EJ}|t|WD=}yck(~uz;P6B650_#-$ofdP1p({q2!Z<>CnrD`Uau*DSc8Jih>Tf5jogzRz4lg z*lw&$0)726f=zh^#)&v!dbbOgsFfxN9aZ_C@M;s1JhBFVyk3RRC_dgilBz8NIfeE0 zFfG9Hcfq3hmDizxy%L|Y7H74Q9Y%NtWy4cG*RJVtgmy!8%j8sS(J`iYaa#8s*I$L` zv;+G9D7uw<8}Rz305V>pV8sZ5hJaJVHzQp8tftSbZwBtQ`_sfHRtZi5CfdvGWC6q(re z+_1n0vsaO@rD<$MR5@#ty(xZK_OC^YHhc6ofy z=S;{12{`DV4!7<|S>M2kc)3t2Ko^f{5hG=r#z3RhHp~r}fStev?Ib0pK%$0PWb#!c z^;Ium9APOuCzfzy!*0N{&CDsu7G|dhIp*p)hTvWTX<qDReEO8N|vDjR%;SUFIf1z{YuKASYBRDkAB zmX13$MS}&2y7uJ;dyM;Jh7ggr}Zb7KQ5(-ba^d#475TRr7Bzf1Om z_TUY=!>q3@4co6RZ5l9bw978=fwMv6WFWYi4Mu6xc1ow5_we=%2A4>e)%12_{oL+V z9C-&sT0$2QH2!UFti(`}ZMuIPbZM))50Vs!v!-}-Fckw4+$>0aaB7nKSD>2%O)?Jc zqQxs<&VY45K<$lb+@rgItE!tx3-(jht=qp&^ydZ`S(_qz@j)D3Yg_=v*M_f-Q3mr{ z2@A1*6dyU&ugOY-L*w3KU~lKa(`$1odl8stSt$d=E1)5i2L9d>GEsqlV}eLN@2})l zZTdq0D&(142erDtt@HTIGS-7?cLA4lkl@}d()5+&RW8|Bb-(UP5N)l3pmH)ThWmr< zXBH9VfZ$;d*e`_D((35OSkoOkvgR%Tp{Om@ai&F2NsT2!Ik3lUqOFq!S(zZmJ?yi{ zkFr0gJJ4_X1&+dNf?FM;Z{q|WyvtrNAyWAh2l5VK=ow=1L=b1;lwp8iA%S%fjw_we ze-$UV<1Xif$U<{8^Z0l?n5HLxiTcGD92X=C{RZkE;bXN9+CN7-Uw|aSE#f2`FFI z?Yz+~%H?4le>is#xO$8o!8FmaO$U@D4#L-k{7!gYm)x?~VDpyMh=mO>FAjQYBVL(cig2$$6)+&gk$kzhFju-!%(LZjAlU>|iQe7;U78#} z+!`8Uo-sh=HsM}$4surle@!NIaQCvK>kaYLbdhbKjd%;ne44uL^Kgu8sy=Lh)v|ii zP)jrbgncU(7+q4bEiLT>zGP)hh&{cYEKg0r4KC9o zk0vxTRR`rmEG$u6)ngSn;%sK6k_e+1xHn6w&7=eykt4DW<_G!5n3yzHro=A{4)hRH zNEc(wW&U{0mHZWaMA8%wZ?G)pv@lqg3y8a<2Jjq2nB~=KUYi{z?6LqRi9kpGN&p)p zV6t;06<+Nea8{jE?T9?4hinsSZ32ywB0qV2yeT9SjWYrQ@_<-EL1=0WG&N9@(Btwn zhW#f_udOrm?V1F+;Ax$cAWu4XM4hCQCC>ZuEg-nJKC+gUPDIou`7lCOH^3F_*iVE3 zI%xS5@6>|vnEZ}Vg+p49f{sMH&&|;%N=F%yj%THcSw?guZs~}!)MQFreelZk?IA6~ zR)TWK2ECUiM!so7YS0{_Mha%}o7czW5Tf=hWwe}+_<=koVw=85D`;1x$^4fvHE z1GN$<&-f3m;B(zJ!lXn@2^Y9eg%l371tds@Zg4l0)LTlE-uy@4gxy3n_Ec0@Lr7>s zO2*onN`T5#B!;cYLpp;S(%&1=4hE%cY-}Y8)6gqMdwUl6r`Ng;lBPCrCCFOGyUQbO z54La#NXK915)gIroqR7!527DoZ9<*A7K&wscbr4&qib5ZRDG~9Je$792yJ<{P~NNM9r%mT8WD2wVLFu1!7MYie@+zKH> zGU3!d_!+EctN?62^jnn5bY6@xbLNUzq=-DtK4Ia^hdE^QmuHb`B$wHY9PLaX)=EUe z^l@&QWg!E!` zQV82qn3uDDU?|HA(=&D!Pj3CxZ9|W0)Hp0R#XYiH=3rk8IIcEwQN_7z#7n!Zst;)F zu>BCb8a3bxiabOH86qjC5-1F{4#lZ@LWW#k$40$-Jr0MY8U0QoVcx%rOup{$UQ&Yl znEWVV*c>FmjwqGYNDjzCLv2b=0c^|&`vDz{Y<0XJ{IM@j;Nu-Y;=f(;cm!{ykGlyc zx`$Uu{^I+&9SgtVzx$g1cq(3qhgh6UN3y zE6cATvB&iy>QEsQ|4y0!rZykk%?7F1gAn4mPYLbHR&@rw=3u4!&o3XTnRsX>A~#Dt=uo?UjizM4n3V3yWS(rD!f zpNnG&yQJ7aLti)ZDJNS!hzFl%%arTruHP5$jmh2W8Y6Qxz|s^AMTat??N0{+*@Ua6 zD0ighNqjglelQfCI*I#1jc`cWdK;n2#VQDGG+z@!FORq3&2hn^eUL$pyjLi-p&TM_ zz8$+95ht(?u_KBT7=1Q?Fsa-b^g&R@&Vk7=AyB}G_|e@U=u+Y92MIHd1b*N=S(N5& zKxC~eh`8XT&3kB}aUKT+56jY;3|^%HoR7LSvWXEnGrV3hX5Oa z-&|I^O>@^UoPQ3cY=)fznbWRbINU4V4V2xbSRHQtrVR@i#l@^}d2ZQ_g)UYb3@0uwCE6^<*L;T;^1hU=Wyl+FL^sfzSwi3orSU+$0PmjL~N5!~A1Lky9#a znyCOUuFZUFJ(;L($Wa^u=*y!)Th|Vwl*;y zD@=f~JQ*i1vQ62n;s4NIJt$yAFur6>KqgG^9^eeem<`JC1z{U?_zz+`EItkNX@%iw ziJsDcnzw-R!@df0@4(ortpO5^I>amh86?5-8jjj8kH*+MYPW>DhjkczgbC5_GS*Q- zwrSbbOOw3$@jY;K2fqXffle}4{88`>4twr4Ag>?#xj{Fp33WCLMKq>^svB`v&{!kh zTO4nxh0`I?LJhUibd_BudI^WAi{ZJ%sU1vJd>~ZZIFLhh}_2ltH5m(FlFG3PZ59$k5*NBZxoIvbTE(?1#?6lngH~pQ#d5YTDS1UGb)_{W*q@cp8fj$GY$Zbr57B*j})jUYsesmvFh)^n2(eWLrI{5wL-W z6ZY*H)cp;zZ}=d5d-8+oW3^Rs>nxP6m)kK;Gbk3@>c}N*b8!(FrxopV3UWj>`lM;=Iz(2Y^#+Chz@(Tyg+)=)jy*rO7#q zYsPDB2X9E&n}FA>$5|cTWVc}4<94Aj?f0>|rT@Re(b<41BKx&d3SN%)tzmgcA>WSgoNHPIe~X zWD@}=n?w!fID_G2JH`~w#J5MLe@ciRKq51<(VrO}#UL{2w*0yAwV|9D(T1vrd9@kE zTc%}qP8sb3H3|gM6%>UyxKco0~Tq{P2 zyIyOixk9L=!aI`j&G1WNRR3+%b<}86xe0jiCdBrVYZ6$rataFD;(}H+X|4kK0>UPQ zf2(NTx7vfk-T7O)I6m&+S$K(_Ev@*{5E*jw?lNDgD>X?)hT(v|7ul9Y4mQr;wYoBxggH-!dwGmu@%!+F#h6X2D8 z9X|^^5Hv-onuR&gHSxQBoCqWoOi-zL{nfjDip3EorgGDW+{pu7Y6K;lu#Pe{KVQK| z-X>o|h%QoPm=Az?+P4b_srnE?1&)F5Ad&>=3n&$_@IrJKPPp%mFuv-`JnMkBb2E4s z3=8oyJ08Ue3E*ga3_IF!RIgDU00e)$=0|ok;y$Aa3XzdTi#6B3h!ATuqS-Wb1GR`bzNRtc^o6s7=WWO*hHeF# zi5QA%y;i$dHwR&-*zAkJIL6h!m3s3P_9l$or1u1WqIkcpyy$pdSSKxyAjx}?{cMj1jNz5Spfw_iQg!4oNyt7K)m8!K2{=3>_WlA(Ijw#N6 z3DYau1V7|M(>V+sxC;k*$%ZPfj z13n0=uH|DO0eNm1(_l~4A?qlK7_o=>vuVt^=;zwaIbYW;pz6w<09Z@yZwD;yX&mOF zWN4>wQMMfl{pM2vu@KZ9RZo5w>Xu68!b+RgTMXa@o~ak{gX>KWk*=qg3(pX|iLe&O z=>6B^o4WYA@k`wRJ_{?92ln{BPz1wh@=sknAB`+o(MWY&1$-6x)HmSi`YP&PvR=1J zUHW?mJO>-RRpZr@IzAO`i$Snm%$HuuL{?!4_^MBhz+!oac*lK&L_mrm(VI$WI~9x^ zQ`6{a_3q%fqOaNaxr`>y%wI!Z?HTxUyn2%f75pHO!U&T9)}w9<<&#lA!%?Rfb_B8L zdf|i#cTBiS(a4V9QL`I?Yo44%=w~R6mK)(XLDU4x`lcJI8lMgh z;GmSe9-MB#`n?!3o{}Yvhm0S9(>*>T(-70ML9c}{t1#eC!+kan;v@$}%jFYNHv$ky zg;3LQ0z;6fnxTuE%L6BdE28Cj1bWMn>=@#QNoWwhXF5+8DA+YUdk-W<*V{(#+s6C* zv=Tzx4ILNZDxg%BR$;6?fbmdIApzsbk+1je_tmR98r93VspGB$jFB*4m3&c5IA84I@BS8WQD>V#v!aS6!`=)DT2!QO<+)TC7O3F-nN=% zprr9Hgupbl-7+eE+h|fmdbVH2M~-H|mG%M6d4bC(Hx`BKN3ZylB`)Zr#A}Vi2G88n zrIxB8Mobi+4fyorn%I9|_YQIcGdfTo9Bbo}(fH$UH_$op-NN#Y5(kD%BD?ITRoUpad<#47FuWCTEqUY2+kSqX*Gg@EP2v=KR*b~wTW+&ZR$tA5t+Bh!SIB}T* zkn;dmL=S1SMW@*ivNVioD%xNH^}jKlFXX3oofz=P2bxBs3)?%eALjuU=gJG-z)-Ws zR%^!g69pMnmxm34)3$htA-A1-MCmjg_N0nO+gg8vD7aL2j7Ol?#J?lr9aPACgSxMWM}iTzW${(ug*_ z@aJ|_t2v&Y!wbUwBXDDQuXQ)PF`%<>!OhNJYutN60=tqhC-nK3NuSA(L>`WdkKpZW zQ0f`%5v_Zqy!aqD|N9}~SI;9`5Vi6awios6@_MC`KME@i>LctF=qZ-)b@tv9xWJaN zr*X@G@=goqb|9QnV260l16W#s6Sv{@kB00$*n#H=2se5~u38;l0j@s}MzMpVxHj4Z z9XB(94&TPLk`7j4a0f$v5#bmv(7+zg{WRb|D4Q0yua!*f!8%3+0nlymTw;OIyO6eP zlSBxm*D+AJ>dArm8wf!N(3Z^NJrmN+WQ2v{rKX_7dxB7{?1L1m>N$}A%hsXfKq z+@zD+XJg@tfud>$Iy#xpPR7BcsLu&qKkW+(Sj)4aQ?#PDZVDRMd-Y z#+(OzbjHm=|2x!iSuU}vW^hG_*`mHuASn%{ffTzLY)g#en@v0YylI`#^Se&}-wg5TrQZKE9oZrbp zysa*d1zqG)T)B70R_YyBoi6rt&@mkQTB&0NEi(pyY?@- z1?E9&xlIOwU<3{0IF6Qnef@nSE1_YuzZ>iXxqE-37M6dY;7#DrAw;reY{l}t5*d=) zI^;Z)Uts&I*wWd$7CLx=ja|T@n-ee60oV;Y`^rUx6CluoQds)&SHHOnX($Hk=7HvY zox{JJJdCeQ9{QJ;e=%4|_o!D^T1npti6Fn;YPp?aIiWcG*F-2Zb-UrtEz9NBg^cfzMquB&iFhH4s-^+IHG0sP_rDE#z&-!l zpa}u1@Li+}z}H)68h$WXFac!<2lv~f3}N}jVCmegGAk{e?}RekR#)E%x=Pv*LfNjD zH>3?=(H{;v*r86KgRnSFV)VsAP*3VWl*?^Sgqk#M6dyT1!myBtf{(L~P85f!<2)vS zZv=^yL)ANKi7VDs`HjN@@jVDjQ;Q-lEDmuOaD3qN(eGmjnq;mIB<2_*szW7?fbvjG zYxRQGWp=cz3!Ru=MU4l6eU@ zhGKi73f=%1axcc#4&9s3H>bS7$opp&V5D+B5*#lB)N~{DpP)lDank*T0XLv_L4e44 z_>xK;y4$8x&2ib;#c+7R446?z_c*@VVquDCJQxwD%WPKvLdOEvCebm&$wrKI&cfWh zM?)XL5g=&ehf)#mf!HR&Dtyu|teSzXoow-8DP3JN3+K|b)GBZHrtPkJN5f4WL1j#x z1pd|&lF=AWC4?W&Y9aimVo)g9(gN(3>^jEZDHL2WmPMt^rhba+MEq0wSt76GZ%*iaVW7*To(zT?S?D9t$mf)s4sTswsv! z!c4aY4Y9?!P+>H5_{8dcP#K7yRflpEA(iZ3Gd1n4Aa$|W2S zMZ`2qVx|!!3rcFS6~YSn7_w!$^RSEIZB{gkz@LduM$qEOWXQC1b9Tkp87OeX!Rf1< zQcg?+hi1DzsNUV6_zo$mcsg~eKSVYi1m!1q_2WzqFd+!_?!z$pEzD~RuteV=W%Mn# zAzp;`QBk1_JUN25g;hO=tKTG0jBy-^_0SmrCwZ-CA0nsp!#M!{WpEGZv+hes-evXI zJLbv`0j_t`3b`;pL1sjgZ|IYQKMr$%jbFkKyaMuxY7cOS#5-Z|Cb9^BVEzLZ0{{TsHXnmi1QrEyOZ&x}5HdJaE`E zCJ0x3;Q4~M);AC&5_opL081r~4%2g@3msJ-!5A+?JKTeU0t0_*e0seT!DdPx2l@{= zUD&jML)C|U{Atymg~$|?y9xU9KsV9`@06uKu#}Sf*5Wr2SD32$xCnR2idL3}7zr|#ViN}P86f!BNkgxCr zlNx0+9QaHxc9n*gWvQQJ?yvGmcLT3gPvQrT%P7)V%~nXTzASzs_B;Z=NW2#9FZu}c z9A@&fOs+8bX(V`YmoP`_H}E5aK*F>}WV%95T@{%1O(vTFU_DM|6d{#Fo1f{@-z0g6 z?!xFq$bilugZR0sK6dKEESL~8dM1wha|je_!YAXU8KnXa;HuLErV}r#a7#3aD>~t4 zI)ez8nG`P>BPi2xey+#{GfB-OVQa?TtpAS>#SY3bn1i@Dh%gteAN2{;dl0mY-wcDH zzoY7l_&pRwNYt@|W2i5t{s1=)9t21C?|GsA1S!Mid;{O(W8)}^PDS*=`lw3bhYy25 zVjgegeQOL2%16rJT7LuPALMCoNC7y9y%||$7U~uPfF==h4GgOs+^%;cB8Ulo7tObFwg1IFSX^mmRM?;Zf$N^sKCWcb@O&;8D7om zy8?;96Z)6wz;sm*l1<&g#|d4spCw776*mrbCzHFF+|7g&SYI{%>XD}=MxS|V^tnT0 zPiOAXy<(6c9>{|;T-^fbk1_u}%%3P>?me}UH||A}>F^-iOqS0pGAH%a5ml~~F&gTA z{_GfEoOfT!sd{P@ycnH-)hJ62Gf6Yq&g4-f^^_kkte!YtLd)8vRu+sfR7aTeMJ7)& zd4)-t$;X&{50e~|StfH#N=WLdLx7)g$J81A#7i#c=COF|iT%e$4;@nHm~o0TyTq%H zGx;QwH<)~y$@eq)Atpb<_pnEWb}FERNtliy-O zVj-{0lXumrf5o4_&*YDp`~{OJp@OewL?XsY1Wt()DY5d@YCd4>H60*{VU8rMiv)G3 zca8BNvBX=@r_dhda~_P5a|q%-FJ9;37cOqo;*MNT(GM0eDjjh{6-Pty-Vmn$%_hOaJ%!Z}mKcpr`Nm^z?NON3Hkq%(6ZJyN&DK&3%c!#3ME~a=C~1 zY`ovQx32?rt|n8=TIs1Pb-mX!WX0v~d-{%U!Mfi281HKc%)R$|?d0-%J$^Z~bG>J6 zn^J4q+`AKXOK+s~w|X{(d2nP7eYW1~{czaYM*m*tx`ai+;{Dz(Ff07-G{5h}OMp`Y zoB9)7G1jI3S>M#qF^D5)q&I4PqxT3$ilfrA!_R45_j|!_P2!qExt-PzZXjP}R-I{Fd_IvwL@2c$3b`~BYaaq-c%5HA~VZo1yv8AoJS>pil6 zUGjwYEV%1*z2Cc&c{%3G^KK0CCMA#Lc&~Sr1q{Y)+{e4R9AHF!a`*1GckgX`_ny|f r97D|8`@Q$xM~uIhzi^Net@K~-+054b-_|#K?r8U$_x>9G{lotP^!~p2 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce07143d3df056cf627dbc5dfa22607d118cedc3 GIT binary patch literal 11081 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 Ui&W0Y63sd4rSd=1@`ZQ*4}{@Q`Tzg` literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/lexer.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/lexer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..caec09e1c5aae0951a288dcab0232ce730eafa12 GIT binary patch literal 20261 zcmcJ1dvqMvdEdPDiN#_8f-jJiMieD-`G6=&wq%+QK_Emy0s#sDDQg9CvDg^^3oLfQ zI|Gs!58POg?Zi1wl-kE}Y_SF0rmfnXzEA3=ZPFy|IXyj&+vGGS?Id;DI(4fy&FQI~ zw1E|~zwf&<`v9P({i93HeZTMhzWco{N}Zi)1;1yW{O(-ARg~{gr1f_Qkr(heilHbs z6iX>6mTGBLwV<-E6?FJ|)mVxZVk+es)%a4Pkl=8vnp{d1QV7SbL^ZwCQOIyOS?yfP z7P1^pRlAmQg`BF``a-w3&#m?p_Mk?(+Pk#3uopQwt7Ba)>_dtD_zqZ^S?!==AGA6z zD7L!MXJt3l!XXZIA#|8SIa^&gvZ)mw;aE3fkK!|5RFL)55YeL|1kX1@Q=Vh1OE~D{qP@!{}g-^ z{#p2s!G9Y5QTXTJKMwyH_{ZQs3;zlDAA$cQ{Exyv4*xm$C*VI1KM((7@K3@&5C0VW zkHbF={{s9o@GrvehkptFQ}8dtKMVf__)o(hfPW7Di}0U;KM4O>_*dY61pW~GkHUWm z{&VoJ!hatA%kV!2e;EFG_^-hKIQ&=PUw}UX|04Wr@Grq1g?}0T82lIDUxz;c|26n8 z!XJk}2!FzU-2S+I+&*bPW1q7>YG1JX?dR>M?2p-J?C0#f{j7b;K5d`1pSF+LC+sKe zkJwMz=dCO6_7x_rA?u~L6?<~y#-?&bL0dQN*X_x574FS-by0gqbH4eCVqINV-%|Mm zylf3`e8PIgdKI)P9jHTngOYHzAvQ>?KEI!;uDT8B#BbTR?c3J%cQxxZYy54aP_!lxpG5qIbrbPv&VL>8PgrjtUP64v zDj@!*HHCQDx`oqi(Fv!LbjA-V)@|e$t!d=jR~4&d&0vHx>snzJv9dLR*aT|Kt?Pw( zq*#`X6dU;!#AdBI#O4rNux?oyZfoAEpshvZE?A4mU9_vHyM%bvT0(p&Y^{crnw3FH z2KDQfHlgI}-q!Haa@Ah4Yp!FK%vUP4g_8M{d41KLuh-0SeQBmrE4dYftM+|c^qZ6O zwmCgLLXqidvs^7XPP*clD~@fMZr!x%rc+$@ah>_ftlN@z&qlMgr6Ty5!mp zx9r%BM`6DkWqVIML|Rp%O#iM2=18-hcK~Pb4&M!gs2N7Cr8F_43^6CRJmiQcDEwx zHCo&E&!L4N#>*CDioBM^G8OdnDd&`zIWZ-sYW|e)r)qicxf91vym|Zh)YPq$CoZ3# zn(7ZD`IGtM{!wHdZO!5cvX17xUrL+!onV(jXJ<|nFTZ*A%+t5>r_9H(wzZO2I9HSbm2d7RRIS!&8URm`7+%LOZQI60@y z4%_y4%s50LgAW$k_*a$+8M@KvZR}7R1W+YMs5MrBa|=5mhC`auHOsdBCO0lR~E8z%CVO!awxj9G84qyO4YK1^u2k&jI)d$gBV6ra)Sf` z%bYC&qgGn7gSg`gz~X5i!=6IrB+DEh+VS^*}ElCDa};vFe}rDQ*KI> z?u8i%3Q}4p5EFq_nBEaZkryPwNMTR4QnPVxfE1cVyW10~F;0qFkb~=@Qc)6>>1as^ z46EdpXu1`*QmO{JU7yYOZKo4*L?Mh+8tv;c~21+k(t*6t^aJGE(YpdPGD#2>frgQ8xGL$RL!=l z%TrfuXVI-MPu&>C|5q`s86f-e)JSD!%EA7g!Tv6m=4@wbfi8w~PsvMQc{NC1uqtI2 zOSF9HC(+&a@G0U&I9_+O-;QaC`tq`EiKi*^Je;-(X-J?6mGLyVCxFE+}&C*=m(p>{z%re}#6>}3- z+)Y{uH)SQ=w3Tu@thAf4Ix3lsP9JqQ=~~Z>dO1GHW_^|}aRLA@i-X(}7f+y9??9ti z15!+eOmAOUe0zGc#xmfWF|&lQMvd+1`x|`_6cH*9E9?!s*p}RjY`)%20yIz~u6^J2 zy28RyWcLK7rtqzOq4luePa$$W`UJo%AuYn&B(JQ9!pmJKZ}w z0?O5#ZXd|BIRh$pwl3uK+Q?4vF?1zjaDby@&N66EQKlqX`@AmZC_F=sMGhfz=`e!Z z)80{$ruNGy;$+|`T2js7i))4^Du@G7awEI$U}NrClytFw8ye7uoR{i3gY^|aH*HaE zWogD1v|%;-9>Z#R9t3xp$$6s2QAS?&{U-PWa03;G2`4ZGvn!yfunvG=yT)`kikBj8 z07n89?b4E@=rH?NFqR-4_EQAPPs~T^0SWo02{sVk~j_O*>P*G!>QhlSHadF$$aWft71O7N56l3#6<%%EharE^Jyqmq_k z#okujtgn#-M)I|QvZOaKh`YE_wETJnq0Df z)Jxrd)0}dr?%q1-?FZv=+Xo?jacUx;fAjX#1TiSLPPX9zT4*}R6SQu0o6TV+bcg$@ z1qk{K_}!mkq9m{JfghCz`6^0oKiBCCG#I8Qen8o@72abM$DE3CfEPeMma5LB{$|-p z+|`Nj7RYyrA*%WkIedg}|D@V9+i69lPAwTGmN{)raf=KrD5lU5BN15M5RiT2P)w8fIbN9{5-(fXs!d;yjaEa!+ngY50Ql`IyCIVcu&keUwRSw)YlUM^gT{wUk)aP9ul zy1XCJY@E(ltq%4Mhn|?I-G@!P#KZ1IfG#Vb4}hGnZR&5e4gE)u&!fco`ZR^t$$6Wc zZPyA$ObcEtLbMwq(6;f)%zP$5K^j=G7^I6uaFf6>2xp4LJ1eDXn3E_Lt$Mjw6ogX) z9bgxzZeUD;78Y-D67Wxu91D4F@tO7k@z4e+Z4J&3@i}xuB~>G)J=D~+s{Jq%=e#nK z+kQG?FW_?~;Y8>61_aTzVW|);$KY$Buaj>X@2XbJisQV-k(7?<&AZiAO0%saDS=Is_Mt2Tqn|@#20A*w8n{+!-8EsBm1fW`A z9rH2o8T} zf!U$+GRU;u@#*Q-mg+UgZ6H->id~`+NYrg|C7=y3GSqem?F8|YO|t4GoOa%td8~rm zA5AVZlUCc-+MxcRl29Dhn}lfcfaay;f>Sp5xg<*nA*0y2)6vS)X=ldVRX(T8vNq*y zPy{4-4r#>`a&^O1g&4-IK=!%|jkx2MrJa3-+Hdm7KT3e##wUl&tN0=c;>NuMPg0Zb zP^bx3#1KD;8Hbl_bDqUgZ55YmbjwDpH1Wg8L6e`RhQ8EjjoTeSG)U4iQT1cAl6)>T zFWcVoXg)1IOLad-&X1Dw1*+RsM8#Siw>~H}kBkVx88vz6`ffix{1H?-LctPG{xb--ewmN_X5|$1? z$$-x!)@Xu>*I^PKLyGN9Pl6KWgMwI-{Kw%1i3?dZ#NbpCFafreZ!?)CiRBt3Ym!nU z)`*%19Syl5Nr}UYFz9IMmV_cCWJBBXQ1Y^4YV@NpeT)w1WXtQVd9kVDYeT$@8W))X_rsQz zS}hjy$?YKXW7NZ2;%AVNr(Wp-!UbyN^sLUQJAi|B=mmVv@4;yW z4%=7&2tYe)fcQ%`eMPD>Fdd%)Y{vPD_T6^D)753Ok?i*vU_91n@bpYjhk(%N7L8}k(yc^%RXwEh(q5DAU-O-im7_PJrDw$1SNtwTxxU-NhB@F)zyk! zwH)(2(|_lu84#wY2%-V;480JRL#%4f*YA-?iq#e-a9W5BLWr-pEEgbR3XLt>_ z+UIGEz?_qc5GWMF@s#H6k|nz^!^3Eja^h}O03&sPXh0j6&>U1#;{0@2a5`eBgA`$L zMo;1>rpwe{nKnE6QJ6l)6m(~RP{D;oWU#BP18R#p6UBxPp-wSILXu(}Qb-L_NPV5s zQf`{$r%?U_!t=)HOU&#AO1>j7XdQzXL$%P+c#tSAuQ)(x&CvvLhAWHDawM1=9vz+> z9vBf1P)BUQ$s6+a`3scLn8`L+W55`q15XsA5~u4R&i}Hi*V}@>{uI2Wp)#+>ZiE{F zmDmM)F+fgG=Tu$U+2Kxvg~ClNO)`BV5*M)g%e_RJEkN?S(m+fx@fDO1f0-O!mKh2W zX4-8ugm&omEEaEm_>g3QHXKSrqK~IfvNT`G(6*|cIUsBkx>!hWNa7QTW2Nv1m(b-8 z$Lmm$IBztDp?h7eTYx!HLSmv+gWhig^&>{}Zy+3~#T}z|7AwmOG-}2`T4vjLDSLO;rm^Uf z0FI7==q0flk=NlE?_9S9{QshT-!eb0B5_N?t0tO$rOFggJ&2B*gXdWU-EyB4E3;Ap%?y>C00urOR_tl!$6kUM4Re6)gZMi%>Rks+ zn}L?@w*W`mV8i@2_@Ki@ICBu6a}y5HR}wlzAHm3mwu!W&QhT0qB!Uy;Ue1jn9_MRE zd0naX8H$@&y{-Zkk#uw;Nfg@~N=-YD$4y0m@b5;^_E2MK}!c5Y6Qi0wt73jPW z{lqi3AQJD16>KdH02EzxyN1%y)1*R@IpTRN4YZ+AT%s~Bei{^{YvwyzkP)eXn*0lk z5%gVqpG1SZ- z+?A90abyKa=B7xv!tBgXAWaGZ-l7oGTg>b*{qtA328_!fO>|eqU!x*)cZ$DG4oMWm z-zJ9<+ux-S!571z_I6Dped*K2Ii$amw>_Ibm65z_zSHe9m{;D3l@&Mib;3 z<~ETU#HHjt4Q&SwT$CdyrzcWjv}CLxL)@d>4yaO=irl6XbXI{na94!UT%^5o$cnC3 zwu8Nkw!K_*A@nDt8Y$}pt(Uk(P6r%Zqoe~7*Wd&(o>$9O(Jm1$<4W7PpNsZN(QyiQ z`}ch#n`U*W_!U$w<7@lTe$mf42B($XwX}l4;yYq(lZDvlfLIH0LJvVUl30&S(0sku z2c!xDW@GLO3GztMxl|I1baRwoiALrT4gDy|eOUELGSm6eU5PE^(wWd8RV$H{ho`;c zbP>hWMI$B}z*W`>HR9SJdk-nN03qhA04Ts>(Go*=ptE*@G$EwGb%OZfJzys1JvB%{ z-cQ;XNZXn~@K4e3uhGJ42!Mat*FInHOtRU;Zjek(I@P*MO;STaXV^vACcQ$-R{k^O z%8Tz;5&9?8A)$Q|PZ)-vv@*W7A0dzz@HwM!qTM37{(?bzCouPb4#X0W+3O3C+*=wO zlv6l$5K2}qqjMS7RH24(L9t@k*ErbIai}o_4Wd7YGd^{s85ywtC@|`0k<%izWSo__ zE^R?2qWWo+2x2#CBoK;C(qUi)g+8^ZY}D*Sph^)&ALW2&IE9aAUr{snx_zl0M_ zeK(;crXFiiU&O5*QeeX9AcN_A z*I>y_tdO&M{||jo`E6}-uO#P*LC!;h)V&P)C6eE^Xa_5;Cdm@R5okr%a*HOr-yB$R z>!9E(Bvg^6tz}3==?V=MhApL~x$WJw z;@b~XA^d5GT{O3Gn-Q@ATf$(SS0rd$w6Mmk=d!d0^l`GIC>Fb^GiBb8a|yK*F^V=!R8f=7|9eN zP_G5*gm{&jZDP0qL<6<_9YSs4HF9u-Uk*e{@1}yO4BPkGW#%`$?1{_QFElKDFM0b; zOr7zkPWkyM=OmKhk|q2Z&p^ocw0wT2J*keaNe4H9kLftJM(L9_To$fM><^UWaJ2`q z&@M&y4DR?NsNwT%W8$ld=r4ZIWUcRnnNE)S?~zut_#;RRTlQ>#mnP(SP!C z9~&^nJwdSu$P{GqCfBTU90eOiikM~DKyh9 z&3Q3dMZ*%M8f|!ejTvFtK*%*$@|1UYTWiP*IbHBRUW!&6FA|RBy)M}vhJ29|^8GD# zHlN2T2)Yo(zaWRMu%NSP8%`EnIcd81`pd(ULlf5r28Y;uz2s6}hs=9vWNctENP}J? z19Hj;?K6i*Cx@;MjRy%fEf6+a$^|K+H$h0ETt+r9F*!awdNt^X3_&R?E3?L~4~-8@ zj*YX$3lqcQ7ig&ekeq)&&OajO7s>f0a{e)#z*qqF#>9wtlM=~jNYKd=oHU##svhyKHu|3u!s;utuxz3d9o#-a zCL*02q1O%$qT3sc)c;yg*lOAifv@rRmW zs67vjxTa~KhL8@ErtJUHIy5kwltQK-vRqu%wzOpL|I{)&^N_NIl45n-apbh(bq#wN1YgzCglOw|79=R4&h<}b8Net3EdHq z&UdpU(uqU|`^Q8&WLDGTHtd?qHk;^0CX4b>3lSLQdTq8c2U95vPgf-CMC^k+?9!r= zgimb!&}t#wBA3#|B1RyNkVA(#lsd5$#J24U_7rOnl;RzhXGbiVa}$%0c-!zIyuGs& zcp(_Bt%$NMj#5u=!vXU_c5(8CA$mRf5m`+iFUyk%Ncknm2HiI{jkOrbnISeOGDF`a zT@$oQAPrUT{2(jJm>?%Tl6gwXo-trvgnOd23|mv?u}U&468yuMD%GgR+P9EoM{H^vSt~*9LrgmY$wb#X>S|6^){?5?opW9tgUNDeu%+fafFxLP~qf{s( zWF0~iT7v{0jNHRJF7MId@Ihq5u$lnBVnKvhnXSO~kO1oahxi4tl2fi!AkTre%K-~N zkB63oQ@rd-4ezupJgVh4GHeeuD*hHKN{KGcoRU8jWbw9)bjDJ>_&WP8 zRr*il@ZI-5h3Mc0nTpdgC?dARf1va@#60Lah~wQK`Kh7%BpC%aEZO6EDg*=psfqYq zs>OysFx=&#i+@W=05C=T9u-VQx46UdK$s1En)0@R*gB<^;1p84t|YyZc#iH#ymE8q zwqZQ+-;gm!fINbLlFHFF15QVuh4C;R z%c=X+6S&rT)ievXp~Xqd%Yjf#xfS_6f_`Y380=pFLWo{B;e7$@@IC`h8~hdS2Ih;sNM#1k939|NetvSJOk6>AAAIY%59j2U57F5o8@b@o$t701F$XmAm4seW?9 zKwbxNPozD8&=IP7;^_g3uv-Vnq~{cHTygMLnYB(o1yrQp5#5D7Zf;TMo|J_i_PaOsY$_YQ?%qxH9o6}Hw7HM!TZ#S3+CG1u6<-9pbbi9` zq|)yGjRXE3f8VAY?H=$4`v}=>?+HkyYaIyt);GXS>|Z;8IUaEPc#hxp5BLdOSsKvi zm;D1)H|C;=^H>cU$02&Re(PD(I=I&7_tCzg-|wTwLBDU7Q4_*_a*od_YxpY*?`U`2 zcho!IcMtnnXfJvmKy8Dz&-*?8eyrso{}5iikE8!1cUAOs8}$$PhZ=1il5P2!{R*{5 zdyLk8vGyAn(IZ&hL)fuLF-Bb+^$%HuZZ+|BzhlF&dg-*(egvs|IrSTyx{p&Akh-5! zzs0EsICT=K2k+wSpsfy!>ie!~_4$XuVI6`-hGYafX<|_0G4y=cKkOgEZlQFe9MZTn z5Ot&Up?7rW97aj=0}F-b03;!vx92{0A+(~B{bI85qmtcpo+cTmB;KSt65=&Ks*a_38|;yzl! zU*%Bv79+({oy1O(M3H(ZdMn2_Po(xG%94wKRKg|IxV;*7LH(vwi$by$wg|mAiN+RI zVEcQoM6ZA#77Kg9H5a|WYf-HB_nWxp=zR}vFco z)8ykl$+WyyDMCRKhK0gA+{0uH-`2nk@)lccen;QuJLA6tzw#9qsA)mB9N(7Ww-6%3 z-H5{pV$9ljozWj3V0yI>mv4wC+vM%ku8xmXCr%$6JZtHZ&suQ$0fM*C`7 ztKg2M0F>>^YA_}vi9%%AAfBOyo+amLa?X+S6gg+%K+M5eoJt8^rbQ2Vd`ms<{t-zG?ZUu7X$FXK z=s~~3YF=i^%8Nk^KH8diL zHsTCnIvQ%V@uC-|S#{^!b`tLQQS1ScaNkBi$@YQ(i^GbRRDf|U2aAcUM$!XT2^z4U zAPGYpJUq(*;xSDpqZ_0ehan_Lf{^Rg<3EJn=>sF4*)mdD4HmL$pOynLm@$~dBO445 zdQ1w&ljtKuM4yq=Nv@G;`KXuNL&G2`2ib0LpC1_D7c*K`>!liG^@|ULBmE28Olvvx zMC}_f%mOkK11jeO54|o)R5lPrULPHWBsctewyULn3=1MHgFjCprrKFD$4aQLQraJo z^9^!-ogAjZrSctiq*D1#G_s&oZdv(@6dfRkSlHjfE;|D10 zqq?)|2x6-X9mN(#gv1Nt-%*vc9Wfq`1f19ktm+++q|DCAH?9vA2VWiv-TFg+T?6npARfMX24Juk1BQG4O`^0aML+~z9(7&S4zlRf~hp&!~ zjSmeDObi8yn?vI-j!g^+I;MmAmOXS+MfvC!r z;hT-%*kmCo<%UDA6+%%b#HeHAR4B~3I#~$cQ(v7#sj#<^7snxljp}gh)uG8o?)8E3 zq0y*?kwyz6)IvD)Yhza$!5bq{+0mh>x9h{#hoS=4$6k+`9&hWIV=Wzz%Z@_<>cr5s zVYv`tpA$D;j238ec;w2E_-$HH<{X)$Bo2$2QHeEokB~g)-2RO5`GyVgne4-(R7qK~4TDg}zA+f#hzm8YC~s z_j#949xnjk#_>p$7+m}#{00|{u9h(lGcE(}d1%0#LhDTb57@h?S~~rQklBVn{r}B3 zq*V6*$^CBpNRQeFEdM0%Eg_zke}4>#GNi_7VAEW0E}84hCCq%btLJcbUv?>XAlKOw F|KAQn3f}+# literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/loaders.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/loaders.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fd33878b328a4e4afb9de1254fb7b14a49af6a9 GIT binary patch literal 21164 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 M{M0W_ot<+24?XX>!vFvP literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/meta.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/meta.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea4c8475e5080781b33c4b662881de1950352048 GIT binary patch literal 3787 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 VSbg+EB{u#!{tuexo0aAd{{=Bd-2(ss literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/nodes.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/nodes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc870ed583bbaba3dfdc880f438ddab52a6a5195 GIT binary patch literal 40864 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 Rp*1PIXCt2K-;~N5{|~r~)Up5o literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..068fdf2d5d740209bc5b7d141875f2f9b67f8a92 GIT binary patch literal 1918 zcmZWpU60%}6t$B~CX=0MODSDZknj^|P#F+NJRnrHEK8}17DTtI8U}(l_RMBBV+Y%_ zUrL|0QlH=#^r1z(^ojqIS0tqV1tbvndUpB&p0VTDH`nLfdwls|kP>Jgz5VCZ#)SNV zFE6$TUams7Kf)kLMg$c>MYBMJBC5i9ltq-lyi;}NaTZe|gIU*n3@dS!%zIf6R-#!d zx_(R^hN36Z`%$)borpEjzfVM8#wTIc7r`wu9Pr;MA=|r>>Dra^@>m+?OermMniX1E z$CYCfT?r-+Ya^{KVUckq*j$Tpa>N{bd+pYCS}ImoypYUlSmTbBj@ezkfG>9>n{eyU zwPtdkR}1dsC`~_;1z%XXa>0a#bCq^@u;bv6SC!wig|16AWu=;EGv^L4cnENITIhLQ zR^WS=d(e{-uz3J_;V!cS$qKH}snE~-opSY#ESRJRz;eXC&<0rYd0olNtkSw>3uSaw z;n9dqz2n${HhVy534FONg*Ue8foHqR_a);Df-{juLi7;595D>C)z!kIUz$Q-II|My z3TBUh^C1LZ%GATRP8)EI@m=vZi%Qy2`V^Ewww^-b$dI-jrG>OGIlBduZNrttC`kiL zYny7nG+NC8hv}ew*hXmIuF2;+ZEU1l7*z!5__T%a1bvbX==Mz*9BJqYy%#w8C~)B{ zYJx|dhCHT^QAhOn2jqu|lZTG&mcSe0j;V(X0}IV+X%H7Aj)AINS*#@I(~vS~I~;8x zxk!5DYg+D0H5$fk@9ULBTk6`V07)4{*+xjb?d+Gfbi>dfYSV=w>pc_o6JpN5%3n7( zJ{jM((%7+*vZ}|QOS|WEJ-&Sd{x`YfJBV!jRkx!qpD&YK!n;AR^I$D;mO;?Z|l6^&RFS zei%I<6DqnQx!=!{2P6Vg5bmDoft%xXH^P``#jEdL$n^JH!@vi?Bw+PYRx!iaeO9p$ zHMAi))EUg-){y$ohCv%ySxuHcFm670<}A$GB+pA#x;#fsSg#m*d>&!=>M>ev4)z91IzRCk+D60^<*mdWhQ#OQgxfP1!pQYW&6 z+Z-ee8hs5|dCysTV_s`0p*xj?@VtWSUaYU;3`O*Ww!J(rDsF9_KM%TDhrPF;+lw%e z@KV&L0gdSe8qw(Qq;rPG!SVX@9K3{km}1TppUXUN(>#Z|4P^x8{XG9^!K>wtIS-CK zEz`#tYNHLWsUv@OJ2*vE$f{Z)^TN1<#+W>>$TwhOF`WrL2N-tiIczc$(@N#*l%jo=9oS!b)UBSFs R+>FvB=+k}>(|&ld`!D?${nP*e literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/parser.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/parser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..896cb0b9cf646f65c16f0eb396dd2d6f5b653090 GIT binary patch literal 28014 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 YT_L~)7=^Rt3waR_6cPCMS~2&30V7~gIsgCw literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/runtime.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/runtime.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc216db86f19b4fbe55b643d05f239991011eee2 GIT binary patch literal 32361 zcmd6Q51bs=eb>zF?4R4)TkV}rr_jiS1luMe^CQT`T8cDRHu~+1uNh zJMC(3_dK&F={9#w8#%3Ak`M@lw6Q@-Q@~JK2(+{fC55)Mg%&<7<=;>!6iVwhq(J$Q zR-qQ(@9)jb&ff0XNeiJT&D%F`-n>7*_j|wh`}f{d$HuZ6{_el)zbyaUM>Xv~@h1K^ ziks88yssFVW@}~5)@`Gymv#9y%7*+V$|imj&E!g|oYI-cY^GN-<&4CW&5@OCIV%i|KyAwE%_koXwlJIgyIo^MXB z>?-e)_>Sh(%I@-Ri5C!`E>BB*9PvHnJrbWle5O1j@tuh8E$@~1B;xzZ`y{>#@%`of zy5^YI57<*T^zvk{%v^YVcfmlegJn5;O-Re9<(3A z-9yePKsR;|6VT5lrWaaLBFc;b~_=QNrx>VBfSSi?`UcClJ- zA(C>uT6NW7?A=xO(%LFw8Lz$6sdydtbscZLru*6ITBlv9);o@i$HCnd+~clrA*f`& z-8tJ{YuQMf4AY)bt$oaO+k7+s-j?kw)mx4ori?yzx!Rm-w>r*M7M7{Jr|NlU+-1a5 zwRWpkWooXD=WeUothH^nG`&*yyn2h7M&_$4j<;H^F}=`UY&f+}rL(^3R9t73RgSNs zz>0%fDkzWD`1<>N{cH)(l8ZrmM;~iluDk8liqq=U2&wpA3OA>5c}Ea98i$jraSB2CX}F1dS=>h5E(pMezy zH=mrFeeS)U<9g4v9H+VZ+@p?nsncG4?!8aq|5MdYb+Ov1*Pc69UwqC(%kBX*FIATv z@3}_3)u^7hH$b`4>N>`!QmZzbmC9Wx-2)NUv}AX8e@9DU9-y1*^a$T;VW27%KU=A+ zwC%MfYvAh;8kmq(CE zYX93XGP=QkUz2CWyg$n31t{i^N0{j>Ie>l5@ssba)_|T#7MEi%!GJLKM^|J@R2uDi z3$vo*2C=#gM5%YyT`oxOPG%j6P}?2HeKFw|&UovsTC8$+gt@uG6%Aj%>K;I>#z77L z81Eb84GeNo@1A=`5W=(S9ZYw3d5w5lvM{DgYfWpZ?OHX*?O;Azor{&8anhOTR!#74r_uNm${$FxCuuO~aH4SmD7X57#Xbo{*b!bB&% zpqPfm7&FX&rv>b6vqRO6rHBgpa$<39$NC2_X9HtQ$O+Vlw1im4Ak3uSdiVbGbx>`G z10CxQh&p@d5fr5Oxa|R_R7^;t-3L*idlUf%n9bkX)O(Tkeq3sR4VU+4-8~5XG{7xX zIOC7Tkj5Vi7ZI7kermDVu3hqc^K#Yo{FHaG>N)`BaUjdH_3qCM}W z->Zla7uGQ2>Kbswbf-2Fo9WhMN83oQ9oBAeYipA6O!>mul& zSq=SIQ#t3mUAUsq@G8DM`EsJGrEa?DPvMM z6DBaLAlL;gyX8KG=QU=E|0Qs98kff)TCenS!Zx@FWy}%Hq?KD!r@**YU zB<<`gx;<*=a5rKn0JSmq7>emmllNHQI>?Akz8|1u`^Md5X01t;Q+bnq}OV1&A3825O-2nK{YaxcGF@6=WPVNVg0pR5X zk3lxM#D_1l1U6PPy0=wgUE;&iNkv;vl_YO5<&TIE&~Ah7Ca<{FRZn2)K8N>xvsT4A zxEoQlTPj;XT-8`%Oa`>DwUU?c$m1%hfyzuLTpO_(Z{vTQ!>4h1UjW|qQJBMa0s;`| z3c_?C+-01Uh(RiK#MVRv%rZ450%q{WXzxAn)#fWnp;XCoPSOY7#2aIF8aXo%tw!uD zXjUFVr_{~*?NOxX>@o1r~YNJG9??>wn*tenO zQ_gN@y0Hhj_eg98u^EZ&MQktHzR$Lh`*!;vTCqRY7bTz{a8lC#J4GzNO+?9~g3s08 z0@9MKg93?^NS=brnsu?=w847d5f=G6`Ek!`FIm+nXUVdj?10Z|yLb|EnzE*O7UeC9 zo^2^0Dw{kD7z33`609nSo;z1p+u+|6k2)u7acdb%4J2DI>EQT0aC~*t;aqDk?yqDJc`SZZ`dbxveyQ7L2;WRR9|eb zHCahVN?UZo!YN~4M2=Ec9$Y{fA?VP|`pU{0WU8hED80LF*OySglGMSv&644qT~N%x zf_3!h%9__<6-SRsSr>&j6%G$#($IIwcrAcC1c%scwyyvTOKy9`T6S9GQG>2WeWJ*0 zwOh?~wB|xM&`b3u7+R$|P@G##pFo)hg;qUj&@5>T8w@Er=;Q+G>ImejP(fVobv_t+ z48>C2MYlpxMG6uGh&37rQmv7Nmy$yGVc_k1q`5uV#`>c0Ge7{(Vs7c2MOtaKv5p0x zKC*x|E*z7Z7r=6P3&*Slg`tcIGZ#eATlJVseqR%E2!LxxW*D7F&5E>BYz*cM|uJH+0%WHg=+CXY04W?TIbAOVl ztrS+$A0_7^7YHTRJF`yPZB?<7CZGL$ojjuwCP<%eg=#st~>0$NByl1jUr%tVCoOG74Lo zE_~AW;XSW_K+B|b{>x)=PU+LhZeeR5UNhWhkk7pj0XR^OFgWuym$HZAiwN5Ak33NZ z*Bma7quf0tY%ZBz2wuZj{YB`IE?H}<09v>na|Pledd$KKsHg*;26a-c(g95)ykOs49F5(kycaE$OR2 zUM~ya9~IG=ki><865;1wVPHjpFsTWU@}EVLF#cMaBLN|4G=x8%Ds(qw2!@Mxg#H}M zpgcnE9K1bAiP51F!cqd#25|l3fcXZwexnKu*S=2BV__el$r0cK+Pp1PqKr>2S?ldJ z@Hs$rE{`_UJYWy7xGy>vtC#C-7vl{jkPH1|^iu!wQfa%DU;)4)#UY1E(6iKfQ;Noz zOb~~5Z8a)KWC<}SfTL0?lX@#wOuOa$k&wsr0DXv@6TxB_Ypv3{3RS$!Oo8+)lge-h zC_1$0vYh@h$CT4b%VweZ%^TevAzlPIY6hPMe~j}IRG=WJ^oe1RW3A z5{z}Cd-vnua;un)R}^qeD`8uP@-Di&!nb;*NsN&6bMcqIij+|8FgdLB zzU~oz2%YkBoGX|+2)${9GG}-vnq1sdm&-ZS{i3pF0F@{?P}L37Wi1drAv*{w zUvJf#Yc|yQk}d3Igqh(w<$>=$izTqV3ZrPf8!-P63p`pz73r%lUla)|T%7_Yn&=Ao z1@%SSXl_S@4cIt*6vXY{WPIq6QQ)Gxk)ofDCR%1nM3gt~D*n+9K(sm)p1_rYpC$#Fe zFJlRXtsJryY@DECf@WL9S>RR75JC-uh_w+Ch6RWGR@5Nam8_w1bK8wxjz5ppve3h| z3u5)0FJ~*D^Q$6Rlt(MVFUw8$aS>LnE2u5va)HCODhYYD2Oqaur$(k~orl%;NwH+n zisW3a!Q6}(bo}oCD!DrllrvN&5EYfpRg~`QctFn9g|Kf!8;5#BU4VOuZ*tl86RYi2 zf2^+#SC;ZrIp0HaF;#ynU-~eEZ$nU?s8l*GO!$j1JXbDaWGa<%Ml=opv7&<(GYjQ{ zVzb$VTaV_QK$AiIyT z=mQA)IE4ffB6gkPG4<)-1|afM7QLRhAcP!s9eQa8`L_=2$VsZOuCBVL-i6UsYu&+ctO9_~ zNAj!i@(f~rYHihqUQ9&rkgb$47u>d@mI&$ocHBNdqsR0>V!s_PC}oVrm;{3BaFF1*DJ9ccHjCwJdN*37 z;~DxIL;U3>jZwq1Md+EKRqLAm5l~@Smshu!brgwRSoq-c3*cqf(W0wL@+4)ksu3bB z^z>FR6UL>`VNxIlgAASG{I4Pwj*c+>CY5hna6~LbPZAEo@|$G&Ge&o3h$S(0c7SD} zhCzTq32>`^wZdB%xZ!W^@^wk;sd|JO8!(y@zsiqsY?IH(JB{eSaL#)3`i#BW{IqppJ5qjTA2U zWx?8%q>V*cn_!88T|2TZndPiAis!k&j-)F)5-clYP9EiCLTfluc0?&-c3$i^1>s3{ zh-RsK@adMLv{}$dTRmF|*v`Pys1(@BlWMM${6L%4!J?-;wm3^`6db}o#yQ~yZTBHU zGEz~hSX~sY#)gTMM32ClO68Xc*JnQkKR(oeUvVz$Q-BEp{BtOGi^rHkURr2B7|pe` z;$pkI`>ouO^3-jyoT0)NnO5n-w;+NUhS|4U+=LofBQ7P~!bA$X_p zG{qdaxX{Ymfi|&lp1MHc-C}w~ca=?ffdQ3xO6ibs{{rHEqUp5UPc!w;Gl=vJYDk`8 z+OUbta+V2;EFxNB64;x+l}dCcw?IR5fqkTh0 zR$ipapGzFD!gcUN%wa{rLB#ygSY@jm23eg!{HTI3S9*$@V%7hcQnz*?pBg8Pb3E zvwT3za9?3yMFD#(%=d@bQ@*M}%aK8E3t?{uCn0&+N~JhHbQL+u64g?2j@;MBdH)Fp zMFyPceg;Aj<`R4wKgl$iIIb`tO4lmR`t0lzndH*+~~PZ==Y zSwj~RSwoh-zlehWPm~Z+@b_YZ(^m;j{E0H`;;^7+gld~7H78q!k3b^_8lIH9vEVKx zclqEhEqAc_OHO!%*$*OKaK=$isxe__D z_>4V)Rbi(+DQm!VaIgFWXroup#VY`B&{nTf_SiG>#@;9;^aI!zrR=v4NS^&jIUx1i zW?PbS8+#)u%F=H|ImFJ7nr=r*s&P>AWyQyV?G(E|p58I^>0$eblzzw=cgF1^{0NTP zcf*h1PL_fe9775n>P>7P(4_Wz?c=yRjOXyQK#RnOL!R7cpTLu%a}?}rrZGS0yRMzfU&T)>W?U+!xdu#kWHD~QXeyML82K8n#tA&n%f zpCM@!o?!>fhR{ExjPB$)G_fbKgpP@>6e&C)5iR^<+`uI$!&P4S^@WR$?o&>pIaFS^ zkU_OWn()_g`vYtOOMp+=bYIo6&JQwfe1p|Vy$wXT2*P7mcMFW22ZKRRZ?bUYNnsX# z#Ds_U`l8a`b!7RZE1l>O6>>xS$VC%xrFXNuOlM>btRUb2fYvgOOC8{EjPCcGlPMZ{ z=!7E{voyd~MomZfM7df7J}^`W<3FCeS16#;!$Jg57}4V5s#ovAf?9_T(6bzP1iA1M zqH+rg6`&Ik7kXN&3KdH?hJf>MYWy7F;eLj}Uqj%JT!06qGCF^hiQmtFuvdoV?`3QP zLCE3^87eqVOONSMr!3CtERaR1t!VGGjP68y^i=jf-iD~cONNY0w;HHG^Wy#;qzq$j z>63}lDwUs(Fh%d~jMo)BAE=BtB9#%tSs5978NWxKXkWo3ZmnBQ=d#m;Qr~fCzm8_5 zn&|=E1=#B#>kw32Sjm>@sdb-n34n1#rq(c?d_OAv*{I2h?s&Y(LLa_?2H!KMd?XY? zam@&EuZh_@v~90pi;}n<93KW%8Twz?u6gp__RS-EOL*earwLKL>&~yOEP{wa3!x|$ znh1q7J-;{)Kwflr#ksF(s8=qfnVL2HI} z(I4S@0MdT-_%B5rO?7w0$05q`P3r7@f7H(Y-R(M?3A^IQ`r1d!!wlPZwKq>LiHkw^ z__G(`942d{sCQ*7mGfLQ%JFe6DJJBHw`*il-u<$fQ&bRZ1Y*PWhV=(1EnM7!Ff?Rr zs4iby#Ac>7dLGp-I@rh}J`qtVELGh0P!wpta1@cLoSlTPA6E;CTWDbP9(01=%P}F9 z#|{HzRExk6x&`KfJ*qI%Z*ZWv%4#W6`@G(ricg+i#(^=5NUtIl^fsp_i;#+cKMbkJ z&-N%sA5Qhm_j5EIDTmBxM6e82?aOq+#TtnfvSgiidZvTGjK$m?I--}B-S*n*;<^Gl zwrQ?Oc>=N)z=raBP`dzF2L<$A6W3I$dbwQ}A7rcrQcCYFkfpyL!g?rKGTGPPjpjh6 zTZjXd4+p>*O@S$tOe80la~qa?aUUAz zLWCzW#gW(yz5q%^o z%+v<};!*?vGN9->@QHdO@s66oJ=9eK3V;KiQ6s2hD=dTr2-b+iH53jOfgb^*m-&wa z2FhmFdzO@EbPSE(5+85wiVs}~hLzV6F*KF28=~j&GtAFnOJfuiDHx%uXY0U)*@}j; zn-0hc97HO%9>=B3ak`i5fFlzN4|#6xGQ{1KMt>&o*q;yRH@yn!zZdZm%MiGr!G;3@ z$n1KpsgM}+dikQYSf$-D5V`~6aUhX>ME81j6^ijfq=*&XF=5AknUP5kh4|I zAUH66q9VE#}J|d5(^12h^7PW$U(w1TEws~t6z8sa`jOhkdL0E zLagORXOUA>`9ldD_V8hqsZ>g=k0U`lXq>W#8TzVX#)!C`m8t>;N4%8i9Ye;Zl~s(6 zl2}dH^KJb>2;Q*iiy9b??aU|c%u84exC1ba(u(Qc!tee#64bgcDEWEb3c(&a^RXpf z7>fJYA5rtd)|CQQX2A&1zk6%%RQ5hAFMF57HHXW)3jvW*_SH^w=o3WiuAr%ekk+vm zmb*I5?oWY9XoU;`Rw??GLhD1m%ObCKEUvW?g-x(qrU`i{!qG^c16D`=af*J_TiB1H zDxi}N%Z%aa1tK0wvSj~@$mPVvg@vd@%o@=Gsa?9_$_0dlN6)1mp3ZmYwkhavRL zZ1Y6)@Q-n#jEoh_+G>Pu7}%?+Owic zb;v>H$NntkXsS#SqBptD%+jqNVoXLuy85HM{UU=;F%ZT`xWS*`t(Y$U0b@VK;HMe< zBL+W%z)xOSgR`Ogb4(D^#!<#Npxc|Tsh<8WjGRXUcUCu(rZEBIwfswghJB6aP4J&s zJf;l&Kmt0Oi9AEtLga$SdV!Z&fJLM*V(9yL?I?^+A#INi@ z?6hd+cSI?&4;*<4QA*Yxl|17p7oLH5i#sa06LQSiDffAMhvb+1a_1}W4Dy3><4_JEGX0VZqTP`_XN7EXz33kHZYNh&@z#@@bsxfU8cBy zi-8pd2N@$~J%bn3Y%sg~w;s?@itB^7SBd^4%JHc27h5aX6u-ehOVT=&=|A zLiF|1Ku&Z0RG_aHE-0>rS8C&AjJ@G#!b$?FFMNwXL0?a4J@^L&>kNP2?qb&EfJ) z1YZXO&5=_a^mjy1z+o8!P>8bi)z}Axb5i3_KAJce!!;7Px8|nZpGARvth7*$e}+^g z-F=?1?O17-`Cew9;#_ngwHQsNii`!u0?niVO@TLPl*KXFEaS245Y&rW4+)YZ@C&i%^n^?B&!$T zLN^V+xjYyN zgBvpP4@Vo&4FgMfM%ad=IL_sQ!wuku(L03U8k7uWIM1o052S=tbQFULH@d+m!b0#M z2D=cl4CQf=r6=8c(A4hkXL-DZRRu4Pv$~?q>Nu-s4<47`Y(!5k-=x)9dBBZ?-ua%N z!~Xl)#fsWf;g6}i%h>oRTP;MacKwN9M`MMD1}L|r+6c-F{}@l;k{Q=TB<_m`*%6!- zmhe8q{RZ5JAUDE!4I852#>VZ>8|G!q)yl|5Mm9(68vp5Eub!@kQpOk~+#1sjBJnS-@|8VY}a%uY)c+LHn4E_}Z zmg4V#mvys_Q|QEdiyjaJ0=+K8D+%5YgTN?`DBX&9%>6QpdJlsk#k>E853DE<1g0_k zyNSU25Ya~IOh{oj{6|M#SUC-t$MbR=TjW;=HJYe%z74MpDrJb!9GRzad7lPF+|b>l zUZ$Z!IZ_EDVvv8e;bFl%fkV5in?j7THNbV&au&LqQFZeqvE zW{M-&NJ7Q)1Ncp=C#nRTK6QFC-OX?)*8gmsssdhJk}WPubXqa9Kml>WtgKp~eJUDo0*TP#X|S$#!;jCh4Ys z4O_QgMW01iunX_uv@O&DdjV59Q|Bd#%H*sd;f3z_JhXnaqrlH6*rM%W7`rJo$Gh*hxU;3+y4>b*6iT~r zr5&maLp7MUisKZyhf9?dP63*Altpc&4fR&De#wD~qKX|q%cbsKt5dxsE&<&6+_y={ z>h6jjc9f11n<83PHy7z&Eo-xg27K|FbwR1@2L1cJ> zv>f6E=%|%X3w0nl=s+OI%4UfvJmV(q%&pWdGufNa93uEACKN=Z#iC^;Sq=Y8M9>z+ z%vy*5tuUQG5ioj~#D=>MauSdkh8d``6q{k^hTq+pjZ-dg1n)y?qg(MvB<# zn^Y*pHb=aK#I1dx9%VQCK;UWmwBEyy-j;}otz6j$SrS<@<-011o4>@{Pciry1FkSi zt+R_UQ9<3om;jcb+g{5<9^=zMJ7KSY=A+tIxk(`hG!9M^)iYns?HAwHb2FKlQQ=Bz zc&qP^+P%}bypLfe>SM3On-!<)CBR;p4jhP`5imySMm827b#h>^dV3R+vIk)V=kw|6 zd_J&MJDfuBR@R1QCOF@UTAgt`8R0WK4_(g=yC7PZ31{5Y$~$pQ;@Snh3-5R1g7jD3 z1MgJc?=A0>-~HtS@_Sp^lHc2Lm^7c?QHFmge(%I}7p}wQBXVCv{Al@Zi66re(dtbNO>@p$}_Ue@^|lkilVF>rbwt)hsKLb*0+d4S)I2b%sWmJe~FOyCS9!+TU1EV63qI7j4p70XDJ z8tq+UD$G0Ye`KwWv&$eb@sQkQcs)k$(b1qNRw^>-;@Gz*neaow0x4W4=}KzfB^R= zVi*y0jL)9sA+cs`4_5(ubfDm+1~LPj|TG@KUGb}tZQoEciWdng8) zZC@C^xs{Na!{r@EumQQr)+sgF2Be!KxW_)U-aVzTKn}oZy|9>?^RKfBzEP>X{suhp zacXD&Oo$@Nd-lKMxjTewzy=_ml}d!FRGw#NQpl;LEZXpQ#X8i>h0>Ga0j$V`be`|v zkMXE09AITXPz|OJmEtLN;bdM5dQNGi~~g?MB5aKKy})l4Q% zPz#8ai`9CQHU0kZ>RQ+ue|fv=_^=O?`$!I}3r^?8xP+ZFe4}nFmTlPd;}P0b?_#C0 z9;>vE+^NR{)w1e2T*Bt5Ni*+05Or!;U2sFj;#R3_#Ht#PgHxWqbxrP{c(ZEUAHvfQ zZ&!u*K@U{Hv8~|}1-7j}CL8PUVGd$7G&2?+sbEOA#Ps-)SbcraQ~KDx3RxMiIRvtc z+}5FN$bvQ3WH&w30~owpVV!}8hObv*?KsG%R4aaz6)R3V1E=mdGy`35U)>zFVIy~T z+wSp5U~)i}%FEmJQ9b^;>Jct&+q#5*|JZib1k%GhhlvifT6oQN2S+ukD_#@y}S&+w$eHL;-e-B9$e2D zHnzjVZE(%t9HIb?W+`8Qm%s{uUpoesqTYld2dX=8a5waq^_TSP5che0bOXoNP<7Tx z!}goN8PhlniRUA}n0py+WZ$Xb9v>31(=TRh994e}>PV^vika#q%>Boe7aqK1*skz^ zPw|6s!{b2ZWRJDT;WXIA#Y06YcnBAV*Q2jPaJgTDXETly!STH!oA9v`aAZFLB^(ia z2pihzNEc)`c6R(ZD5>}<~sFv$9_^occKO+P2yI}&~$ zM9DQ|j`#q1B9aBkXa!n39EKz5Jr?Ik#I5o*Rma2XN1gx5Wd3nvACAh4-YTjFmP%Ie zeFaQs$DW8dk4Gyyh$0WEksAlJy zz!|WU*iZibC9uRWW{@eyQBHx0qIYgR7+H00G=vGag;AWf?)1QsrGs0=(CY3!6b$bx zeEcfT$mTf4A+!GdBm`U!;q7;9I0Ez>65=n`_)h#!mO&(VbR>#vXXN~CIeq|>G=XVp zU|PyFE%VDhsaN!1s;2GCi#dEHfyOZ82j|;+#`DK>G>XO2_#Fj&QtUecyYd*d;N9bI z)q`_euwE^O{|zl36ja!uEUw#diSo8P)zPkDOg3~JQDpGIH94>K0h8j3v3^d6A`%C0 z?IVT4=mke|eMEm&`vAspGx4p77Ea^k?{S>n8jkAT3*oWR(Wr`0A!BN)o#L`EQdIGi z@(lYSZpU3uSn+iS#6%c6;^kJ^7dS7HO1lO=ibszf1+poCb0es2-k{gglqkJAqf}<0{@m4^1)C3kz1&E&SHKmGYDc8@O{GV z3EB$tCnNg_bVB%b#n-SYFcc`1tvNJa$aKWu%eWJTLA?YK4&qfG`%L=RtRG}Y@^}O; z2B%0FZ%m9#n)^)mPQID((*ZU2N1}yL8jQ0sZ2JkU#juU>L^Z4tE8%SdXM5qZI~{DO zc7>P0RFk=cuLf%FT?|;dq8o=8lcr4#ALdVn4b-Ng0)xg3+v}Zj?2dd)pDo9s66L=jSKnIm9 z6fg9nhgO#ASu9a_Q&!KfPf0u2@Hf-emKLk-2M;e+yN912P~1X48+-iCR@F+Ehp|5Q z-B&s;4;3a|z_<@3NpnO9YD1M0B_x(@h}ZT|x=V9Ne4{0!4Gxs>gGm2DIKQd;y&2ZpvU!Z|9MF*nT?(q-`6a5PTl)8Hf1Zoeb_`ASN@RcQO)$x^z#S*Jbgx z7f7A=pdJ61b#e^`#oA#S`9vY-GQEbRzCYyCPUG_U>YEb-JB7)P?;$?w!1~^s=%iYM z6Frn|s2H{R0z3eg;P=nn3V}&xz+%#0@S9D@h~WU()(p(L+{mKr2fb77lF%x_`xrKbl-Lc@ z^W8ln0`L=^fq5VR`mEI*hnC-4t6dCL{j>Oh)CX_s&vz4mXE$MOZo-l>OwUj4eyFEP z2TJ&@$j1fv7LkwQg$Bop=H06W_xdhU$d*XF7lNb(d`!o~nW568o=I~{x8Hh(UI>qa{eNz!WFz}+r{63KX$YSG55`%U3iHJs z+fN;8$wVkq{IEG_^{UuINvTU6 zsm3W?9#zgeYn?hiNJ%e2`Sz-xjV#Na`hKgZd#MrjlP!EL$rFDr=tAVZ9ej^QBBcQ) zb&?Ohx?-~2#kbPj&-A{kEAGI`K}DpC-F!H9;REk^tTOk+V{=bEIsdpY=;d+MMI7Fa zubc9Vo}O=@SMOrkd-zi3J#M?xM&IS6DQFzz<5)O*Ij_1D-n+;7$`J;#$d?$qm%+yv z{3!+^)O?DuKaIdohv$Mm#UwINuFZ5DZ?TNC;UHC_?^T*U+1yrOnZlt6fl3h>B$I*&@&bf6{)Rlj3)Qbwr7Ap8R8fGbviN=9>Fyb= zR>nLsyM6lH`<(OLzwfx?<0S*X7mxmO_1?T;{4*6se|Z#M#S?sF8pahv7&Swf!fKl} zliya&;&-NIwK2};+vU!9ZJhIk_C#m0 zHp%%S@>8`b^^O9-QkhCnbU@NLhQL_)t(VgioJM0 zEB1+5ypPDj+EMx3sv-7&Xl|KJ3*|X3A4tm;E+34`MJ^rErKVjwhVMKdKgaQ&#VYKz z6SNv$=@g|{*Hc(mRh|^i9ZNhd4&SnCr{sRQUp#~Iv*HNKpP|vxkuQj&cQWERF^9Sr zAF8W}W2pP=>xOt<9KU6V<8pc{Q+o;J6QYW8RlbDs%P5}|r%*m6$5H+q%AXN0p!|aT zoSfXUYo8a^Wux+9|JE5Na6Pf&-*npUhEz^?%?%yt1wADLr{@K3Q#yWEDmQHTUf?ub z&+|iPMLMW!`l=&EwR9zr&0gENaZP#{FP%_!x@|XQ+W@$z@45g|!Te2*o*(-~e&zwJ3KYwL$Vd=uf z#rm10rArrHyRvldaP>|WMtS5KzK~I&fsN}bnYL)P_yM0wG|)|H4dUB4UUl_UcqN6KBIXZGrjP_RYx>SLTaxE{ADva#F zN1DU=QOAQcuBZ;v#3enrEt{d9;3(JXo?M%LpG!0r+wem`I~uQddZD}0CcKc1iWS+e zS`BEIVNZDtbWML2ayFjV@dR^7LStZj-`F%ma{y8gt#w;H8)gJ@KQ@H*L1xSR9$G*c znf_a69OZheKxQHcp#5{9vno9z1gTpB=SC~M=D1E|tIiS#CLzI zGWdE_Og|NkUj!7IZU2TwVoM#zzN3utR_`0?MdUxaurPlW6sv-(o|NtG)w42K5B=`d zD;MzpWfx})T5nu^qqTB1z`{>--Nw4RDub(QEpN?z;bgqnYIg&O0rpVmg}g;)JcY!t z3s%{*=mEA zGz^tK0@`x&qkI+*AHhE%LpU0mYu1*fW(Q`Nxo)Um2;ijm^SH%E%W2&byo`4??ePQd zkwg2^0OEYzibwY2k$KEpz*B5y(8r@$n{vc}ex;vIAklpIN33%tV)mlYv}$CXFc$ zAS4@MfKM#Zl=$yyp%yPy4kbm5f;@Vj&~bkGTbH#Am10DqR9iuv=_B31GR+HCtW-+~ z>BXq~$}6vE*{JEOnlOV_rway(A@$@$>gi1UaT>T|>s%138R8SAOk`dA}Pv- z=o>`k^DzxmH${9RD!s|1%oV$+!ltfKVF7eZmC^W;avO35?1ziR^CTH{%fnyYAIsR+ z&n=$2bY|(|rBN}Pzvc#XZt66BBk8(u@zTXBOBWW;jdWFCq#jSllbyNz_ToZ)$0_=F_6FUMYK+m9x#3+}|f|)bR<`mKr=l7U4%2c~2ZUYO=6i}<) z#E8Zy=O8Xa4|5JJ-Od`{ICRz8v^F!4aK?amh&?a|;31Y_f~md(b)HzO`>#Za57AEJ znk3N!bO#Bhc;HDuQ8DXbtoj-8 zEPBjgW%1sVw>W}z9~IA`wel`lPwg0Z$y_wElkjuN#u`y=f!re^6k_&52sS|KUAwhT zavVyvT6yiI0#Hh}q8w(ISlz9A(1^dMk}K zR65w8vCwC=VPri{$K6N-vtEo=GwGAi{^{#_iLhN;9SKX<)$2+bC8k!XA_6rAb^x2s zSf$%&$N<`ZLjSba)Ix>=gk`0@p!@`6gc92n60CP#-fYY-KV+B^Q{cIj+X}!I9Op~^ z4YIu)2yEZ+F+UFRW^;2eIpp(kz985dSyUvmE5#@ab}dy@s6#Dl zh4nhyH!$Jb{tC`tT|uwNZuqc{#zwZRzDo6_;T~ZY*kpR}4pa@T_u*xz*BMhWE17DF zEDLoN$-m*z%+{O+vn`wbgF8`OHCfdC5%wNsue`bL@C19146M6g z%=gUhG#SXGK9qUy?%SV4%#dWj4#FMa3KZPfLIVb|P7y2njAUe7r6fZJGjt6t^GGw^ zMlg=^6(Dkq9l-7OaHz(AnvFFvLTYV`lQ;!l2T(ddJxoSk&_WGZLszw~lkpDhzCi>{ zSbj|_xI7c&Ukg@8x<29-j~FAdoj`*Vx$LZLJT%cfnH%%VJ1T!LN@6`&6ApbiGV36S zH*o%};{kLo<%epeq$1-(iWH!R?Z(A_qF2EBVZMKKN91^9NTR&5T|TN>Qa)8JXHkH8 z$DZM>Om`3GA-uOTj2(9WUlvGrj8(^n!3pl0*v(bvwT%>-N#zib+knNm(DT~hoEQXf z0&+qFIX+))Z!gDul@5{>TIPWYBUZgupI9sS+SxU@T!4ORSah8)I&4Vd8#F!r)aP&*=WAmlz2G9quS&S4LWT1jf^HkYrjpZ7wr+x^ zw5Oo3=RyC-CqgV4Q^`ho?1FrfQ9*lUeHGc{B!fSw1%9lloE!?tkMb#%li>y421?&& z3^D_l?hxT-|36??YgE@f7oI84RS=2bbZ&??T0r2;#pdoPCuSZOENeTHj)-|cg5^Zk z@+Kr2L62-g=|aoZ)_-DEBp*p^Z}{5M^M;=pcDNvMM9x`?-cuE=Zd^%ho!$r|uB zx-d_Yi4s{$tASq#k})7v04BGXpLbrUzMM`EUrrq-01%nq``?3wC&gKW-t8(&3Bf!2W5jQY{QPHT%) zd(YBke8-|$)_A?bdY=eB)1SNCTL~I)zCj$OBA5d-LE_2Ms`TQ0?cj)P3dK~$q9Qq9 z*tZ;wz2Wc=$@*DlZqzJByK)EY?9(Nb@Z&mL5FCMx<}*6tRPi&3W83AbYb@ndqiJA?xiTQF=3TGJFB3%XO;%vlx;R(g}$ zrGR_^4wwFc9q}ZdEWwgusvtayCd6yYcoPtY9SQT zph6qa259tZiU0r|0QfSafj!6o4eSA2I6#Bn9N3HkggzEpGO9bsa7|8wpYm&Y%BMj8 z&Zh)AP=d52iKx;;icPw4=G4HP1g`8b2bVt9L0s<`1qb0X+6dw4B@1IHJr`AgGpQ69 zFVqI|sz=FnO8S%#DyVN#GC-2>Wmbj0O|=AawMogte3@sQCvYD?BY~U1OX-wZW+2HnaHMKdaiw&33VU*38n0N=ylr&5z7cZOLbxXwy|Zthhs+1%)0fS z$?XM}hS(}}bg7fw0gb5-*!c;*1c(VBY4?V?s2KgUxILmLSg z?a3Rd?vMF_8F&Qr+a&l$l#&J?gbzIjo(GK-!`WP{jEEA$q431&7|Fb4cwc>Lpjaj8 zY8@B;12T%>vByHW55ga6Xz;M6oU;2Nl_FM`)4PmH`b~RVR9gTYl--=A< z-I?p>HLxoR(AS&=$jqGSBr1?UPW5b~+c=v#+3mG)DD=ZmL;kWuP?I?b>Nz3YK#E1d9SE|Xihbfl5>Q!3fYe=G9 zuW5h%NPOkHR1dB|D~EI82K8N_gxs^y-r9)y8Ah2i-i9Km zC;A!jfT*ZX0G5<`4`qE4zePFrXb`La8Xd)9WQ-hS@&nr{d~9WGizG7gW+?-CZ52>< zCi~B(3m6TrZ95p)Mu+MbRU|R4EUIA@-YEjE1h)ko7xaI)j0);j_%l z;akE?m27SQV>ZK1rQfISKcFN<-R%0&iN9B6`ou1p)k|xU6>%wo;>$PH#sF2#0+KcI-8TM8XMeMbsJZ}F;(YhWLa7zJn ziyW@0+(4r**n6hFPXp|;2q`h5A|i+#Q|Mj&9<@x?>wF1G-$=qbFg%Ddo?O*Vwj%V{ zKAe}h>Oz+ia4Cq(mr?#2%Ir^z>=oZ{YjuNyJH!h+PjD6qaJ*#ahy|p7|8;x<`H$yz z&rHr(v$?&+X@m#ukIQ3wOVj4W$K_dPW~OwwY9%8+QZ(a33>al*!1QK3O~Ne{Y{4zE ztjuwm7uFq{LmALm5Xva9GrvfhOLXu;Cyw&%gbMwCe2abd2_JpLcfY*TsAY2FJHlsn zt^MZkD|A|69CmBOcgqlKWYd1fXd|Nf6l#Q=TLxtD0+O*@T&CC~KCuB$0XYI`ir7W8 zbKq*b4^9c3SAz&V`B9#DS_V(xAR)K$U3Q6*svXSm%?aotLl^1dc@XK>(N*KrBIQ;o zVGLkgU^E~F_m5MmgLVqOfASO0{LyO!l@imU`XSB#hm`ygB}6t%A)3Aago>5tLO_^9W8cgFr)Y6-k0qk}(Q5LajI~rg14J^T4qJ;Thk8EOI&9 zgq?%BlEyzOK^fC3m|YuV{3`?h3hI4)Vv(-QAUeYmSF>Xa)ya>bLJKC(Zcw;qZRXxN#ASP=oEz9pD9Y+DF)a)yIOpa1+m^il0%E ziijxNY^eY@_YklTwP}%umP3Y7WVS|7h)`Ki&inpzIx2Em8JRL0UN&U+)TpU7JTzJn z52}oB$Knz#W{AZEgjfJvrW>Dhnc5KVD8P% zf|D|eJ%Z!tWxR?fAVHAexV|i*eiv21qV3BaQq+*Vsq5d;7wPy5CJ(KALDOd&Rjj2& zIp~Slgcfvpa)nTdAvV_VaS4KNy9J6cT@n63p`x$>L{`AcR+Nj!5NXy*9lq5{N`uPN z5ZZ1uHWJ@dbhJ@v7!+hxqLx=Wo~dZlEbO8@xp%(mD)lE+MeP=3ER~KJyV=O@R{?PHWZW6#{m!f+PpUoBqfr#D7r8%ke^s$vq%XzYsx#gGD6H}8@<1mV=9;Qh`INg)`F-6p!ytr+t9D>o-CsZE*WbI_ z8XWA`@Z6pH&&JdlP5U=B($5SUKf&w2G&GHA6^-f4aP*2Ue~n58zZoan$W?MW^<|yD zM!u3qJ;(Z-LZetI%6i`EZ;h(=OHnSeOQ4)jQ7$tRlnW`!1iJ#t#S~?dT?OS*igJxjfpS@5qTNoj z8MMu$JN{TYa%Aic9D7V;cP_CvZ^Xv{N*Ca*p=`J|%5&Ia_snoc8 z>=RI?Q78j-Tfj_(gt+U*;yC z;8*x0zsj%iX?}xG@fm)d>svQd?;Ps%mQ(L7)akvQdgoD}XAj;?SMD%lS(|;>zW1}1 z?F4hSYX-d0bgY1*;s?Ij@;NhK*ukb5Y;tpL&Gy&UOs~m>6?mfjj&%9ytR7~pS{*-q zPg{)|7w>eC(JVf58DF2w9-MhcS&A+q8j9d-7X3#|%V^oA$ayyJHF4syS%;rpH+M9W5ZTDBfys zby1*JDK6fBxwx?U%;&;ibvbvMt6y+`JMfyT&mQCdD=V;SR$$jxpV+lk-wya()2eS< z8{A*rvfVA~&MnEWa&tEc@SpYRznm)s7tV@&_i{4QykwTj_Z=+Mtg2?lh?P2*Or;) zG_!YX-zK)#cF~2kp%LYMkh6y3{4mz;#5ydoCM(o-$1x~|Jc9Zm7G}~2187B{zcvOm z=!9;44#phA#YjCD`uj~h<+AB}Em7xnkMV^CQ%Y8KQTMBBwA%xFRoZP{`(DncLG(y9 zHog6^3+Ag=`xC$4AB`os}#&;1!e>@`3OyO8NlGflDN!aurSbt^_E*-Si^X$ zS>Ox%tA{H3QG|d0@6;`;?2sJM+u3`PK;gAxYN{EVs@@j^x!% z!3LDj6e}(z0vi&fZ$}G^R5unFiK{*L#NJNtfc(aqS!)GyXCAgEBzEBec3F%bg=a|O zNw#(?L1c*2G$)T@HWOyxij*eyR(-;`r|)T7+Ky7Iai~>F_ahebmp1uJ=)7w+c-e$2 zS#LSYJfa~DFuukmZ@p$d;Fp(Y0cF0YY6D1_|o2xlqefuaSoNicRn|UwXX>xAS z`W;#*RSy2t+%x0R=JBeR%<33=K;2*{JMfgW1;#i7%Dd&;a$|7nc?HLRYlt!8_d!3a zoKi{3NDcf5gOrV*5M=L1d!a+3_{~94(4uB9LC66=rWhQr#iR)2%AEp;`~}GXQlhb) zhECoh=J;N#iMW~;k?ig6Ar4G*ycgXk#zLdf^c>-CVg%`LA9680WuBw``{FFgI|-@j z_(T1V5<#C7=Sk2MxZ;QENw^`Ep#a|^i!<8C#X{F}dHLyaA&^F`V&OQRTtNM32o#a9vzKZ`PFDaD*>Jp z7kdKl;N2HJ0Y9=3eU69O17$x+wz^L1*eQ$@2aaZL2gb#o7*~+e9S?EkXhy0Gh%&?H zDTJ51AxzSVbLfqulXq4sf-ZlJmM#;{$2~Da18g_o8_0YTuYR-+ASF79?}Zu6=@DY1 z72ByzO!VBup%DA1H)wO+@vPu@#4+BS9N!gjq!zT^>lEI}Zg>;3r|g25{#yT&{%09% z+t<4wj`I}dRN?yS7EUSUStHE&fe7=qFCAhJT(bYS2`)oS{n)sqFOPAFt5}|JNoo&V zvj2A}Tr=HpB}#fozEfSemG(|xkL_-NQ&Qg~tgdKOcvhqTkb*PY6HY9?K;JT6)3Ho% zFCPP_VKtjTWX>=f9+U_5@@xP+;P1dt(ab^}CSa*+m6Z+lc(h7SAK(sk`untLj%1;*}_ zuF>Cj2$##+ZA2>Ro_>8SWS>88aU}L-b2+LZehHo&Q+&znVABdD8Ao2BvQ$bW9<5LY z?Ql0NRjV63KyRa34U0=J>s+R`U3WhyV@3SoztYx7XSA%L7xaF8Kra~LHrnyQG$)h( zV~(aOmh7oqL2v(eKQ(vFNcWo_T&GWm9y%lW$j{9NZ+HU9H)DeP=-PzGws6$KAw%w4 z&HRva;kxIQtpEmw6N}9E=sOmYa|(@}c^~1x1ap6a;PNzpB!c?ZWME#yk(E9H`ACL)0hvr*O287M)lnT>=YHL4B8pTB)#_%@aH>^0%4}LbiKr_wzwgA1!lmad5^rPKvXB_G{AgvI1U9rme%TbQNg!Yn1$VLnP!!<kmU?BdC-%U|-NSvU3o4+j#iky?#G5oS;&0-~p(k zZQREshtJ*(^VKTz>hNfV_^vbT3w9|~g?bQ{>Yn2u<;VHg7b*-X=)NGmtK>z?4eW-x zGr@KP+wnyoabR%eyKk1Ni$7ml{Oa-3FT+ymI#k|E2$M!-iI?)qP|!V{pqsBS^HXC3`!~FaakUv1RZAN!9Y;vEhxDalpKmlD#)6}3>6f?W%!dJM|xZ72?SY@)ZDPR z=(&M~+ZQ2qLp-LQCsce*#V@G%hKg^gSVmFFtt>6CET^ zk0NUn;O=3(2EBdyKxQ~MoEy!Jj*R9E{nQBF(`Xg&SHxc->MejaI5s%iKbpHxH1rSq K%j!M;{`EgvYWi#d literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/utils.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b19b60ab6a3e2c716221739571ff9f2e026d447e GIT binary patch literal 24847 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 literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/__pycache__/visitor.cpython-39.pyc b/UIKatabatic/Lib/site-packages/jinja2/__pycache__/visitor.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd68f432a38a401a8af87258672cd7ff4a63579c GIT binary patch literal 3910 zcma)9O>f-B8Rl@wU5b(%J8fOtNYH@`#MyqRKzeD5w6LLkR7kKfEX6^$3b-TA?20Qc zxt`%l)|NWSz4i|@1?-|1_b2qwKhXXHUW*3ExwoGByhH7Wv^G#;XO=S@zVm)Q&rob` zh7PWuzVr3q-C5IbM>bV!7@Rk{YnW-t05ie4+YK>VlOaZ-3h{JZy1Pz$efs#p!yVqwH7~R{R@x-l zfER~~KiJ*lSuT~?;ya^pszxd+l;j7e_Gz4t#!0F)7nux4st`QM3Z0v=ii;%Aw!&|q zx6}ECp>MOw>p)UWQ_Gi+!F@FI4m#y@84Pt*LwQ4g)+GDNlQ8<3*KJA<3j5XOgsC|=*uPMR#TSvft9JU`6kR%ll}MDk137n8KGs;};4iwath zT80a)c&~TQE{pEd1I0cgDeJhBTL;u~J3*Ot)rynI5j6dzw=Gph>9^fbW zB$Zas0mRqBm)@~{NDM4H6vqjQJQf)SJU$fJpf)gv`*b2v_Erp)es7?P=)#`fd@sn_ z=|hPXuX6P?F-08=VYRf9-d*-H?{)G__1e}#$j_8c;(CwXTp$#k7-*GbrceTorl3x5 z7h9i=2~c>~$l znEv&VMT%F(u*Sth=w(w2{;SR4$+9D?nxyKIABx#a zRm-`tFt@r6uFz3@n4~fy9~e!+d5y*4V%-(f^&PzRBQ#5Ej=RC8x0j8+)!7H~N`;<;O#3n5SAgJCTL-(}E4DfcO zwD<=&{{LVUge^ZY9F&^$lNjusXNDlyhT#I^i9=BFm*n?qt~dc_*g;Dw3dXeSFA`!to9n@^W{u4Lzg8lox zd*+?_zra*Dhu@+-q$5_LWKk-z*&iRxo)^HUw;ND#Ezja~!iu0Fov)he|09FhE8a;~K@@0J^~raQfJ)qRV_tB|h0N4qzu zTOc_Ft@1vl{Mn)>i!;Ik&p95vhi0h45X$h@O-*y{4J)#0;<$mcqLo_tlp4lvQ*G}3 z=HZ9Y_OCzO{$!`~arZ{OF0$Ea2wW?-P*w0y=S3dpsr~%0JYmJZN|!2lzy9F)6@9fC T`mpi5z};}0EO6iSuHF3~KGz4j literal 0 HcmV?d00001 diff --git a/UIKatabatic/Lib/site-packages/jinja2/_identifier.py b/UIKatabatic/Lib/site-packages/jinja2/_identifier.py new file mode 100644 index 00000000..928c1503 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/_identifier.py @@ -0,0 +1,6 @@ +import re + +# generated by scripts/generate_identifier_pattern.py +pattern = re.compile( + r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߽߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛࣓-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣ৾ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣૺ-૿ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఄా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഀ-ഃ഻഼ാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳷-᳹᷀-᷹᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꣿꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𐴤-𐽆𐴧-𐽐𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑄴𑅅𑅆𑅳𑆀-𑆂𑆳-𑇀𑇉-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌻𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑑞𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑠬-𑠺𑨁-𑨊𑨳-𑨹𑨻-𑨾𑩇𑩑-𑩛𑪊-𑪙𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𑴱-𑴶𑴺𑴼𑴽𑴿-𑵅𑵇𑶊-𑶎𑶐𑶑𑶓-𑶗𑻳-𑻶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 +) diff --git a/UIKatabatic/Lib/site-packages/jinja2/async_utils.py b/UIKatabatic/Lib/site-packages/jinja2/async_utils.py new file mode 100644 index 00000000..f0c14020 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/async_utils.py @@ -0,0 +1,99 @@ +import inspect +import typing as t +from functools import WRAPPER_ASSIGNMENTS +from functools import wraps + +from .utils import _PassArg +from .utils import pass_eval_context + +if t.TYPE_CHECKING: + import typing_extensions as te + +V = t.TypeVar("V") + + +def async_variant(normal_func): # type: ignore + def decorator(async_func): # type: ignore + pass_arg = _PassArg.from_obj(normal_func) + need_eval_context = pass_arg is None + + if pass_arg is _PassArg.environment: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].is_async) + + else: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].environment.is_async) + + # Take the doc and annotations from the sync function, but the + # name from the async function. Pallets-Sphinx-Themes + # build_function_directive expects __wrapped__ to point to the + # sync function. + async_func_attrs = ("__module__", "__name__", "__qualname__") + normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs)) + + @wraps(normal_func, assigned=normal_func_attrs) + @wraps(async_func, assigned=async_func_attrs, updated=()) + def wrapper(*args, **kwargs): # type: ignore + b = is_async(args) + + if need_eval_context: + args = args[1:] + + if b: + return async_func(*args, **kwargs) + + return normal_func(*args, **kwargs) + + if need_eval_context: + wrapper = pass_eval_context(wrapper) + + wrapper.jinja_async_variant = True # type: ignore[attr-defined] + return wrapper + + return decorator + + +_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)} + + +async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": + # Avoid a costly call to isawaitable + if type(value) in _common_primitives: + return t.cast("V", value) + + if inspect.isawaitable(value): + return await t.cast("t.Awaitable[V]", value) + + return value + + +class _IteratorToAsyncIterator(t.Generic[V]): + def __init__(self, iterator: "t.Iterator[V]"): + self._iterator = iterator + + def __aiter__(self) -> "te.Self": + return self + + async def __anext__(self) -> V: + try: + return next(self._iterator) + except StopIteration as e: + raise StopAsyncIteration(e.value) from e + + +def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + return iterable.__aiter__() + else: + return _IteratorToAsyncIterator(iter(iterable)) + + +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/UIKatabatic/Lib/site-packages/jinja2/bccache.py b/UIKatabatic/Lib/site-packages/jinja2/bccache.py new file mode 100644 index 00000000..ada8b099 --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/bccache.py @@ -0,0 +1,408 @@ +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" + +import errno +import fnmatch +import marshal +import os +import pickle +import stat +import sys +import tempfile +import typing as t +from hashlib import sha1 +from io import BytesIO +from types import CodeType + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + + class _MemcachedClient(te.Protocol): + def get(self, key: str) -> bytes: ... + + def set( + self, key: str, value: bytes, timeout: t.Optional[int] = None + ) -> None: ... + + +bc_version = 5 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket: + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment: "Environment", key: str, checksum: str) -> None: + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self) -> None: + """Resets the bucket (unloads the bytecode).""" + self.code: t.Optional[CodeType] = None + + def load_bytecode(self, f: t.BinaryIO) -> None: + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal.load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f: t.IO[bytes]) -> None: + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal.dump(self.code, f) + + def bytecode_from_string(self, string: bytes) -> None: + """Load bytecode from bytes.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self) -> bytes: + """Return the bytecode as bytes.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache: + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self) -> None: + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key( + self, name: str, filename: t.Optional[t.Union[str]] = None + ) -> str: + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + + if filename is not None: + hash.update(f"|{filename}".encode()) + + return hash.hexdigest() + + def get_source_checksum(self, source: str) -> str: + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket( + self, + environment: "Environment", + name: str, + filename: t.Optional[str], + source: str, + ) -> Bucket: + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket: Bucket) -> None: + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__( + self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" + ) -> None: + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self) -> str: + def _unsafe_dir() -> "te.NoReturn": + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = f"_jinja2-cache-{os.getuid()}" + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket: Bucket) -> str: + return os.path.join(self.directory, self.pattern % (bucket.key,)) + + def load_bytecode(self, bucket: Bucket) -> None: + filename = self._get_cache_filename(bucket) + + # Don't test for existence before opening the file, since the + # file could disappear after the test before the open. + try: + f = open(filename, "rb") + except (FileNotFoundError, IsADirectoryError, PermissionError): + # PermissionError can occur on Windows when an operation is + # in progress, such as calling clear(). + return + + with f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket: Bucket) -> None: + # Write to a temporary file, then rename to the real name after + # writing. This avoids another process reading the file before + # it is fully written. + name = self._get_cache_filename(bucket) + f = tempfile.NamedTemporaryFile( + mode="wb", + dir=os.path.dirname(name), + prefix=os.path.basename(name), + suffix=".tmp", + delete=False, + ) + + def remove_silent() -> None: + try: + os.remove(f.name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + pass + + try: + with f: + bucket.write_bytecode(f) + except BaseException: + remove_silent() + raise + + try: + os.replace(f.name, name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + remove_silent() + except BaseException: + remove_silent() + raise + + def clear(self) -> None: + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) + for filename in files: + try: + remove(os.path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only text. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client: "_MemcachedClient", + prefix: str = "jinja2/bytecode/", + timeout: t.Optional[int] = None, + ignore_memcache_errors: bool = True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket: Bucket) -> None: + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + else: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket: Bucket) -> None: + key = self.prefix + bucket.key + value = bucket.bytecode_to_string() + + try: + if self.timeout is not None: + self.client.set(key, value, self.timeout) + else: + self.client.set(key, value) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/UIKatabatic/Lib/site-packages/jinja2/compiler.py b/UIKatabatic/Lib/site-packages/jinja2/compiler.py new file mode 100644 index 00000000..a4ff6a1b --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/compiler.py @@ -0,0 +1,1998 @@ +"""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(new_func, f) # type: ignore[return-value] + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor + + +def generate( + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + + if stream is None: + return generator.stream.getvalue() # type: ignore + + return None + + +def has_safe_repr(value: t.Any) -> bool: + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + + if type(value) in {bool, int, float, complex, range, str, Markup}: + return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: # noqa E721 + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + + return False + + +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame: + """Holds compile time information for us.""" + + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: + self.eval_ctx = eval_ctx + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False + + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False + + def copy(self) -> "te.Self": + """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) -> "te.Self": + """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(sorted(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, sorted(public_names))) + self.writeline(f"context.exported_vars.update(({names_str}))") + + # -- Statement Visitors + + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> None: + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import async_exported + from .runtime import exported + + if self.environment.is_async: + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = "" if self.defer_init else ", environment=environment" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail(f"block {block.name!r} defined twice", block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline(f"from {module} import {obj} as {alias}") + else: + self.writeline(f"import {imp} as {alias}") + + # add the load name + self.writeline(f"name = {self.name!r}") + + # generate the root render function. + self.writeline( + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline("agen = parent_template.root_render_func(context)") + self.writeline("try:") + self.indent() + self.writeline("async for event in agen:") + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent() + self.writeline("finally: await agen.aclose()") + 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"gen = context.blocks[{node.name!r}][0]({context})") + self.writeline("try:") + self.indent() + self.writeline( + f"{self.choose_async()}for event in gen:", + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + + 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() + + def loop_body() -> None: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.with_context: + self.writeline( + f"gen = template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)}))" + ) + self.writeline("try:") + self.indent() + self.writeline(f"{self.choose_async()}for event in gen:") + loop_body() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + elif self.environment.is_async: + self.writeline( + "for event in (await template._get_default_module_async())" + "._body_stream:" + ) + loop_body() + else: + self.writeline("yield from template._get_default_module()._body_stream") + + 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() + # The position will contain the template name, and will be formatted + # into a string that will be compiled into an f-string. Curly braces + # in the name must be replaced with escapes so that they will not be + # executed as part of the f-string. + position = self.position(node).replace("{", "{{").replace("}", "}}") + message = ( + "the template {included_template.__name__!r}" + f" (imported on {position})" + 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() + + # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However, + # it is only valid if it references a Namespace object. Emit a check for + # that for each ref here, before assignment code is emitted. This can't + # be done in visit_NSRef as the ref could be in the middle of a tuple. + seen_refs: t.Set[str] = set() + + for nsref in node.find_all(nodes.NSRef): + if nsref.name in seen_refs: + # Only emit the check for each reference once, in case the same + # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`. + continue + + seen_refs.add(nsref.name) + ref = frame.symbols.ref(nsref.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.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: + # NSRef is a dotted assignment target a.b=c, but uses a[b]=c internally. + # visit_Assign emits code to validate that each ref is to a Namespace + # object only. That can't be emitted here as the ref could be in the + # middle of a tuple assignment. + ref = frame.symbols.ref(node.name) + 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/UIKatabatic/Lib/site-packages/jinja2/constants.py b/UIKatabatic/Lib/site-packages/jinja2/constants.py new file mode 100644 index 00000000..41a1c23b --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/jinja2/debug.py b/UIKatabatic/Lib/site-packages/jinja2/debug.py new file mode 100644 index 00000000..eeeeee78 --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/jinja2/defaults.py b/UIKatabatic/Lib/site-packages/jinja2/defaults.py new file mode 100644 index 00000000..638cad3d --- /dev/null +++ b/UIKatabatic/Lib/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/UIKatabatic/Lib/site-packages/jinja2/environment.py b/UIKatabatic/Lib/site-packages/jinja2/environment.py new file mode 100644 index 00000000..0fc6e5be --- /dev/null +++ b/UIKatabatic/Lib/site-packages/jinja2/environment.py @@ -0,0 +1,1672 @@ +"""Classes for managing templates and their runtime and compile time +options. +""" + +import os +import typing +import typing as t +import weakref +from collections import ChainMap +from functools import lru_cache +from functools import partial +from functools import reduce +from types import CodeType + +from markupsafe import Markup + +from . import nodes +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import Lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import _PassArg +from .utils import concat +from .utils import consume +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + +# for direct template usage we have up to ten living environments +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + env = cls(*args) + env.shared = True + return env + + +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Return the cache class for the given size.""" + if size == 0: + return None + + if size < 0: + return {} + + return LRUCache(size) # type: ignore + + +def copy_cache( + cache: t.Optional[t.MutableMapping[t.Any, t.Any]], +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: # noqa E721 + return {} + + return LRUCache(cache.capacity) # type: ignore + + +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated extensions. + """ + result = {} + + for extension in extensions: + if isinstance(extension, str): + extension = t.cast(t.Type["Extension"], import_string(extension)) + + result[extension.identifier] = extension(environment) + + return result + + +def _environment_config_check(environment: _env_bound) -> _env_bound: + """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 = missing, + ) -> "te.Self": + """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.5 + ``enable_async`` is applied correctly. + + .. versionchanged:: 3.1.2 + Added the ``newline_sequence``, ``keep_trailing_newline``, + and ``enable_async`` parameters to match ``__init__``. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"], args["enable_async"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in args.items(): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in self.extensions.items(): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + if enable_async is not missing: + rv.is_async = enable_async + + return _environment_config_check(rv) + + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) + + def iter_extensions(self) -> t.Iterator["Extension"]: + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, str): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj: t.Any, attribute: str) -> t.Any: + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a string. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" + + func = env_map.get(name) # type: ignore + + if func is None: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: + if context is None: + raise TemplateRuntimeError( + f"Attempted to invoke a context {type_name} without context." + ) + + args.insert(0, context) + elif pass_arg is _PassArg.eval_context: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if the filter is running from an + environment in async mode and the filter supports async + execution. It's your responsibility to await this if needed. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) + + @internalcode + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, filename).parse() + + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = str(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + str(source), + ) + + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) # type: ignore + + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + + return stream + + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( # type: ignore + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source: str, filename: str) -> CodeType: + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @typing.overload + def compile( + 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 = "