From 1aa8d8e15778365ef6c79e120f19ecda1ec3702b Mon Sep 17 00:00:00 2001 From: sairate Date: Sat, 31 Aug 2024 14:00:42 +0800 Subject: [PATCH] Signed-off-by: sairate --- .../Markdown-3.7.dist-info/INSTALLER | 1 + .../Markdown-3.7.dist-info/LICENSE.md | 30 + .../Markdown-3.7.dist-info/METADATA | 146 + .../Markdown-3.7.dist-info/RECORD | 74 + .../Markdown-3.7.dist-info/WHEEL | 5 + .../Markdown-3.7.dist-info/entry_points.txt | 22 + .../Markdown-3.7.dist-info/top_level.txt | 1 + .../MarkupSafe-2.1.5.dist-info/INSTALLER | 1 + .../MarkupSafe-2.1.5.dist-info/LICENSE.rst | 28 + .../MarkupSafe-2.1.5.dist-info/METADATA | 93 + .../MarkupSafe-2.1.5.dist-info/RECORD | 14 + .../MarkupSafe-2.1.5.dist-info/WHEEL | 5 + .../MarkupSafe-2.1.5.dist-info/top_level.txt | 1 + .../PyYAML-6.0.2.dist-info/INSTALLER | 1 + .../PyYAML-6.0.2.dist-info/LICENSE | 20 + .../PyYAML-6.0.2.dist-info/METADATA | 46 + .../PyYAML-6.0.2.dist-info/RECORD | 43 + .../PyYAML-6.0.2.dist-info/WHEEL | 5 + .../PyYAML-6.0.2.dist-info/top_level.txt | 2 + .../__pycache__/_virtualenv.cpython-312.pyc | Bin 0 -> 4220 bytes .../__pycache__/ghp_import.cpython-312.pyc | Bin 0 -> 14812 bytes .../__pycache__/six.cpython-312.pyc | Bin 0 -> 41160 bytes .../__pycache__/yaml_env_tag.cpython-312.pyc | Bin 0 -> 1972 bytes .venv/Lib/site-packages/_virtualenv.pth | 1 + .venv/Lib/site-packages/_virtualenv.py | 102 + .venv/Lib/site-packages/_yaml/__init__.py | 33 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 835 bytes .../click-8.1.7.dist-info/INSTALLER | 1 + .../click-8.1.7.dist-info/LICENSE.rst | 28 + .../click-8.1.7.dist-info/METADATA | 103 + .../click-8.1.7.dist-info/RECORD | 39 + .../site-packages/click-8.1.7.dist-info/WHEEL | 5 + .../click-8.1.7.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/click/__init__.py | 73 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2672 bytes .../click/__pycache__/_compat.cpython-312.pyc | Bin 0 -> 27416 bytes .../__pycache__/_termui_impl.cpython-312.pyc | Bin 0 -> 30527 bytes .../__pycache__/_textwrap.cpython-312.pyc | Bin 0 -> 2413 bytes .../__pycache__/_winconsole.cpython-312.pyc | Bin 0 -> 11952 bytes .../click/__pycache__/core.cpython-312.pyc | Bin 0 -> 135630 bytes .../__pycache__/decorators.cpython-312.pyc | Bin 0 -> 23945 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 14707 bytes .../__pycache__/formatting.cpython-312.pyc | Bin 0 -> 14032 bytes .../click/__pycache__/globals.cpython-312.pyc | Bin 0 -> 3092 bytes .../click/__pycache__/parser.cpython-312.pyc | Bin 0 -> 21450 bytes .../shell_completion.cpython-312.pyc | Bin 0 -> 22728 bytes .../click/__pycache__/termui.cpython-312.pyc | Bin 0 -> 32761 bytes .../click/__pycache__/testing.cpython-312.pyc | Bin 0 -> 24534 bytes .../click/__pycache__/types.cpython-312.pyc | Bin 0 -> 49387 bytes .../click/__pycache__/utils.cpython-312.pyc | Bin 0 -> 26264 bytes .venv/Lib/site-packages/click/_compat.py | 623 ++ .venv/Lib/site-packages/click/_termui_impl.py | 739 ++ .venv/Lib/site-packages/click/_textwrap.py | 49 + .venv/Lib/site-packages/click/_winconsole.py | 279 + .venv/Lib/site-packages/click/core.py | 3042 ++++++ .venv/Lib/site-packages/click/decorators.py | 561 ++ .venv/Lib/site-packages/click/exceptions.py | 288 + .venv/Lib/site-packages/click/formatting.py | 301 + .venv/Lib/site-packages/click/globals.py | 68 + .venv/Lib/site-packages/click/parser.py | 529 + .venv/Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 596 ++ .venv/Lib/site-packages/click/termui.py | 784 ++ .venv/Lib/site-packages/click/testing.py | 479 + .venv/Lib/site-packages/click/types.py | 1089 +++ .venv/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 + .venv/Lib/site-packages/colorama/__init__.py | 7 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 456 bytes .../colorama/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 3909 bytes .../__pycache__/ansitowin32.cpython-312.pyc | Bin 0 -> 16370 bytes .../__pycache__/initialise.cpython-312.pyc | Bin 0 -> 3514 bytes .../__pycache__/win32.cpython-312.pyc | Bin 0 -> 8096 bytes .../__pycache__/winterm.cpython-312.pyc | Bin 0 -> 9052 bytes .venv/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 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 162 bytes .../__pycache__/ansi_test.cpython-312.pyc | Bin 0 -> 5431 bytes .../ansitowin32_test.cpython-312.pyc | Bin 0 -> 18053 bytes .../initialise_test.cpython-312.pyc | Bin 0 -> 11717 bytes .../__pycache__/isatty_test.cpython-312.pyc | Bin 0 -> 4868 bytes .../tests/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2452 bytes .../__pycache__/winterm_test.cpython-312.pyc | Bin 0 -> 6576 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 + .venv/Lib/site-packages/colorama/win32.py | 180 + .venv/Lib/site-packages/colorama/winterm.py | 195 + .venv/Lib/site-packages/dateutil/__init__.py | 24 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1102 bytes .../__pycache__/_common.cpython-312.pyc | Bin 0 -> 1899 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 278 bytes .../__pycache__/easter.cpython-312.pyc | Bin 0 -> 2822 bytes .../__pycache__/relativedelta.cpython-312.pyc | Bin 0 -> 28312 bytes .../__pycache__/rrule.cpython-312.pyc | Bin 0 -> 68874 bytes .../__pycache__/tzwin.cpython-312.pyc | Bin 0 -> 181 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 2534 bytes .venv/Lib/site-packages/dateutil/_common.py | 43 + .venv/Lib/site-packages/dateutil/_version.py | 4 + .venv/Lib/site-packages/dateutil/easter.py | 89 + .../site-packages/dateutil/parser/__init__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2628 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 61766 bytes .../__pycache__/isoparser.cpython-312.pyc | Bin 0 -> 15552 bytes .../site-packages/dateutil/parser/_parser.py | 1613 ++++ .../dateutil/parser/isoparser.py | 416 + .../site-packages/dateutil/relativedelta.py | 599 ++ .venv/Lib/site-packages/dateutil/rrule.py | 1737 ++++ .../Lib/site-packages/dateutil/tz/__init__.py | 12 + .../tz/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 681 bytes .../tz/__pycache__/_common.cpython-312.pyc | Bin 0 -> 14124 bytes .../tz/__pycache__/_factories.cpython-312.pyc | Bin 0 -> 4567 bytes .../tz/__pycache__/tz.cpython-312.pyc | Bin 0 -> 65880 bytes .../tz/__pycache__/win.cpython-312.pyc | Bin 0 -> 17232 bytes .../Lib/site-packages/dateutil/tz/_common.py | 419 + .../site-packages/dateutil/tz/_factories.py | 80 + .venv/Lib/site-packages/dateutil/tz/tz.py | 1849 ++++ .venv/Lib/site-packages/dateutil/tz/win.py | 370 + .venv/Lib/site-packages/dateutil/tzwin.py | 2 + .venv/Lib/site-packages/dateutil/utils.py | 71 + .../dateutil/zoneinfo/__init__.py | 167 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7404 bytes .../__pycache__/rebuild.cpython-312.pyc | Bin 0 -> 3920 bytes .../zoneinfo/dateutil-zoneinfo.tar.gz | Bin 0 -> 156400 bytes .../dateutil/zoneinfo/rebuild.py | 75 + .../ghp_import-2.1.0.dist-info/INSTALLER | 1 + .../ghp_import-2.1.0.dist-info/LICENSE | 201 + .../ghp_import-2.1.0.dist-info/METADATA | 154 + .../ghp_import-2.1.0.dist-info/RECORD | 10 + .../ghp_import-2.1.0.dist-info/WHEEL | 5 + .../entry_points.txt | 3 + .../ghp_import-2.1.0.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/ghp_import.py | 306 + .../jinja2-3.1.4.dist-info/INSTALLER | 1 + .../jinja2-3.1.4.dist-info/LICENSE.txt | 28 + .../jinja2-3.1.4.dist-info/METADATA | 76 + .../jinja2-3.1.4.dist-info/RECORD | 57 + .../jinja2-3.1.4.dist-info/WHEEL | 4 + .../jinja2-3.1.4.dist-info/entry_points.txt | 3 + .venv/Lib/site-packages/jinja2/__init__.py | 38 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1623 bytes .../__pycache__/_identifier.cpython-312.pyc | Bin 0 -> 2104 bytes .../__pycache__/async_utils.cpython-312.pyc | Bin 0 -> 4053 bytes .../__pycache__/bccache.cpython-312.pyc | Bin 0 -> 19314 bytes .../__pycache__/compiler.cpython-312.pyc | Bin 0 -> 102235 bytes .../__pycache__/constants.cpython-312.pyc | Bin 0 -> 1526 bytes .../jinja2/__pycache__/debug.cpython-312.pyc | Bin 0 -> 6536 bytes .../__pycache__/defaults.cpython-312.pyc | Bin 0 -> 1576 bytes .../__pycache__/environment.cpython-312.pyc | Bin 0 -> 76670 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7685 bytes .../jinja2/__pycache__/ext.cpython-312.pyc | Bin 0 -> 41832 bytes .../__pycache__/filters.cpython-312.pyc | Bin 0 -> 71979 bytes .../__pycache__/idtracking.cpython-312.pyc | Bin 0 -> 19119 bytes .../jinja2/__pycache__/lexer.cpython-312.pyc | Bin 0 -> 31986 bytes .../__pycache__/loaders.cpython-312.pyc | Bin 0 -> 30940 bytes .../jinja2/__pycache__/meta.cpython-312.pyc | Bin 0 -> 5440 bytes .../__pycache__/nativetypes.cpython-312.pyc | Bin 0 -> 6981 bytes .../jinja2/__pycache__/nodes.cpython-312.pyc | Bin 0 -> 58179 bytes .../__pycache__/optimizer.cpython-312.pyc | Bin 0 -> 2659 bytes .../jinja2/__pycache__/parser.cpython-312.pyc | Bin 0 -> 60782 bytes .../__pycache__/runtime.cpython-312.pyc | Bin 0 -> 48449 bytes .../__pycache__/sandbox.cpython-312.pyc | Bin 0 -> 17860 bytes .../jinja2/__pycache__/tests.cpython-312.pyc | Bin 0 -> 9020 bytes .../jinja2/__pycache__/utils.cpython-312.pyc | Bin 0 -> 34468 bytes .../__pycache__/visitor.cpython-312.pyc | Bin 0 -> 5323 bytes .venv/Lib/site-packages/jinja2/_identifier.py | 6 + .venv/Lib/site-packages/jinja2/async_utils.py | 84 + .venv/Lib/site-packages/jinja2/bccache.py | 408 + .venv/Lib/site-packages/jinja2/compiler.py | 1960 ++++ .venv/Lib/site-packages/jinja2/constants.py | 20 + .venv/Lib/site-packages/jinja2/debug.py | 191 + .venv/Lib/site-packages/jinja2/defaults.py | 48 + .venv/Lib/site-packages/jinja2/environment.py | 1675 ++++ .venv/Lib/site-packages/jinja2/exceptions.py | 166 + .venv/Lib/site-packages/jinja2/ext.py | 870 ++ .venv/Lib/site-packages/jinja2/filters.py | 1866 ++++ .venv/Lib/site-packages/jinja2/idtracking.py | 318 + .venv/Lib/site-packages/jinja2/lexer.py | 868 ++ .venv/Lib/site-packages/jinja2/loaders.py | 667 ++ .venv/Lib/site-packages/jinja2/meta.py | 112 + .venv/Lib/site-packages/jinja2/nativetypes.py | 130 + .venv/Lib/site-packages/jinja2/nodes.py | 1206 +++ .venv/Lib/site-packages/jinja2/optimizer.py | 48 + .venv/Lib/site-packages/jinja2/parser.py | 1041 ++ .venv/Lib/site-packages/jinja2/py.typed | 0 .venv/Lib/site-packages/jinja2/runtime.py | 1056 ++ .venv/Lib/site-packages/jinja2/sandbox.py | 429 + .venv/Lib/site-packages/jinja2/tests.py | 256 + .venv/Lib/site-packages/jinja2/utils.py | 755 ++ .venv/Lib/site-packages/jinja2/visitor.py | 92 + .venv/Lib/site-packages/markdown/__init__.py | 48 + .venv/Lib/site-packages/markdown/__main__.py | 151 + .venv/Lib/site-packages/markdown/__meta__.py | 51 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1153 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 5428 bytes .../__pycache__/__meta__.cpython-312.pyc | Bin 0 -> 1107 bytes .../__pycache__/blockparser.cpython-312.pyc | Bin 0 -> 6384 bytes .../blockprocessors.cpython-312.pyc | Bin 0 -> 30333 bytes .../markdown/__pycache__/core.cpython-312.pyc | Bin 0 -> 22367 bytes .../__pycache__/htmlparser.cpython-312.pyc | Bin 0 -> 16596 bytes .../inlinepatterns.cpython-312.pyc | Bin 0 -> 45234 bytes .../postprocessors.cpython-312.pyc | Bin 0 -> 6499 bytes .../__pycache__/preprocessors.cpython-312.pyc | Bin 0 -> 3993 bytes .../__pycache__/serializers.cpython-312.pyc | Bin 0 -> 6304 bytes .../__pycache__/test_tools.cpython-312.pyc | Bin 0 -> 10605 bytes .../treeprocessors.cpython-312.pyc | Bin 0 -> 20879 bytes .../markdown/__pycache__/util.cpython-312.pyc | Bin 0 -> 16042 bytes .../Lib/site-packages/markdown/blockparser.py | 160 + .../site-packages/markdown/blockprocessors.py | 641 ++ .venv/Lib/site-packages/markdown/core.py | 503 + .../markdown/extensions/__init__.py | 145 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5227 bytes .../__pycache__/abbr.cpython-312.pyc | Bin 0 -> 10642 bytes .../__pycache__/admonition.cpython-312.pyc | Bin 0 -> 6876 bytes .../__pycache__/attr_list.cpython-312.pyc | Bin 0 -> 9220 bytes .../__pycache__/codehilite.cpython-312.pyc | Bin 0 -> 14606 bytes .../__pycache__/def_list.cpython-312.pyc | Bin 0 -> 5374 bytes .../__pycache__/extra.cpython-312.pyc | Bin 0 -> 2351 bytes .../__pycache__/fenced_code.cpython-312.pyc | Bin 0 -> 8755 bytes .../__pycache__/footnotes.cpython-312.pyc | Bin 0 -> 21557 bytes .../__pycache__/legacy_attrs.cpython-312.pyc | Bin 0 -> 3556 bytes .../__pycache__/legacy_em.cpython-312.pyc | Bin 0 -> 2489 bytes .../__pycache__/md_in_html.cpython-312.pyc | Bin 0 -> 18548 bytes .../__pycache__/meta.cpython-312.pyc | Bin 0 -> 3579 bytes .../__pycache__/nl2br.cpython-312.pyc | Bin 0 -> 1264 bytes .../__pycache__/sane_lists.cpython-312.pyc | Bin 0 -> 2874 bytes .../__pycache__/smarty.cpython-312.pyc | Bin 0 -> 8675 bytes .../__pycache__/tables.cpython-312.pyc | Bin 0 -> 10174 bytes .../__pycache__/toc.cpython-312.pyc | Bin 0 -> 22150 bytes .../__pycache__/wikilinks.cpython-312.pyc | Bin 0 -> 4775 bytes .../site-packages/markdown/extensions/abbr.py | 185 + .../markdown/extensions/admonition.py | 183 + .../markdown/extensions/attr_list.py | 203 + .../markdown/extensions/codehilite.py | 347 + .../markdown/extensions/def_list.py | 119 + .../markdown/extensions/extra.py | 66 + .../markdown/extensions/fenced_code.py | 193 + .../markdown/extensions/footnotes.py | 418 + .../markdown/extensions/legacy_attrs.py | 71 + .../markdown/extensions/legacy_em.py | 52 + .../markdown/extensions/md_in_html.py | 376 + .../site-packages/markdown/extensions/meta.py | 86 + .../markdown/extensions/nl2br.py | 41 + .../markdown/extensions/sane_lists.py | 69 + .../markdown/extensions/smarty.py | 277 + .../markdown/extensions/tables.py | 248 + .../site-packages/markdown/extensions/toc.py | 488 + .../markdown/extensions/wikilinks.py | 97 + .../Lib/site-packages/markdown/htmlparser.py | 347 + .../site-packages/markdown/inlinepatterns.py | 989 ++ .../site-packages/markdown/postprocessors.py | 143 + .../site-packages/markdown/preprocessors.py | 91 + .../Lib/site-packages/markdown/serializers.py | 194 + .../Lib/site-packages/markdown/test_tools.py | 224 + .../site-packages/markdown/treeprocessors.py | 476 + .venv/Lib/site-packages/markdown/util.py | 408 + .../Lib/site-packages/markupsafe/__init__.py | 332 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 17407 bytes .../__pycache__/_native.cpython-312.pyc | Bin 0 -> 2515 bytes .venv/Lib/site-packages/markupsafe/_native.py | 63 + .../Lib/site-packages/markupsafe/_speedups.c | 320 + .../markupsafe/_speedups.cp312-win_amd64.pyd | Bin 0 -> 15872 bytes .../site-packages/markupsafe/_speedups.pyi | 9 + .venv/Lib/site-packages/markupsafe/py.typed | 0 .../mergedeep-1.3.4.dist-info/INSTALLER | 1 + .../mergedeep-1.3.4.dist-info/LICENSE | 21 + .../mergedeep-1.3.4.dist-info/METADATA | 154 + .../mergedeep-1.3.4.dist-info/RECORD | 12 + .../mergedeep-1.3.4.dist-info/WHEEL | 5 + .../mergedeep-1.3.4.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/mergedeep/__init__.py | 5 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 294 bytes .../__pycache__/mergedeep.cpython-312.pyc | Bin 0 -> 4466 bytes .../test_mergedeep.cpython-312.pyc | Bin 0 -> 16281 bytes .../Lib/site-packages/mergedeep/mergedeep.py | 100 + .../site-packages/mergedeep/test_mergedeep.py | 397 + .../mkdocs-1.6.1.dist-info/INSTALLER | 1 + .../mkdocs-1.6.1.dist-info/METADATA | 143 + .../mkdocs-1.6.1.dist-info/RECORD | 212 + .../mkdocs-1.6.1.dist-info/REQUESTED | 0 .../mkdocs-1.6.1.dist-info/WHEEL | 4 + .../mkdocs-1.6.1.dist-info/entry_points.txt | 9 + .../mkdocs-1.6.1.dist-info/licenses/LICENSE | 26 + .venv/Lib/site-packages/mkdocs/__init__.py | 5 + .venv/Lib/site-packages/mkdocs/__main__.py | 370 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 182 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 18291 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 1948 bytes .../__pycache__/localization.cpython-312.pyc | Bin 0 -> 4209 bytes .../__pycache__/plugins.cpython-312.pyc | Bin 0 -> 32688 bytes .../mkdocs/__pycache__/theme.cpython-312.pyc | Bin 0 -> 8264 bytes .../site-packages/mkdocs/commands/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 163 bytes .../__pycache__/build.cpython-312.pyc | Bin 0 -> 17230 bytes .../__pycache__/gh_deploy.cpython-312.pyc | Bin 0 -> 7482 bytes .../commands/__pycache__/new.cpython-312.pyc | Bin 0 -> 2566 bytes .../__pycache__/serve.cpython-312.pyc | Bin 0 -> 4776 bytes .../site-packages/mkdocs/commands/build.py | 369 + .../mkdocs/commands/gh_deploy.py | 169 + .../Lib/site-packages/mkdocs/commands/new.py | 53 + .../site-packages/mkdocs/commands/serve.py | 112 + .../site-packages/mkdocs/config/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 272 bytes .../config/__pycache__/base.cpython-312.pyc | Bin 0 -> 19109 bytes .../config_options.cpython-312.pyc | Bin 0 -> 61435 bytes .../__pycache__/defaults.cpython-312.pyc | Bin 0 -> 8333 bytes .venv/Lib/site-packages/mkdocs/config/base.py | 392 + .../mkdocs/config/config_options.py | 1226 +++ .../site-packages/mkdocs/config/defaults.py | 218 + .../site-packages/mkdocs/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 162 bytes .../mkdocs/contrib/search/__init__.py | 120 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 8025 bytes .../__pycache__/search_index.cpython-312.pyc | Bin 0 -> 10556 bytes .../contrib/search/lunr-language/lunr.ar.js | 381 + .../contrib/search/lunr-language/lunr.da.js | 284 + .../contrib/search/lunr-language/lunr.de.js | 384 + .../contrib/search/lunr-language/lunr.du.js | 450 + .../contrib/search/lunr-language/lunr.es.js | 599 ++ .../contrib/search/lunr-language/lunr.fi.js | 541 ++ .../contrib/search/lunr-language/lunr.fr.js | 703 ++ .../contrib/search/lunr-language/lunr.hi.js | 123 + .../contrib/search/lunr-language/lunr.hu.js | 565 ++ .../contrib/search/lunr-language/lunr.hy.js | 98 + .../contrib/search/lunr-language/lunr.it.js | 617 ++ .../contrib/search/lunr-language/lunr.ja.js | 188 + .../contrib/search/lunr-language/lunr.jp.js | 5 + .../contrib/search/lunr-language/lunr.kn.js | 110 + .../contrib/search/lunr-language/lunr.ko.js | 114 + .../search/lunr-language/lunr.multi.js | 79 + .../contrib/search/lunr-language/lunr.nl.js | 448 + .../contrib/search/lunr-language/lunr.no.js | 258 + .../contrib/search/lunr-language/lunr.pt.js | 570 ++ .../contrib/search/lunr-language/lunr.ro.js | 558 ++ .../contrib/search/lunr-language/lunr.ru.js | 391 + .../contrib/search/lunr-language/lunr.sa.js | 110 + .../lunr-language/lunr.stemmer.support.js | 304 + .../contrib/search/lunr-language/lunr.sv.js | 256 + .../contrib/search/lunr-language/lunr.ta.js | 123 + .../contrib/search/lunr-language/lunr.te.js | 122 + .../contrib/search/lunr-language/lunr.th.js | 99 + .../contrib/search/lunr-language/lunr.tr.js | 1087 +++ .../contrib/search/lunr-language/lunr.vi.js | 84 + .../contrib/search/lunr-language/lunr.zh.js | 145 + .../contrib/search/lunr-language/tinyseg.js | 206 + .../mkdocs/contrib/search/prebuild-index.js | 56 + .../mkdocs/contrib/search/search_index.py | 225 + .../contrib/search/templates/search/lunr.js | 3475 +++++++ .../contrib/search/templates/search/main.js | 109 + .../contrib/search/templates/search/worker.js | 133 + .venv/Lib/site-packages/mkdocs/exceptions.py | 41 + .../mkdocs/livereload/__init__.py | 381 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 20574 bytes .../Lib/site-packages/mkdocs/localization.py | 92 + .venv/Lib/site-packages/mkdocs/plugins.py | 697 ++ .venv/Lib/site-packages/mkdocs/py.typed | 0 .../mkdocs/structure/__init__.py | 36 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1893 bytes .../__pycache__/files.cpython-312.pyc | Bin 0 -> 31323 bytes .../structure/__pycache__/nav.cpython-312.pyc | Bin 0 -> 11761 bytes .../__pycache__/pages.cpython-312.pyc | Bin 0 -> 26187 bytes .../structure/__pycache__/toc.cpython-312.pyc | Bin 0 -> 4358 bytes .../site-packages/mkdocs/structure/files.py | 626 ++ .../Lib/site-packages/mkdocs/structure/nav.py | 251 + .../site-packages/mkdocs/structure/pages.py | 569 ++ .../Lib/site-packages/mkdocs/structure/toc.py | 80 + .../mkdocs/templates/sitemap.xml | 11 + .venv/Lib/site-packages/mkdocs/theme.py | 166 + .../site-packages/mkdocs/themes/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 161 bytes .../mkdocs/themes/mkdocs/404.html | 12 + .../mkdocs/themes/mkdocs/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 168 bytes .../mkdocs/themes/mkdocs/base.html | 251 + .../mkdocs/themes/mkdocs/content.html | 9 + .../mkdocs/themes/mkdocs/css/base.css | 366 + .../themes/mkdocs/css/bootstrap.min.css | 12 + .../themes/mkdocs/css/bootstrap.min.css.map | 1 + .../mkdocs/themes/mkdocs/css/brands.min.css | 6 + .../themes/mkdocs/css/fontawesome.min.css | 9 + .../mkdocs/themes/mkdocs/css/solid.min.css | 6 + .../themes/mkdocs/css/v4-font-face.min.css | 6 + .../mkdocs/themes/mkdocs/img/favicon.ico | Bin 0 -> 1150 bytes .../mkdocs/themes/mkdocs/img/grid.png | Bin 0 -> 1458 bytes .../mkdocs/themes/mkdocs/js/base.js | 287 + .../themes/mkdocs/js/bootstrap.bundle.min.js | 7 + .../mkdocs/js/bootstrap.bundle.min.js.map | 1 + .../mkdocs/themes/mkdocs/js/darkmode.js | 65 + .../mkdocs/themes/mkdocs/keyboard-modal.html | 40 + .../mkdocs/locales/de/LC_MESSAGES/messages.mo | Bin 0 -> 1519 bytes .../mkdocs/locales/es/LC_MESSAGES/messages.mo | Bin 0 -> 1515 bytes .../mkdocs/locales/fa/LC_MESSAGES/messages.mo | Bin 0 -> 1619 bytes .../mkdocs/locales/fr/LC_MESSAGES/messages.mo | Bin 0 -> 1436 bytes .../mkdocs/locales/id/LC_MESSAGES/messages.mo | Bin 0 -> 1500 bytes .../mkdocs/locales/it/LC_MESSAGES/messages.mo | Bin 0 -> 1496 bytes .../mkdocs/locales/ja/LC_MESSAGES/messages.mo | Bin 0 -> 1548 bytes .../mkdocs/locales/nb/LC_MESSAGES/messages.mo | Bin 0 -> 1452 bytes .../mkdocs/locales/nl/LC_MESSAGES/messages.mo | Bin 0 -> 1459 bytes .../mkdocs/locales/nn/LC_MESSAGES/messages.mo | Bin 0 -> 1433 bytes .../mkdocs/locales/pl/LC_MESSAGES/messages.mo | Bin 0 -> 1572 bytes .../locales/pt_BR/LC_MESSAGES/messages.mo | Bin 0 -> 1503 bytes .../mkdocs/locales/ru/LC_MESSAGES/messages.mo | Bin 0 -> 1842 bytes .../mkdocs/locales/tr/LC_MESSAGES/messages.mo | Bin 0 -> 1455 bytes .../mkdocs/locales/uk/LC_MESSAGES/messages.mo | Bin 0 -> 1767 bytes .../locales/zh_CN/LC_MESSAGES/messages.mo | Bin 0 -> 1455 bytes .../locales/zh_TW/LC_MESSAGES/messages.mo | Bin 0 -> 1475 bytes .../mkdocs/themes/mkdocs/main.html | 10 + .../mkdocs/themes/mkdocs/mkdocs_theme.yml | 28 + .../mkdocs/themes/mkdocs/nav-sub.html | 14 + .../mkdocs/themes/mkdocs/search-modal.html | 21 + .../mkdocs/themes/mkdocs/toc.html | 26 + .../themes/mkdocs/webfonts/fa-brands-400.ttf | Bin 0 -> 207972 bytes .../mkdocs/webfonts/fa-brands-400.woff2 | Bin 0 -> 117372 bytes .../themes/mkdocs/webfonts/fa-regular-400.ttf | Bin 0 -> 68004 bytes .../mkdocs/webfonts/fa-regular-400.woff2 | Bin 0 -> 25452 bytes .../themes/mkdocs/webfonts/fa-solid-900.ttf | Bin 0 -> 419720 bytes .../themes/mkdocs/webfonts/fa-solid-900.woff2 | Bin 0 -> 156496 bytes .../mkdocs/webfonts/fa-v4compatibility.ttf | Bin 0 -> 10832 bytes .../mkdocs/webfonts/fa-v4compatibility.woff2 | Bin 0 -> 4792 bytes .../mkdocs/themes/readthedocs/404.html | 9 + .../mkdocs/themes/readthedocs/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 173 bytes .../mkdocs/themes/readthedocs/base.html | 199 + .../themes/readthedocs/breadcrumbs.html | 44 + .../css/fonts/Roboto-Slab-Bold.woff | Bin 0 -> 87624 bytes .../css/fonts/Roboto-Slab-Bold.woff2 | Bin 0 -> 67312 bytes .../css/fonts/Roboto-Slab-Regular.woff | Bin 0 -> 86288 bytes .../css/fonts/Roboto-Slab-Regular.woff2 | Bin 0 -> 66444 bytes .../css/fonts/fontawesome-webfont.eot | Bin 0 -> 165742 bytes .../css/fonts/fontawesome-webfont.svg | 2671 +++++ .../css/fonts/fontawesome-webfont.ttf | Bin 0 -> 165548 bytes .../css/fonts/fontawesome-webfont.woff | Bin 0 -> 98024 bytes .../css/fonts/fontawesome-webfont.woff2 | Bin 0 -> 77160 bytes .../css/fonts/lato-bold-italic.woff | Bin 0 -> 323344 bytes .../css/fonts/lato-bold-italic.woff2 | Bin 0 -> 193308 bytes .../readthedocs/css/fonts/lato-bold.woff | Bin 0 -> 309728 bytes .../readthedocs/css/fonts/lato-bold.woff2 | Bin 0 -> 184912 bytes .../css/fonts/lato-normal-italic.woff | Bin 0 -> 328412 bytes .../css/fonts/lato-normal-italic.woff2 | Bin 0 -> 195704 bytes .../readthedocs/css/fonts/lato-normal.woff | Bin 0 -> 309192 bytes .../readthedocs/css/fonts/lato-normal.woff2 | Bin 0 -> 182708 bytes .../mkdocs/themes/readthedocs/css/theme.css | 13 + .../themes/readthedocs/css/theme_extra.css | 197 + .../mkdocs/themes/readthedocs/footer.html | 26 + .../mkdocs/themes/readthedocs/img/favicon.ico | Bin 0 -> 1150 bytes .../themes/readthedocs/js/html5shiv.min.js | 4 + .../themes/readthedocs/js/jquery-3.6.0.min.js | 2 + .../mkdocs/themes/readthedocs/js/theme.js | 2 + .../themes/readthedocs/js/theme_extra.js | 8 + .../locales/de/LC_MESSAGES/messages.mo | Bin 0 -> 1528 bytes .../locales/es/LC_MESSAGES/messages.mo | Bin 0 -> 1570 bytes .../locales/fa/LC_MESSAGES/messages.mo | Bin 0 -> 1605 bytes .../locales/fr/LC_MESSAGES/messages.mo | Bin 0 -> 1542 bytes .../locales/id/LC_MESSAGES/messages.mo | Bin 0 -> 1498 bytes .../locales/it/LC_MESSAGES/messages.mo | Bin 0 -> 1548 bytes .../locales/ja/LC_MESSAGES/messages.mo | Bin 0 -> 1605 bytes .../locales/nl/LC_MESSAGES/messages.mo | Bin 0 -> 1518 bytes .../locales/pl/LC_MESSAGES/messages.mo | Bin 0 -> 1623 bytes .../locales/pt_BR/LC_MESSAGES/messages.mo | Bin 0 -> 1526 bytes .../locales/ru/LC_MESSAGES/messages.mo | Bin 0 -> 1867 bytes .../locales/tr/LC_MESSAGES/messages.mo | Bin 0 -> 1490 bytes .../locales/uk/LC_MESSAGES/messages.mo | Bin 0 -> 1822 bytes .../locales/zh_CN/LC_MESSAGES/messages.mo | Bin 0 -> 1477 bytes .../locales/zh_TW/LC_MESSAGES/messages.mo | Bin 0 -> 1475 bytes .../mkdocs/themes/readthedocs/main.html | 10 + .../themes/readthedocs/mkdocs_theme.yml | 25 + .../mkdocs/themes/readthedocs/nav.html | 22 + .../mkdocs/themes/readthedocs/search.html | 16 + .../mkdocs/themes/readthedocs/searchbox.html | 5 + .../mkdocs/themes/readthedocs/toc.html | 12 + .../mkdocs/themes/readthedocs/versions.html | 27 + .../site-packages/mkdocs/utils/__init__.py | 410 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19521 bytes .../__pycache__/babel_stub.cpython-312.pyc | Bin 0 -> 1979 bytes .../utils/__pycache__/cache.cpython-312.pyc | Bin 0 -> 1859 bytes .../utils/__pycache__/filters.cpython-312.pyc | Bin 0 -> 206 bytes .../utils/__pycache__/meta.cpython-312.pyc | Bin 0 -> 4390 bytes .../__pycache__/rendering.cpython-312.pyc | Bin 0 -> 5257 bytes .../__pycache__/templates.cpython-312.pyc | Bin 0 -> 2457 bytes .../utils/__pycache__/yaml.cpython-312.pyc | Bin 0 -> 8321 bytes .../site-packages/mkdocs/utils/babel_stub.py | 29 + .venv/Lib/site-packages/mkdocs/utils/cache.py | 36 + .../Lib/site-packages/mkdocs/utils/filters.py | 1 + .venv/Lib/site-packages/mkdocs/utils/meta.py | 100 + .../site-packages/mkdocs/utils/rendering.py | 104 + .../site-packages/mkdocs/utils/templates.py | 55 + .venv/Lib/site-packages/mkdocs/utils/yaml.py | 150 + .../mkdocs_get_deps-0.2.0.dist-info/INSTALLER | 1 + .../mkdocs_get_deps-0.2.0.dist-info/METADATA | 102 + .../mkdocs_get_deps-0.2.0.dist-info/RECORD | 16 + .../mkdocs_get_deps-0.2.0.dist-info/WHEEL | 4 + .../entry_points.txt | 2 + .../licenses/LICENSE.md | 21 + .../site-packages/mkdocs_get_deps/__init__.py | 211 + .../site-packages/mkdocs_get_deps/__main__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 10437 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 2916 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 4565 bytes .../__pycache__/yaml_util.cpython-312.pyc | Bin 0 -> 2743 bytes .../site-packages/mkdocs_get_deps/cache.py | 70 + .../site-packages/mkdocs_get_deps/py.typed | 0 .../mkdocs_get_deps/yaml_util.py | 50 + .../packaging-24.1.dist-info/INSTALLER | 1 + .../packaging-24.1.dist-info/LICENSE | 3 + .../packaging-24.1.dist-info/LICENSE.APACHE | 177 + .../packaging-24.1.dist-info/LICENSE.BSD | 23 + .../packaging-24.1.dist-info/METADATA | 102 + .../packaging-24.1.dist-info/RECORD | 36 + .../packaging-24.1.dist-info/WHEEL | 4 + .venv/Lib/site-packages/packaging/__init__.py | 15 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 522 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 0 -> 4931 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 9675 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 4519 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 13964 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3205 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 0 -> 7875 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 10968 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 24904 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 4374 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 38673 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 21306 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 7303 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19452 bytes .venv/Lib/site-packages/packaging/_elffile.py | 110 + .../Lib/site-packages/packaging/_manylinux.py | 262 + .../Lib/site-packages/packaging/_musllinux.py | 85 + .venv/Lib/site-packages/packaging/_parser.py | 354 + .../site-packages/packaging/_structures.py | 61 + .../Lib/site-packages/packaging/_tokenizer.py | 194 + .venv/Lib/site-packages/packaging/markers.py | 325 + .venv/Lib/site-packages/packaging/metadata.py | 804 ++ .venv/Lib/site-packages/packaging/py.typed | 0 .../site-packages/packaging/requirements.py | 91 + .../Lib/site-packages/packaging/specifiers.py | 1009 ++ .venv/Lib/site-packages/packaging/tags.py | 568 ++ .venv/Lib/site-packages/packaging/utils.py | 174 + .venv/Lib/site-packages/packaging/version.py | 563 ++ .../pathspec-0.12.1.dist-info/INSTALLER | 1 + .../pathspec-0.12.1.dist-info/LICENSE | 373 + .../pathspec-0.12.1.dist-info/METADATA | 647 ++ .../pathspec-0.12.1.dist-info/RECORD | 22 + .../pathspec-0.12.1.dist-info/WHEEL | 4 + .venv/Lib/site-packages/pathspec/__init__.py | 76 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1562 bytes .../__pycache__/_meta.cpython-312.pyc | Bin 0 -> 2334 bytes .../__pycache__/gitignore.cpython-312.pyc | Bin 0 -> 5420 bytes .../__pycache__/pathspec.cpython-312.pyc | Bin 0 -> 15815 bytes .../__pycache__/pattern.cpython-312.pyc | Bin 0 -> 7220 bytes .../pathspec/__pycache__/util.cpython-312.pyc | Bin 0 -> 26290 bytes .venv/Lib/site-packages/pathspec/_meta.py | 58 + .venv/Lib/site-packages/pathspec/gitignore.py | 157 + .venv/Lib/site-packages/pathspec/pathspec.py | 394 + .venv/Lib/site-packages/pathspec/pattern.py | 213 + .../pathspec/patterns/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 352 bytes .../__pycache__/gitwildmatch.cpython-312.pyc | Bin 0 -> 9645 bytes .../pathspec/patterns/gitwildmatch.py | 421 + .venv/Lib/site-packages/pathspec/py.typed | 1 + .venv/Lib/site-packages/pathspec/util.py | 792 ++ .../pip-23.2.1.dist-info/AUTHORS.txt | 738 ++ .../pip-23.2.1.dist-info/INSTALLER | 1 + .../pip-23.2.1.dist-info/LICENSE.txt | 20 + .../pip-23.2.1.dist-info/METADATA | 90 + .../site-packages/pip-23.2.1.dist-info/RECORD | 1063 ++ .../site-packages/pip-23.2.1.dist-info/WHEEL | 5 + .../pip-23.2.1.dist-info/entry_points.txt | 4 + .../pip-23.2.1.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/pip-23.2.1.virtualenv | 0 .venv/Lib/site-packages/pip/__init__.py | 13 + .venv/Lib/site-packages/pip/__main__.py | 24 + .venv/Lib/site-packages/pip/__pip-runner__.py | 50 + .../pip/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 662 bytes .../site-packages/pip/_internal/__init__.py | 19 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 822 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 0 -> 14230 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 12658 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 17346 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 33362 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 0 -> 4945 bytes .../self_outdated_check.cpython-312.pyc | Bin 0 -> 10071 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 0 -> 13687 bytes .../site-packages/pip/_internal/build_env.py | 311 + .../Lib/site-packages/pip/_internal/cache.py | 292 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 253 bytes .../autocompletion.cpython-312.pyc | Bin 0 -> 8376 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 0 -> 10419 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 0 -> 30311 bytes .../command_context.cpython-312.pyc | Bin 0 -> 1756 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 0 -> 2273 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 0 -> 4875 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 0 -> 15025 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 0 -> 2590 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 0 -> 18793 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 0 -> 7815 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 350 bytes .../pip/_internal/cli/autocompletion.py | 171 + .../pip/_internal/cli/base_command.py | 236 + .../pip/_internal/cli/cmdoptions.py | 1074 ++ .../pip/_internal/cli/command_context.py | 27 + .../site-packages/pip/_internal/cli/main.py | 79 + .../pip/_internal/cli/main_parser.py | 134 + .../site-packages/pip/_internal/cli/parser.py | 294 + .../pip/_internal/cli/progress_bars.py | 68 + .../pip/_internal/cli/req_command.py | 508 + .../pip/_internal/cli/spinners.py | 159 + .../pip/_internal/cli/status_codes.py | 6 + .../pip/_internal/commands/__init__.py | 132 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3977 bytes .../__pycache__/install.cpython-312.pyc | Bin 0 -> 28906 bytes .../pip/_internal/commands/cache.py | 222 + .../pip/_internal/commands/check.py | 54 + .../pip/_internal/commands/completion.py | 121 + .../pip/_internal/commands/configuration.py | 282 + .../pip/_internal/commands/debug.py | 199 + .../pip/_internal/commands/download.py | 147 + .../pip/_internal/commands/freeze.py | 108 + .../pip/_internal/commands/hash.py | 59 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/index.py | 139 + .../pip/_internal/commands/inspect.py | 92 + .../pip/_internal/commands/install.py | 778 ++ .../pip/_internal/commands/list.py | 368 + .../pip/_internal/commands/search.py | 174 + .../pip/_internal/commands/show.py | 189 + .../pip/_internal/commands/uninstall.py | 113 + .../pip/_internal/commands/wheel.py | 183 + .../pip/_internal/configuration.py | 381 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 916 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 2155 bytes .../__pycache__/installed.cpython-312.pyc | Bin 0 -> 1418 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 0 -> 8014 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1968 bytes .../pip/_internal/distributions/base.py | 39 + .../pip/_internal/distributions/installed.py | 23 + .../pip/_internal/distributions/sdist.py | 150 + .../pip/_internal/distributions/wheel.py | 34 + .../site-packages/pip/_internal/exceptions.py | 733 ++ .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 207 bytes .../__pycache__/collector.cpython-312.pyc | Bin 0 -> 21813 bytes .../package_finder.cpython-312.pyc | Bin 0 -> 40729 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 0 -> 9828 bytes .../pip/_internal/index/collector.py | 505 + .../pip/_internal/index/package_finder.py | 1029 ++ .../pip/_internal/index/sources.py | 223 + .../pip/_internal/locations/__init__.py | 467 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 16736 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 0 -> 7981 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3756 bytes .../pip/_internal/locations/_distutils.py | 173 + .../pip/_internal/locations/_sysconfig.py | 213 + .../pip/_internal/locations/base.py | 81 + .venv/Lib/site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 127 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5775 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 2840 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 0 -> 35055 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 0 -> 15090 bytes .../pip/_internal/metadata/_json.py | 84 + .../pip/_internal/metadata/base.py | 688 ++ .../_internal/metadata/importlib/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 305 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 3308 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 0 -> 13127 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 0 -> 11093 bytes .../_internal/metadata/importlib/_compat.py | 55 + .../_internal/metadata/importlib/_dists.py | 224 + .../pip/_internal/metadata/importlib/_envs.py | 188 + .../pip/_internal/metadata/pkg_resources.py | 270 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 241 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 0 -> 1898 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 0 -> 11200 bytes .../format_control.cpython-312.pyc | Bin 0 -> 4219 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 0 -> 1669 bytes .../installation_report.cpython-312.pyc | Bin 0 -> 2160 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 0 -> 26005 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 0 -> 1144 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 0 -> 5049 bytes .../selection_prefs.cpython-312.pyc | Bin 0 -> 1826 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 0 -> 4415 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5755 bytes .../pip/_internal/models/candidate.py | 34 + .../pip/_internal/models/direct_url.py | 237 + .../pip/_internal/models/format_control.py | 80 + .../pip/_internal/models/index.py | 28 + .../_internal/models/installation_report.py | 53 + .../pip/_internal/models/link.py | 581 ++ .../pip/_internal/models/scheme.py | 31 + .../pip/_internal/models/search_scope.py | 132 + .../pip/_internal/models/selection_prefs.py | 51 + .../pip/_internal/models/target_python.py | 110 + .../pip/_internal/models/wheel.py | 92 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 229 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 0 -> 21962 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 0 -> 4132 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 8542 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 0 -> 11620 bytes .../__pycache__/session.cpython-312.pyc | Bin 0 -> 18727 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2223 bytes .../pip/_internal/network/auth.py | 561 ++ .../pip/_internal/network/cache.py | 69 + .../pip/_internal/network/download.py | 186 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 519 + .../pip/_internal/network/utils.py | 96 + .../pip/_internal/network/xmlrpc.py | 60 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 172 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 7511 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 0 -> 25808 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 178 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 0 -> 7087 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 1855 bytes .../metadata_editable.cpython-312.pyc | Bin 0 -> 1889 bytes .../metadata_legacy.cpython-312.pyc | Bin 0 -> 3040 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1659 bytes .../wheel_editable.cpython-312.pyc | Bin 0 -> 2000 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 0 -> 3904 bytes .../operations/build/build_tracker.py | 124 + .../_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 | 187 + .../pip/_internal/operations/freeze.py | 255 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 241 bytes .../editable_legacy.cpython-312.pyc | Bin 0 -> 1792 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 33933 bytes .../operations/install/editable_legacy.py | 46 + .../pip/_internal/operations/install/wheel.py | 740 ++ .../pip/_internal/operations/prepare.py | 743 ++ .../site-packages/pip/_internal/pyproject.py | 179 + .../pip/_internal/req/__init__.py | 92 + .../req/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3708 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 0 -> 18809 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 0 -> 21168 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 0 -> 35942 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 0 -> 7181 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 0 -> 32958 bytes .../pip/_internal/req/constructors.py | 506 + .../pip/_internal/req/req_file.py | 552 ++ .../pip/_internal/req/req_install.py | 874 ++ .../pip/_internal/req/req_set.py | 119 + .../pip/_internal/req/req_uninstall.py | 650 ++ .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 172 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 1160 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../_internal/resolution/legacy/resolver.py | 600 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 183 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 8586 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 0 -> 27964 bytes .../__pycache__/factory.cpython-312.pyc | Bin 0 -> 28440 bytes .../found_candidates.cpython-312.pyc | Bin 0 -> 6168 bytes .../__pycache__/provider.cpython-312.pyc | Bin 0 -> 10346 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 0 -> 4905 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 10422 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 11371 bytes .../_internal/resolution/resolvelib/base.py | 141 + .../resolution/resolvelib/candidates.py | 555 ++ .../resolution/resolvelib/factory.py | 730 ++ .../resolution/resolvelib/found_candidates.py | 155 + .../resolution/resolvelib/provider.py | 255 + .../resolution/resolvelib/reporter.py | 80 + .../resolution/resolvelib/requirements.py | 165 + .../resolution/resolvelib/resolver.py | 299 + .../pip/_internal/self_outdated_check.py | 242 + .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 167 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 0 -> 4503 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 0 -> 1838 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 0 -> 2382 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 0 -> 2185 bytes .../compatibility_tags.cpython-312.pyc | Bin 0 -> 5528 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 0 -> 4158 bytes .../direct_url_helpers.cpython-312.pyc | Bin 0 -> 3535 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 0 -> 2890 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2120 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 0 -> 3960 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 0 -> 7410 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 0 -> 1136 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 0 -> 2314 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 0 -> 7487 bytes .../inject_securetransport.cpython-312.pyc | Bin 0 -> 1180 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13624 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 0 -> 32717 bytes .../utils/__pycache__/models.cpython-312.pyc | Bin 0 -> 2684 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 0 -> 2555 bytes .../setuptools_build.cpython-312.pyc | Bin 0 -> 4522 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 0 -> 8666 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 0 -> 10262 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 0 -> 11061 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 0 -> 2377 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 0 -> 4447 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5959 bytes .../pip/_internal/utils/_jaraco_text.py | 109 + .../site-packages/pip/_internal/utils/_log.py | 38 + .../pip/_internal/utils/appdirs.py | 52 + .../pip/_internal/utils/compat.py | 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/egg_link.py | 72 + .../pip/_internal/utils/encoding.py | 36 + .../pip/_internal/utils/entrypoints.py | 84 + .../pip/_internal/utils/filesystem.py | 153 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 88 + .../pip/_internal/utils/hashes.py | 151 + .../_internal/utils/inject_securetransport.py | 35 + .../pip/_internal/utils/logging.py | 348 + .../site-packages/pip/_internal/utils/misc.py | 735 ++ .../pip/_internal/utils/models.py | 39 + .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/setuptools_build.py | 146 + .../pip/_internal/utils/subprocess.py | 260 + .../pip/_internal/utils/temp_dir.py | 246 + .../pip/_internal/utils/unpacking.py | 257 + .../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-312.pyc | Bin 0 -> 506 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 0 -> 4989 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 0 -> 19094 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 0 -> 7574 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 0 -> 12454 bytes .../versioncontrol.cpython-312.pyc | Bin 0 -> 29056 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../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 | 355 + .../Lib/site-packages/pip/_vendor/__init__.py | 120 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4632 bytes .../pip/_vendor/cachecontrol/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 751 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 0 -> 5029 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 3215 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 897 bytes .../__pycache__/controller.cpython-312.pyc | Bin 0 -> 14609 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 0 -> 3924 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 0 -> 7237 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 0 -> 828 bytes .../pip/_vendor/cachecontrol/_cmd.py | 61 + .../pip/_vendor/cachecontrol/adapter.py | 137 + .../pip/_vendor/cachecontrol/cache.py | 65 + .../_vendor/cachecontrol/caches/__init__.py | 9 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 348 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 0 -> 7271 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 0 -> 2188 bytes .../_vendor/cachecontrol/caches/file_cache.py | 188 + .../cachecontrol/caches/redis_cache.py | 39 + .../pip/_vendor/cachecontrol/compat.py | 32 + .../pip/_vendor/cachecontrol/controller.py | 439 + .../pip/_vendor/cachecontrol/filewrapper.py | 111 + .../pip/_vendor/cachecontrol/heuristics.py | 139 + .../pip/_vendor/cachecontrol/serialize.py | 190 + .../pip/_vendor/cachecontrol/wrapper.py | 33 + .../pip/_vendor/certifi/__init__.py | 4 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 294 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 2825 bytes .../pip/_vendor/certifi/cacert.pem | 4589 +++++++++ .../site-packages/pip/_vendor/certifi/core.py | 108 + .../pip/_vendor/chardet/__init__.py | 115 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4532 bytes .../__pycache__/big5freq.cpython-312.pyc | Bin 0 -> 27175 bytes .../__pycache__/big5prober.cpython-312.pyc | Bin 0 -> 1363 bytes .../chardistribution.cpython-312.pyc | Bin 0 -> 9614 bytes .../charsetgroupprober.cpython-312.pyc | Bin 0 -> 4083 bytes .../__pycache__/charsetprober.cpython-312.pyc | Bin 0 -> 4984 bytes .../codingstatemachine.cpython-312.pyc | Bin 0 -> 3854 bytes .../codingstatemachinedict.cpython-312.pyc | Bin 0 -> 765 bytes .../__pycache__/cp949prober.cpython-312.pyc | Bin 0 -> 1372 bytes .../chardet/__pycache__/enums.cpython-312.pyc | Bin 0 -> 2972 bytes .../__pycache__/escprober.cpython-312.pyc | Bin 0 -> 4527 bytes .../chardet/__pycache__/escsm.cpython-312.pyc | Bin 0 -> 15286 bytes .../__pycache__/eucjpprober.cpython-312.pyc | Bin 0 -> 4352 bytes .../__pycache__/euckrfreq.cpython-312.pyc | Bin 0 -> 12058 bytes .../__pycache__/euckrprober.cpython-312.pyc | Bin 0 -> 1366 bytes .../__pycache__/euctwfreq.cpython-312.pyc | Bin 0 -> 27180 bytes .../__pycache__/euctwprober.cpython-312.pyc | Bin 0 -> 1366 bytes .../__pycache__/gb2312freq.cpython-312.pyc | Bin 0 -> 19102 bytes .../__pycache__/gb2312prober.cpython-312.pyc | Bin 0 -> 1379 bytes .../__pycache__/hebrewprober.cpython-312.pyc | Bin 0 -> 5793 bytes .../__pycache__/jisfreq.cpython-312.pyc | Bin 0 -> 22131 bytes .../__pycache__/johabfreq.cpython-312.pyc | Bin 0 -> 82979 bytes .../__pycache__/johabprober.cpython-312.pyc | Bin 0 -> 1370 bytes .../__pycache__/jpcntx.cpython-312.pyc | Bin 0 -> 39525 bytes .../langbulgarianmodel.cpython-312.pyc | Bin 0 -> 83098 bytes .../langgreekmodel.cpython-312.pyc | Bin 0 -> 76964 bytes .../langhebrewmodel.cpython-312.pyc | Bin 0 -> 77475 bytes .../langrussianmodel.cpython-312.pyc | Bin 0 -> 105227 bytes .../__pycache__/langthaimodel.cpython-312.pyc | Bin 0 -> 77653 bytes .../langturkishmodel.cpython-312.pyc | Bin 0 -> 77492 bytes .../__pycache__/latin1prober.cpython-312.pyc | Bin 0 -> 6973 bytes .../macromanprober.cpython-312.pyc | Bin 0 -> 7153 bytes .../mbcharsetprober.cpython-312.pyc | Bin 0 -> 3872 bytes .../mbcsgroupprober.cpython-312.pyc | Bin 0 -> 1564 bytes .../__pycache__/mbcssm.cpython-312.pyc | Bin 0 -> 38621 bytes .../__pycache__/resultdict.cpython-312.pyc | Bin 0 -> 608 bytes .../sbcharsetprober.cpython-312.pyc | Bin 0 -> 6358 bytes .../sbcsgroupprober.cpython-312.pyc | Bin 0 -> 2333 bytes .../__pycache__/sjisprober.cpython-312.pyc | Bin 0 -> 4464 bytes .../universaldetector.cpython-312.pyc | Bin 0 -> 12220 bytes .../__pycache__/utf1632prober.cpython-312.pyc | Bin 0 -> 9950 bytes .../__pycache__/utf8prober.cpython-312.pyc | Bin 0 -> 3146 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 464 bytes .../pip/_vendor/chardet/big5freq.py | 386 + .../pip/_vendor/chardet/big5prober.py | 47 + .../pip/_vendor/chardet/chardistribution.py | 261 + .../pip/_vendor/chardet/charsetgroupprober.py | 106 + .../pip/_vendor/chardet/charsetprober.py | 147 + .../pip/_vendor/chardet/cli/__init__.py | 0 .../pip/_vendor/chardet/cli/chardetect.py | 112 + .../pip/_vendor/chardet/codingstatemachine.py | 90 + .../_vendor/chardet/codingstatemachinedict.py | 19 + .../pip/_vendor/chardet/cp949prober.py | 49 + .../pip/_vendor/chardet/enums.py | 85 + .../pip/_vendor/chardet/escprober.py | 102 + .../pip/_vendor/chardet/escsm.py | 261 + .../pip/_vendor/chardet/eucjpprober.py | 102 + .../pip/_vendor/chardet/euckrfreq.py | 196 + .../pip/_vendor/chardet/euckrprober.py | 47 + .../pip/_vendor/chardet/euctwfreq.py | 388 + .../pip/_vendor/chardet/euctwprober.py | 47 + .../pip/_vendor/chardet/gb2312freq.py | 284 + .../pip/_vendor/chardet/gb2312prober.py | 47 + .../pip/_vendor/chardet/hebrewprober.py | 316 + .../pip/_vendor/chardet/jisfreq.py | 325 + .../pip/_vendor/chardet/johabfreq.py | 2382 +++++ .../pip/_vendor/chardet/johabprober.py | 47 + .../pip/_vendor/chardet/jpcntx.py | 238 + .../pip/_vendor/chardet/langbulgarianmodel.py | 4649 +++++++++ .../pip/_vendor/chardet/langgreekmodel.py | 4397 +++++++++ .../pip/_vendor/chardet/langhebrewmodel.py | 4380 +++++++++ .../pip/_vendor/chardet/langhungarianmodel.py | 4649 +++++++++ .../pip/_vendor/chardet/langrussianmodel.py | 5725 +++++++++++ .../pip/_vendor/chardet/langthaimodel.py | 4380 +++++++++ .../pip/_vendor/chardet/langturkishmodel.py | 4380 +++++++++ .../pip/_vendor/chardet/latin1prober.py | 147 + .../pip/_vendor/chardet/macromanprober.py | 162 + .../pip/_vendor/chardet/mbcharsetprober.py | 95 + .../pip/_vendor/chardet/mbcsgroupprober.py | 57 + .../pip/_vendor/chardet/mbcssm.py | 661 ++ .../pip/_vendor/chardet/metadata/__init__.py | 0 .../pip/_vendor/chardet/metadata/languages.py | 352 + .../pip/_vendor/chardet/resultdict.py | 16 + .../pip/_vendor/chardet/sbcharsetprober.py | 162 + .../pip/_vendor/chardet/sbcsgroupprober.py | 88 + .../pip/_vendor/chardet/sjisprober.py | 105 + .../pip/_vendor/chardet/universaldetector.py | 362 + .../pip/_vendor/chardet/utf1632prober.py | 225 + .../pip/_vendor/chardet/utf8prober.py | 82 + .../pip/_vendor/chardet/version.py | 9 + .../pip/_vendor/colorama/__init__.py | 7 + .../pip/_vendor/colorama/ansi.py | 102 + .../pip/_vendor/colorama/ansitowin32.py | 277 + .../pip/_vendor/colorama/initialise.py | 121 + .../pip/_vendor/colorama/tests/__init__.py | 1 + .../pip/_vendor/colorama/tests/ansi_test.py | 76 + .../colorama/tests/ansitowin32_test.py | 294 + .../_vendor/colorama/tests/initialise_test.py | 189 + .../pip/_vendor/colorama/tests/isatty_test.py | 57 + .../pip/_vendor/colorama/tests/utils.py | 49 + .../_vendor/colorama/tests/winterm_test.py | 131 + .../pip/_vendor/colorama/win32.py | 180 + .../pip/_vendor/colorama/winterm.py | 195 + .../pip/_vendor/distlib/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1241 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 45431 bytes .../__pycache__/resources.cpython-312.pyc | Bin 0 -> 17296 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 0 -> 19554 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 0 -> 87363 bytes .../pip/_vendor/distlib/compat.py | 1116 +++ .../pip/_vendor/distlib/database.py | 1350 +++ .../pip/_vendor/distlib/index.py | 508 + .../pip/_vendor/distlib/locators.py | 1300 +++ .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 152 + .../pip/_vendor/distlib/metadata.py | 1076 +++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 437 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 97792 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 182784 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 108032 bytes .../site-packages/pip/_vendor/distlib/util.py | 1932 ++++ .../pip/_vendor/distlib/version.py | 739 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 91648 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 168448 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 101888 bytes .../pip/_vendor/distlib/wheel.py | 1082 +++ .../pip/_vendor/distro/__init__.py | 54 + .../pip/_vendor/distro/__main__.py | 4 + .../pip/_vendor/distro/distro.py | 1399 +++ .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 857 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 16201 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 38358 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2609 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 192 bytes .../site-packages/pip/_vendor/idna/codec.py | 112 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 400 + .../pip/_vendor/idna/idnadata.py | 2151 +++++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../pip/_vendor/idna/uts46data.py | 8600 +++++++++++++++++ .../pip/_vendor/msgpack/__init__.py | 57 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1807 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 2001 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 0 -> 8644 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 0 -> 43520 bytes .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 193 + .../pip/_vendor/msgpack/fallback.py | 1010 ++ .../pip/_vendor/packaging/__about__.py | 26 + .../pip/_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-312.pyc | Bin 0 -> 606 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 442 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 12038 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 6872 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3217 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 14017 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 6919 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 31187 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 18826 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 5844 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19903 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/pkg_resources/__init__.py | 3361 +++++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 146203 bytes .../pip/_vendor/platformdirs/__init__.py | 566 ++ .../pip/_vendor/platformdirs/__main__.py | 53 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 18005 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 9648 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 287 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 12975 bytes .../pip/_vendor/platformdirs/android.py | 210 + .../pip/_vendor/platformdirs/api.py | 223 + .../pip/_vendor/platformdirs/macos.py | 91 + .../pip/_vendor/platformdirs/unix.py | 223 + .../pip/_vendor/platformdirs/version.py | 4 + .../pip/_vendor/platformdirs/windows.py | 255 + .../pip/_vendor/pygments/__init__.py | 82 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3465 bytes .../__pycache__/filter.cpython-312.pyc | Bin 0 -> 3204 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 38196 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 0 -> 1535 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 0 -> 3353 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 0 -> 4049 bytes .../__pycache__/style.cpython-312.pyc | Bin 0 -> 6627 bytes .../__pycache__/token.cpython-312.pyc | Bin 0 -> 8114 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 0 -> 13938 bytes .../pip/_vendor/pygments/cmdline.py | 668 ++ .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 71 + .../pip/_vendor/pygments/filters/__init__.py | 940 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 37841 bytes .../pip/_vendor/pygments/formatter.py | 124 + .../_vendor/pygments/formatters/__init__.py | 158 + .../_vendor/pygments/formatters/_mapping.py | 23 + .../pip/_vendor/pygments/formatters/bbcode.py | 108 + .../pip/_vendor/pygments/formatters/groff.py | 170 + .../pip/_vendor/pygments/formatters/html.py | 989 ++ .../pip/_vendor/pygments/formatters/img.py | 645 ++ .../pip/_vendor/pygments/formatters/irc.py | 154 + .../pip/_vendor/pygments/formatters/latex.py | 521 + .../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 | 943 ++ .../pip/_vendor/pygments/lexers/__init__.py | 362 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 14522 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 64381 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 559 ++ .../pip/_vendor/pygments/lexers/python.py | 1198 +++ .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 88 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 217 + .../pip/_vendor/pygments/style.py | 197 + .../pip/_vendor/pygments/styles/__init__.py | 103 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4415 bytes .../pip/_vendor/pygments/token.py | 213 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 330 + .../pip/_vendor/pyparsing/__init__.py | 322 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7888 bytes .../__pycache__/actions.cpython-312.pyc | Bin 0 -> 8365 bytes .../__pycache__/common.cpython-312.pyc | Bin 0 -> 13383 bytes .../__pycache__/core.cpython-312.pyc | Bin 0 -> 267477 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 12966 bytes .../__pycache__/helpers.cpython-312.pyc | Bin 0 -> 48440 bytes .../__pycache__/results.cpython-312.pyc | Bin 0 -> 34021 bytes .../__pycache__/testing.cpython-312.pyc | Bin 0 -> 17152 bytes .../__pycache__/unicode.cpython-312.pyc | Bin 0 -> 13151 bytes .../__pycache__/util.cpython-312.pyc | Bin 0 -> 14861 bytes .../pip/_vendor/pyparsing/actions.py | 217 + .../pip/_vendor/pyparsing/common.py | 432 + .../pip/_vendor/pyparsing/core.py | 6115 ++++++++++++ .../pip/_vendor/pyparsing/diagram/__init__.py | 656 ++ .../pip/_vendor/pyparsing/exceptions.py | 299 + .../pip/_vendor/pyparsing/helpers.py | 1100 +++ .../pip/_vendor/pyparsing/results.py | 796 ++ .../pip/_vendor/pyparsing/testing.py | 331 + .../pip/_vendor/pyparsing/unicode.py | 361 + .../pip/_vendor/pyparsing/util.py | 284 + .../pip/_vendor/pyproject_hooks/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 590 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 0 -> 14702 bytes .../pip/_vendor/pyproject_hooks/_compat.py | 8 + .../pip/_vendor/pyproject_hooks/_impl.py | 330 + .../pyproject_hooks/_in_process/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1057 bytes .../_in_process/_in_process.py | 353 + .../pip/_vendor/requests/__init__.py | 182 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5430 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 561 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2001 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 21247 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7181 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13898 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 899 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 1484 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25144 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7024 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1024 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35370 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 735 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27692 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 5926 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5594 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36179 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 50 + .../pip/_vendor/requests/adapters.py | 538 ++ .../site-packages/pip/_vendor/requests/api.py | 157 + .../pip/_vendor/requests/auth.py | 315 + .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/compat.py | 67 + .../pip/_vendor/requests/cookies.py | 561 ++ .../pip/_vendor/requests/exceptions.py | 141 + .../pip/_vendor/requests/help.py | 131 + .../pip/_vendor/requests/hooks.py | 33 + .../pip/_vendor/requests/models.py | 1034 ++ .../pip/_vendor/requests/packages.py | 16 + .../pip/_vendor/requests/sessions.py | 833 ++ .../pip/_vendor/requests/status_codes.py | 128 + .../pip/_vendor/requests/structures.py | 99 + .../pip/_vendor/requests/utils.py | 1094 +++ .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 611 bytes .../__pycache__/providers.cpython-312.pyc | Bin 0 -> 6828 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 0 -> 2631 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 0 -> 25825 bytes .../__pycache__/structs.cpython-312.pyc | Bin 0 -> 10463 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 177 bytes .../collections_abc.cpython-312.pyc | Bin 0 -> 397 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/reporters.py | 43 + .../pip/_vendor/resolvelib/resolvers.py | 547 ++ .../pip/_vendor/resolvelib/structs.py | 170 + .../pip/_vendor/rich/__init__.py | 177 + .../pip/_vendor/rich/__main__.py | 274 + .../rich/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6992 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 0 -> 7798 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 0 -> 205953 bytes .../_emoji_replace.cpython-312.pyc | Bin 0 -> 1706 bytes .../_export_format.cpython-312.pyc | Bin 0 -> 2298 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 0 -> 514 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 0 -> 832 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 0 -> 4124 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 0 -> 1847 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 0 -> 3597 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 0 -> 5137 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 0 -> 698 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 0 -> 6536 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 0 -> 13156 bytes .../_win32_console.cpython-312.pyc | Bin 0 -> 28953 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 0 -> 2467 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 0 -> 2327 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 0 -> 1585 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 0 -> 12264 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 9058 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 0 -> 11815 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 0 -> 5581 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 0 -> 26542 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 0 -> 1678 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 0 -> 8531 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 0 -> 113674 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 0 -> 2235 bytes .../__pycache__/containers.cpython-312.pyc | Bin 0 -> 9174 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 0 -> 10911 bytes .../default_styles.cpython-312.pyc | Bin 0 -> 10343 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 0 -> 4186 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1822 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 0 -> 3554 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 0 -> 3049 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 0 -> 9863 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 0 -> 5181 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 0 -> 19106 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 0 -> 4866 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13531 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 0 -> 9252 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 0 -> 6353 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 0 -> 7101 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 0 -> 1797 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 0 -> 5274 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 0 -> 12069 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 0 -> 40019 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 0 -> 75038 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 0 -> 10354 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1769 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 0 -> 544 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 0 -> 6592 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 0 -> 3802 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 0 -> 2456 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 0 -> 28081 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 0 -> 6041 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 0 -> 33471 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 0 -> 2116 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 0 -> 39555 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 0 -> 43492 bytes .../terminal_theme.cpython-312.pyc | Bin 0 -> 3325 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 0 -> 58832 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 0 -> 6317 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 0 -> 291 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 0 -> 31492 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/_export_format.py | 76 + .../pip/_vendor/rich/_extension.py | 10 + .../site-packages/pip/_vendor/rich/_fileno.py | 24 + .../pip/_vendor/rich/_inspect.py | 270 + .../pip/_vendor/rich/_log_render.py | 94 + .../site-packages/pip/_vendor/rich/_loop.py | 43 + .../pip/_vendor/rich/_null_file.py | 69 + .../pip/_vendor/rich/_palettes.py | 309 + .../site-packages/pip/_vendor/rich/_pick.py | 17 + .../site-packages/pip/_vendor/rich/_ratio.py | 160 + .../pip/_vendor/rich/_spinners.py | 482 + .../site-packages/pip/_vendor/rich/_stack.py | 16 + .../site-packages/pip/_vendor/rich/_timer.py | 19 + .../pip/_vendor/rich/_win32_console.py | 662 ++ .../pip/_vendor/rich/_windows.py | 72 + .../pip/_vendor/rich/_windows_renderer.py | 56 + .../site-packages/pip/_vendor/rich/_wrap.py | 56 + .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 311 + .../site-packages/pip/_vendor/rich/ansi.py | 240 + .../Lib/site-packages/pip/_vendor/rich/bar.py | 94 + .../Lib/site-packages/pip/_vendor/rich/box.py | 517 + .../site-packages/pip/_vendor/rich/cells.py | 154 + .../site-packages/pip/_vendor/rich/color.py | 622 ++ .../pip/_vendor/rich/color_triplet.py | 38 + .../site-packages/pip/_vendor/rich/columns.py | 187 + .../site-packages/pip/_vendor/rich/console.py | 2633 +++++ .../pip/_vendor/rich/constrain.py | 37 + .../pip/_vendor/rich/containers.py | 167 + .../site-packages/pip/_vendor/rich/control.py | 225 + .../pip/_vendor/rich/default_styles.py | 190 + .../pip/_vendor/rich/diagnose.py | 37 + .../site-packages/pip/_vendor/rich/emoji.py | 96 + .../site-packages/pip/_vendor/rich/errors.py | 34 + .../pip/_vendor/rich/file_proxy.py | 57 + .../pip/_vendor/rich/filesize.py | 89 + .../pip/_vendor/rich/highlighter.py | 232 + .../site-packages/pip/_vendor/rich/json.py | 140 + .../site-packages/pip/_vendor/rich/jupyter.py | 101 + .../site-packages/pip/_vendor/rich/layout.py | 443 + .../site-packages/pip/_vendor/rich/live.py | 375 + .../pip/_vendor/rich/live_render.py | 113 + .../site-packages/pip/_vendor/rich/logging.py | 289 + .../site-packages/pip/_vendor/rich/markup.py | 246 + .../site-packages/pip/_vendor/rich/measure.py | 151 + .../site-packages/pip/_vendor/rich/padding.py | 141 + .../site-packages/pip/_vendor/rich/pager.py | 34 + .../site-packages/pip/_vendor/rich/palette.py | 100 + .../site-packages/pip/_vendor/rich/panel.py | 308 + .../site-packages/pip/_vendor/rich/pretty.py | 994 ++ .../pip/_vendor/rich/progress.py | 1702 ++++ .../pip/_vendor/rich/progress_bar.py | 224 + .../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 | 149 + .../site-packages/pip/_vendor/rich/rule.py | 130 + .../site-packages/pip/_vendor/rich/scope.py | 86 + .../site-packages/pip/_vendor/rich/screen.py | 54 + .../site-packages/pip/_vendor/rich/segment.py | 739 ++ .../site-packages/pip/_vendor/rich/spinner.py | 137 + .../site-packages/pip/_vendor/rich/status.py | 132 + .../site-packages/pip/_vendor/rich/style.py | 796 ++ .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 948 ++ .../site-packages/pip/_vendor/rich/table.py | 1002 ++ .../pip/_vendor/rich/terminal_theme.py | 153 + .../site-packages/pip/_vendor/rich/text.py | 1307 +++ .../site-packages/pip/_vendor/rich/theme.py | 115 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 756 ++ .../site-packages/pip/_vendor/rich/tree.py | 251 + .venv/Lib/site-packages/pip/_vendor/six.py | 998 ++ .../pip/_vendor/tenacity/__init__.py | 608 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 27063 bytes .../__pycache__/_asyncio.cpython-312.pyc | Bin 0 -> 4783 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 0 -> 2292 bytes .../__pycache__/after.cpython-312.pyc | Bin 0 -> 1601 bytes .../__pycache__/before.cpython-312.pyc | Bin 0 -> 1441 bytes .../__pycache__/before_sleep.cpython-312.pyc | Bin 0 -> 2279 bytes .../tenacity/__pycache__/nap.cpython-312.pyc | Bin 0 -> 1389 bytes .../__pycache__/retry.cpython-312.pyc | Bin 0 -> 14252 bytes .../tenacity/__pycache__/stop.cpython-312.pyc | Bin 0 -> 5545 bytes .../tenacity/__pycache__/wait.cpython-312.pyc | Bin 0 -> 12390 bytes .../pip/_vendor/tenacity/_asyncio.py | 94 + .../pip/_vendor/tenacity/_utils.py | 76 + .../pip/_vendor/tenacity/after.py | 51 + .../pip/_vendor/tenacity/before.py | 46 + .../pip/_vendor/tenacity/before_sleep.py | 71 + .../site-packages/pip/_vendor/tenacity/nap.py | 43 + .../pip/_vendor/tenacity/retry.py | 272 + .../pip/_vendor/tenacity/stop.py | 103 + .../pip/_vendor/tenacity/tornadoweb.py | 59 + .../pip/_vendor/tenacity/wait.py | 228 + .../pip/_vendor/tomli/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 361 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 0 -> 26872 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 0 -> 3885 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 0 -> 343 bytes .../pip/_vendor/tomli/_parser.py | 691 ++ .../site-packages/pip/_vendor/tomli/_re.py | 107 + .../site-packages/pip/_vendor/tomli/_types.py | 10 + .../pip/_vendor/typing_extensions.py | 3072 ++++++ .../pip/_vendor/urllib3/__init__.py | 102 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3382 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 15848 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 195 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 20374 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 36251 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 13470 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 10367 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 3985 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 20244 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 6332 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 33926 bytes .../pip/_vendor/urllib3/_collections.py | 337 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 572 ++ .../pip/_vendor/urllib3/connectionpool.py | 1132 +++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 175 bytes .../_appengine_environ.cpython-312.pyc | Bin 0 -> 1825 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 7488 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 519 + .../contrib/_securetransport/low_level.py | 397 + .../pip/_vendor/urllib3/contrib/appengine.py | 314 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 518 + .../urllib3/contrib/securetransport.py | 921 ++ .../pip/_vendor/urllib3/contrib/socks.py | 216 + .../pip/_vendor/urllib3/exceptions.py | 323 + .../pip/_vendor/urllib3/fields.py | 274 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 176 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 0 -> 41223 bytes .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 51 + .../packages/backports/weakref_finalize.py | 155 + .../pip/_vendor/urllib3/packages/six.py | 1076 +++ .../pip/_vendor/urllib3/poolmanager.py | 537 + .../pip/_vendor/urllib3/request.py | 170 + .../pip/_vendor/urllib3/response.py | 879 ++ .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1123 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4724 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1529 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 0 -> 1329 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 4160 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 2966 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 21660 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 15068 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5028 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 10749 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11116 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 15753 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 4380 bytes .../pip/_vendor/urllib3/util/connection.py | 149 + .../pip/_vendor/urllib3/util/proxy.py | 57 + .../pip/_vendor/urllib3/util/queue.py | 22 + .../pip/_vendor/urllib3/util/request.py | 137 + .../pip/_vendor/urllib3/util/response.py | 107 + .../pip/_vendor/urllib3/util/retry.py | 620 ++ .../pip/_vendor/urllib3/util/ssl_.py | 495 + .../urllib3/util/ssl_match_hostname.py | 159 + .../pip/_vendor/urllib3/util/ssltransport.py | 221 + .../pip/_vendor/urllib3/util/timeout.py | 271 + .../pip/_vendor/urllib3/util/url.py | 435 + .../pip/_vendor/urllib3/util/wait.py | 152 + .../Lib/site-packages/pip/_vendor/vendor.txt | 23 + .../pip/_vendor/webencodings/__init__.py | 342 + .../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 + .venv/Lib/site-packages/pip/py.typed | 4 + .../platformdirs-4.2.2.dist-info/INSTALLER | 1 + .../platformdirs-4.2.2.dist-info/METADATA | 319 + .../platformdirs-4.2.2.dist-info/RECORD | 22 + .../platformdirs-4.2.2.dist-info/WHEEL | 4 + .../licenses/LICENSE | 21 + .../site-packages/platformdirs/__init__.py | 627 ++ .../site-packages/platformdirs/__main__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19745 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 1900 bytes .../__pycache__/android.cpython-312.pyc | Bin 0 -> 10661 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 12875 bytes .../__pycache__/macos.cpython-312.pyc | Bin 0 -> 7971 bytes .../__pycache__/unix.cpython-312.pyc | Bin 0 -> 14996 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 561 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 13637 bytes .../Lib/site-packages/platformdirs/android.py | 249 + .venv/Lib/site-packages/platformdirs/api.py | 292 + .venv/Lib/site-packages/platformdirs/macos.py | 130 + .venv/Lib/site-packages/platformdirs/py.typed | 0 .venv/Lib/site-packages/platformdirs/unix.py | 275 + .../Lib/site-packages/platformdirs/version.py | 16 + .../Lib/site-packages/platformdirs/windows.py | 272 + .../INSTALLER | 1 + .../LICENSE | 54 + .../METADATA | 204 + .../RECORD | 44 + .../WHEEL | 6 + .../top_level.txt | 1 + .../zip-safe | 1 + .../pyyaml_env_tag-0.1.dist-info/INSTALLER | 1 + .../pyyaml_env_tag-0.1.dist-info/LICENSE | 21 + .../pyyaml_env_tag-0.1.dist-info/METADATA | 140 + .../pyyaml_env_tag-0.1.dist-info/RECORD | 7 + .../pyyaml_env_tag-0.1.dist-info/WHEEL | 4 + .../six-1.16.0.dist-info/INSTALLER | 1 + .../six-1.16.0.dist-info/LICENSE | 18 + .../six-1.16.0.dist-info/METADATA | 49 + .../site-packages/six-1.16.0.dist-info/RECORD | 8 + .../site-packages/six-1.16.0.dist-info/WHEEL | 6 + .../six-1.16.0.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/six.py | 998 ++ .../watchdog-5.0.0.dist-info/AUTHORS | 73 + .../watchdog-5.0.0.dist-info/COPYING | 16 + .../watchdog-5.0.0.dist-info/INSTALLER | 1 + .../watchdog-5.0.0.dist-info/LICENSE | 202 + .../watchdog-5.0.0.dist-info/METADATA | 818 ++ .../watchdog-5.0.0.dist-info/RECORD | 61 + .../watchdog-5.0.0.dist-info/WHEEL | 5 + .../watchdog-5.0.0.dist-info/entry_points.txt | 2 + .../watchdog-5.0.0.dist-info/top_level.txt | 1 + .venv/Lib/site-packages/watchdog/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 156 bytes .../__pycache__/events.cpython-312.pyc | Bin 0 -> 22406 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 402 bytes .../__pycache__/watchmedo.cpython-312.pyc | Bin 0 -> 26296 bytes .venv/Lib/site-packages/watchdog/events.py | 542 ++ .../watchdog/observers/__init__.py | 91 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4092 bytes .../observers/__pycache__/api.cpython-312.pyc | Bin 0 -> 20566 bytes .../__pycache__/fsevents.cpython-312.pyc | Bin 0 -> 16717 bytes .../__pycache__/fsevents2.cpython-312.pyc | Bin 0 -> 13056 bytes .../__pycache__/inotify.cpython-312.pyc | Bin 0 -> 13311 bytes .../inotify_buffer.cpython-312.pyc | Bin 0 -> 5357 bytes .../__pycache__/inotify_c.cpython-312.pyc | Bin 0 -> 25324 bytes .../__pycache__/kqueue.cpython-312.pyc | Bin 0 -> 29242 bytes .../__pycache__/polling.cpython-312.pyc | Bin 0 -> 6878 bytes .../read_directory_changes.cpython-312.pyc | Bin 0 -> 6198 bytes .../__pycache__/winapi.cpython-312.pyc | Bin 0 -> 12273 bytes .../site-packages/watchdog/observers/api.py | 392 + .../watchdog/observers/fsevents.py | 339 + .../watchdog/observers/fsevents2.py | 253 + .../watchdog/observers/inotify.py | 252 + .../watchdog/observers/inotify_buffer.py | 102 + .../watchdog/observers/inotify_c.py | 558 ++ .../watchdog/observers/kqueue.py | 655 ++ .../watchdog/observers/polling.py | 142 + .../observers/read_directory_changes.py | 111 + .../watchdog/observers/winapi.py | 382 + .venv/Lib/site-packages/watchdog/py.typed | 0 .../site-packages/watchdog/tricks/__init__.py | 290 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 12276 bytes .../site-packages/watchdog/utils/__init__.py | 122 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5461 bytes .../utils/__pycache__/bricks.cpython-312.pyc | Bin 0 -> 3075 bytes .../__pycache__/delayed_queue.cpython-312.pyc | Bin 0 -> 4428 bytes .../__pycache__/dirsnapshot.cpython-312.pyc | Bin 0 -> 20486 bytes .../utils/__pycache__/echo.cpython-312.pyc | Bin 0 -> 7607 bytes .../event_debouncer.cpython-312.pyc | Bin 0 -> 3255 bytes .../__pycache__/patterns.cpython-312.pyc | Bin 0 -> 3977 bytes .../__pycache__/platform.cpython-312.pyc | Bin 0 -> 1673 bytes .../process_watcher.cpython-312.pyc | Bin 0 -> 1822 bytes .../site-packages/watchdog/utils/bricks.py | 88 + .../watchdog/utils/delayed_queue.py | 77 + .../watchdog/utils/dirsnapshot.py | 424 + .../Lib/site-packages/watchdog/utils/echo.py | 156 + .../watchdog/utils/event_debouncer.py | 66 + .../site-packages/watchdog/utils/patterns.py | 99 + .../site-packages/watchdog/utils/platform.py | 44 + .../watchdog/utils/process_watcher.py | 30 + .venv/Lib/site-packages/watchdog/version.py | 11 + .venv/Lib/site-packages/watchdog/watchmedo.py | 810 ++ .venv/Lib/site-packages/yaml/__init__.py | 390 + .../yaml/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 15567 bytes .../yaml/__pycache__/composer.cpython-312.pyc | Bin 0 -> 6498 bytes .../__pycache__/constructor.cpython-312.pyc | Bin 0 -> 34809 bytes .../yaml/__pycache__/cyaml.cpython-312.pyc | Bin 0 -> 4599 bytes .../yaml/__pycache__/dumper.cpython-312.pyc | Bin 0 -> 2435 bytes .../yaml/__pycache__/emitter.cpython-312.pyc | Bin 0 -> 50082 bytes .../yaml/__pycache__/error.cpython-312.pyc | Bin 0 -> 4241 bytes .../yaml/__pycache__/events.cpython-312.pyc | Bin 0 -> 4683 bytes .../yaml/__pycache__/loader.cpython-312.pyc | Bin 0 -> 3497 bytes .../yaml/__pycache__/nodes.cpython-312.pyc | Bin 0 -> 2182 bytes .../yaml/__pycache__/parser.cpython-312.pyc | Bin 0 -> 24677 bytes .../yaml/__pycache__/reader.cpython-312.pyc | Bin 0 -> 8817 bytes .../__pycache__/representer.cpython-312.pyc | Bin 0 -> 16870 bytes .../yaml/__pycache__/resolver.cpython-312.pyc | Bin 0 -> 8998 bytes .../yaml/__pycache__/scanner.cpython-312.pyc | Bin 0 -> 49798 bytes .../__pycache__/serializer.cpython-312.pyc | Bin 0 -> 6152 bytes .../yaml/__pycache__/tokens.cpython-312.pyc | Bin 0 -> 5752 bytes .../yaml/_yaml.cp312-win_amd64.pyd | Bin 0 -> 263680 bytes .venv/Lib/site-packages/yaml/composer.py | 139 + .venv/Lib/site-packages/yaml/constructor.py | 748 ++ .venv/Lib/site-packages/yaml/cyaml.py | 101 + .venv/Lib/site-packages/yaml/dumper.py | 62 + .venv/Lib/site-packages/yaml/emitter.py | 1137 +++ .venv/Lib/site-packages/yaml/error.py | 75 + .venv/Lib/site-packages/yaml/events.py | 86 + .venv/Lib/site-packages/yaml/loader.py | 63 + .venv/Lib/site-packages/yaml/nodes.py | 49 + .venv/Lib/site-packages/yaml/parser.py | 589 ++ .venv/Lib/site-packages/yaml/reader.py | 185 + .venv/Lib/site-packages/yaml/representer.py | 389 + .venv/Lib/site-packages/yaml/resolver.py | 227 + .venv/Lib/site-packages/yaml/scanner.py | 1435 +++ .venv/Lib/site-packages/yaml/serializer.py | 111 + .venv/Lib/site-packages/yaml/tokens.py | 104 + .venv/Lib/site-packages/yaml_env_tag.py | 34 + .venv/Scripts/activate | 87 + .venv/Scripts/activate.bat | 38 + .venv/Scripts/activate.fish | 103 + .venv/Scripts/activate.nu | 96 + .venv/Scripts/activate.ps1 | 61 + .venv/Scripts/activate_this.py | 36 + .venv/Scripts/deactivate.bat | 18 + .venv/Scripts/ghp-import.exe | Bin 0 -> 108386 bytes .venv/Scripts/markdown_py.exe | Bin 0 -> 108391 bytes .venv/Scripts/mkdocs-get-deps.exe | Bin 0 -> 108398 bytes .venv/Scripts/mkdocs.exe | Bin 0 -> 108389 bytes .venv/Scripts/pip-3.12.exe | Bin 0 -> 108398 bytes .venv/Scripts/pip.exe | Bin 0 -> 108398 bytes .venv/Scripts/pip3.12.exe | Bin 0 -> 108398 bytes .venv/Scripts/pip3.exe | Bin 0 -> 108398 bytes .venv/Scripts/pydoc.bat | 1 + .venv/Scripts/python.exe | Bin 0 -> 270104 bytes .venv/Scripts/pythonw.exe | Bin 0 -> 258840 bytes .venv/Scripts/watchmedo.exe | Bin 0 -> 108394 bytes .venv/pyvenv.cfg | 8 + 1605 files changed, 284503 insertions(+) create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/LICENSE.md create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/Markdown-3.7.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/PyYAML-6.0.2.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/__pycache__/_virtualenv.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/__pycache__/ghp_import.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/__pycache__/six.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/__pycache__/yaml_env_tag.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/_virtualenv.pth create mode 100644 .venv/Lib/site-packages/_virtualenv.py create mode 100644 .venv/Lib/site-packages/_yaml/__init__.py create mode 100644 .venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/LICENSE.rst create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/click-8.1.7.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/click/__init__.py create mode 100644 .venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/decorators.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/click/_compat.py create mode 100644 .venv/Lib/site-packages/click/_termui_impl.py create mode 100644 .venv/Lib/site-packages/click/_textwrap.py create mode 100644 .venv/Lib/site-packages/click/_winconsole.py create mode 100644 .venv/Lib/site-packages/click/core.py create mode 100644 .venv/Lib/site-packages/click/decorators.py create mode 100644 .venv/Lib/site-packages/click/exceptions.py create mode 100644 .venv/Lib/site-packages/click/formatting.py create mode 100644 .venv/Lib/site-packages/click/globals.py create mode 100644 .venv/Lib/site-packages/click/parser.py create mode 100644 .venv/Lib/site-packages/click/py.typed create mode 100644 .venv/Lib/site-packages/click/shell_completion.py create mode 100644 .venv/Lib/site-packages/click/termui.py create mode 100644 .venv/Lib/site-packages/click/testing.py create mode 100644 .venv/Lib/site-packages/click/types.py create mode 100644 .venv/Lib/site-packages/click/utils.py create mode 100644 .venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt create mode 100644 .venv/Lib/site-packages/colorama/__init__.py create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/win32.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/ansi.py create mode 100644 .venv/Lib/site-packages/colorama/ansitowin32.py create mode 100644 .venv/Lib/site-packages/colorama/initialise.py create mode 100644 .venv/Lib/site-packages/colorama/tests/__init__.py create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/colorama/tests/ansi_test.py create mode 100644 .venv/Lib/site-packages/colorama/tests/ansitowin32_test.py create mode 100644 .venv/Lib/site-packages/colorama/tests/initialise_test.py create mode 100644 .venv/Lib/site-packages/colorama/tests/isatty_test.py create mode 100644 .venv/Lib/site-packages/colorama/tests/utils.py create mode 100644 .venv/Lib/site-packages/colorama/tests/winterm_test.py create mode 100644 .venv/Lib/site-packages/colorama/win32.py create mode 100644 .venv/Lib/site-packages/colorama/winterm.py create mode 100644 .venv/Lib/site-packages/dateutil/__init__.py create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/_common.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/_version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/easter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/relativedelta.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/rrule.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/tzwin.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/_common.py create mode 100644 .venv/Lib/site-packages/dateutil/_version.py create mode 100644 .venv/Lib/site-packages/dateutil/easter.py create mode 100644 .venv/Lib/site-packages/dateutil/parser/__init__.py create mode 100644 .venv/Lib/site-packages/dateutil/parser/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/parser/__pycache__/_parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/parser/__pycache__/isoparser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/parser/_parser.py create mode 100644 .venv/Lib/site-packages/dateutil/parser/isoparser.py create mode 100644 .venv/Lib/site-packages/dateutil/relativedelta.py create mode 100644 .venv/Lib/site-packages/dateutil/rrule.py create mode 100644 .venv/Lib/site-packages/dateutil/tz/__init__.py create mode 100644 .venv/Lib/site-packages/dateutil/tz/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/tz/__pycache__/_common.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/tz/__pycache__/_factories.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/tz/__pycache__/tz.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/tz/__pycache__/win.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/tz/_common.py create mode 100644 .venv/Lib/site-packages/dateutil/tz/_factories.py create mode 100644 .venv/Lib/site-packages/dateutil/tz/tz.py create mode 100644 .venv/Lib/site-packages/dateutil/tz/win.py create mode 100644 .venv/Lib/site-packages/dateutil/tzwin.py create mode 100644 .venv/Lib/site-packages/dateutil/utils.py create mode 100644 .venv/Lib/site-packages/dateutil/zoneinfo/__init__.py create mode 100644 .venv/Lib/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/zoneinfo/__pycache__/rebuild.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz create mode 100644 .venv/Lib/site-packages/dateutil/zoneinfo/rebuild.py create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/ghp_import-2.1.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/ghp_import.py create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/jinja2-3.1.4.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/jinja2/__init__.py create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/bccache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/constants.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/environment.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/ext.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/lexer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/meta.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/sandbox.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/__pycache__/visitor.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/jinja2/_identifier.py create mode 100644 .venv/Lib/site-packages/jinja2/async_utils.py create mode 100644 .venv/Lib/site-packages/jinja2/bccache.py create mode 100644 .venv/Lib/site-packages/jinja2/compiler.py create mode 100644 .venv/Lib/site-packages/jinja2/constants.py create mode 100644 .venv/Lib/site-packages/jinja2/debug.py create mode 100644 .venv/Lib/site-packages/jinja2/defaults.py create mode 100644 .venv/Lib/site-packages/jinja2/environment.py create mode 100644 .venv/Lib/site-packages/jinja2/exceptions.py create mode 100644 .venv/Lib/site-packages/jinja2/ext.py create mode 100644 .venv/Lib/site-packages/jinja2/filters.py create mode 100644 .venv/Lib/site-packages/jinja2/idtracking.py create mode 100644 .venv/Lib/site-packages/jinja2/lexer.py create mode 100644 .venv/Lib/site-packages/jinja2/loaders.py create mode 100644 .venv/Lib/site-packages/jinja2/meta.py create mode 100644 .venv/Lib/site-packages/jinja2/nativetypes.py create mode 100644 .venv/Lib/site-packages/jinja2/nodes.py create mode 100644 .venv/Lib/site-packages/jinja2/optimizer.py create mode 100644 .venv/Lib/site-packages/jinja2/parser.py create mode 100644 .venv/Lib/site-packages/jinja2/py.typed create mode 100644 .venv/Lib/site-packages/jinja2/runtime.py create mode 100644 .venv/Lib/site-packages/jinja2/sandbox.py create mode 100644 .venv/Lib/site-packages/jinja2/tests.py create mode 100644 .venv/Lib/site-packages/jinja2/utils.py create mode 100644 .venv/Lib/site-packages/jinja2/visitor.py create mode 100644 .venv/Lib/site-packages/markdown/__init__.py create mode 100644 .venv/Lib/site-packages/markdown/__main__.py create mode 100644 .venv/Lib/site-packages/markdown/__meta__.py create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/__main__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/__meta__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/blockparser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/blockprocessors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/core.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/htmlparser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/inlinepatterns.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/postprocessors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/preprocessors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/serializers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/test_tools.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/treeprocessors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/__pycache__/util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/blockparser.py create mode 100644 .venv/Lib/site-packages/markdown/blockprocessors.py create mode 100644 .venv/Lib/site-packages/markdown/core.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/__init__.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/abbr.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/admonition.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/attr_list.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/codehilite.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/def_list.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/extra.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/fenced_code.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/footnotes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/legacy_attrs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/legacy_em.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/md_in_html.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/meta.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/nl2br.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/sane_lists.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/smarty.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/tables.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/toc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/__pycache__/wikilinks.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markdown/extensions/abbr.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/admonition.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/attr_list.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/codehilite.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/def_list.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/extra.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/fenced_code.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/footnotes.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/legacy_attrs.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/legacy_em.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/md_in_html.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/meta.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/nl2br.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/sane_lists.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/smarty.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/tables.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/toc.py create mode 100644 .venv/Lib/site-packages/markdown/extensions/wikilinks.py create mode 100644 .venv/Lib/site-packages/markdown/htmlparser.py create mode 100644 .venv/Lib/site-packages/markdown/inlinepatterns.py create mode 100644 .venv/Lib/site-packages/markdown/postprocessors.py create mode 100644 .venv/Lib/site-packages/markdown/preprocessors.py create mode 100644 .venv/Lib/site-packages/markdown/serializers.py create mode 100644 .venv/Lib/site-packages/markdown/test_tools.py create mode 100644 .venv/Lib/site-packages/markdown/treeprocessors.py create mode 100644 .venv/Lib/site-packages/markdown/util.py create mode 100644 .venv/Lib/site-packages/markupsafe/__init__.py create mode 100644 .venv/Lib/site-packages/markupsafe/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markupsafe/__pycache__/_native.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/markupsafe/_native.py create mode 100644 .venv/Lib/site-packages/markupsafe/_speedups.c create mode 100644 .venv/Lib/site-packages/markupsafe/_speedups.cp312-win_amd64.pyd create mode 100644 .venv/Lib/site-packages/markupsafe/_speedups.pyi create mode 100644 .venv/Lib/site-packages/markupsafe/py.typed create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/mergedeep-1.3.4.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/mergedeep/__init__.py create mode 100644 .venv/Lib/site-packages/mergedeep/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mergedeep/__pycache__/mergedeep.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mergedeep/__pycache__/test_mergedeep.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mergedeep/mergedeep.py create mode 100644 .venv/Lib/site-packages/mergedeep/test_mergedeep.py create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/REQUESTED create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/mkdocs-1.6.1.dist-info/licenses/LICENSE create mode 100644 .venv/Lib/site-packages/mkdocs/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/__main__.py create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/__main__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/localization.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/plugins.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/__pycache__/theme.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__pycache__/build.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__pycache__/gh_deploy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__pycache__/new.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/__pycache__/serve.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/commands/build.py create mode 100644 .venv/Lib/site-packages/mkdocs/commands/gh_deploy.py create mode 100644 .venv/Lib/site-packages/mkdocs/commands/new.py create mode 100644 .venv/Lib/site-packages/mkdocs/commands/serve.py create mode 100644 .venv/Lib/site-packages/mkdocs/config/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/config/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/config/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/config/__pycache__/config_options.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/config/__pycache__/defaults.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/config/base.py create mode 100644 .venv/Lib/site-packages/mkdocs/config/config_options.py create mode 100644 .venv/Lib/site-packages/mkdocs/config/defaults.py create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/__pycache__/search_index.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ar.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.da.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.de.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.du.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.es.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.fi.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.fr.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.hi.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.hu.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.hy.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.it.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ja.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.jp.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.kn.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ko.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.multi.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.nl.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.no.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.pt.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ro.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ru.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.sa.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.stemmer.support.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.sv.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.ta.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.te.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.th.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.tr.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.vi.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/lunr.zh.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/lunr-language/tinyseg.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/prebuild-index.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/search_index.py create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/templates/search/lunr.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/templates/search/main.js create mode 100644 .venv/Lib/site-packages/mkdocs/contrib/search/templates/search/worker.js create mode 100644 .venv/Lib/site-packages/mkdocs/exceptions.py create mode 100644 .venv/Lib/site-packages/mkdocs/livereload/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/livereload/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/localization.py create mode 100644 .venv/Lib/site-packages/mkdocs/plugins.py create mode 100644 .venv/Lib/site-packages/mkdocs/py.typed create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__pycache__/files.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__pycache__/nav.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__pycache__/pages.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/structure/__pycache__/toc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/structure/files.py create mode 100644 .venv/Lib/site-packages/mkdocs/structure/nav.py create mode 100644 .venv/Lib/site-packages/mkdocs/structure/pages.py create mode 100644 .venv/Lib/site-packages/mkdocs/structure/toc.py create mode 100644 .venv/Lib/site-packages/mkdocs/templates/sitemap.xml create mode 100644 .venv/Lib/site-packages/mkdocs/theme.py create mode 100644 .venv/Lib/site-packages/mkdocs/themes/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/themes/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/404.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/base.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/content.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/base.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/bootstrap.min.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/bootstrap.min.css.map create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/brands.min.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/fontawesome.min.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/solid.min.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/css/v4-font-face.min.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/img/favicon.ico create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/img/grid.png create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/js/base.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/js/bootstrap.bundle.min.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/js/bootstrap.bundle.min.js.map create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/js/darkmode.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/keyboard-modal.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/de/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/es/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/fa/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/fr/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/id/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/it/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/ja/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/nb/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/nl/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/nn/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/pl/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/pt_BR/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/ru/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/tr/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/uk/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/zh_CN/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/locales/zh_TW/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/main.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/mkdocs_theme.yml create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/nav-sub.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/search-modal.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/toc.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-brands-400.ttf create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-brands-400.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-regular-400.ttf create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-regular-400.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-solid-900.ttf create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-solid-900.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-v4compatibility.ttf create mode 100644 .venv/Lib/site-packages/mkdocs/themes/mkdocs/webfonts/fa-v4compatibility.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/404.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/base.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/breadcrumbs.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/Roboto-Slab-Bold.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/Roboto-Slab-Bold.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/Roboto-Slab-Regular.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/Roboto-Slab-Regular.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/fontawesome-webfont.eot create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/fontawesome-webfont.svg create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/fontawesome-webfont.ttf create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/fontawesome-webfont.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/fontawesome-webfont.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-bold-italic.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-bold-italic.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-bold.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-bold.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-normal-italic.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-normal-italic.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-normal.woff create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/fonts/lato-normal.woff2 create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/theme.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/css/theme_extra.css create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/footer.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/img/favicon.ico create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/js/html5shiv.min.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/js/jquery-3.6.0.min.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/js/theme.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/js/theme_extra.js create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/de/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/es/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/fa/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/fr/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/id/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/it/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/ja/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/nl/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/pl/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/pt_BR/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/ru/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/tr/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/uk/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/zh_CN/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/locales/zh_TW/LC_MESSAGES/messages.mo create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/main.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/mkdocs_theme.yml create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/nav.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/search.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/searchbox.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/toc.html create mode 100644 .venv/Lib/site-packages/mkdocs/themes/readthedocs/versions.html create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/babel_stub.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/filters.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/meta.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/rendering.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/templates.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/__pycache__/yaml.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs/utils/babel_stub.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/cache.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/filters.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/meta.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/rendering.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/templates.py create mode 100644 .venv/Lib/site-packages/mkdocs/utils/yaml.py create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps-0.2.0.dist-info/licenses/LICENSE.md create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__init__.py create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__main__.py create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__pycache__/__main__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__pycache__/cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/__pycache__/yaml_util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/cache.py create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/py.typed create mode 100644 .venv/Lib/site-packages/mkdocs_get_deps/yaml_util.py create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/LICENSE.APACHE create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/LICENSE.BSD create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/packaging-24.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/packaging/__init__.py create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_elffile.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_manylinux.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_musllinux.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_structures.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/_tokenizer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/markers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/metadata.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/requirements.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/specifiers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/tags.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/packaging/_elffile.py create mode 100644 .venv/Lib/site-packages/packaging/_manylinux.py create mode 100644 .venv/Lib/site-packages/packaging/_musllinux.py create mode 100644 .venv/Lib/site-packages/packaging/_parser.py create mode 100644 .venv/Lib/site-packages/packaging/_structures.py create mode 100644 .venv/Lib/site-packages/packaging/_tokenizer.py create mode 100644 .venv/Lib/site-packages/packaging/markers.py create mode 100644 .venv/Lib/site-packages/packaging/metadata.py create mode 100644 .venv/Lib/site-packages/packaging/py.typed create mode 100644 .venv/Lib/site-packages/packaging/requirements.py create mode 100644 .venv/Lib/site-packages/packaging/specifiers.py create mode 100644 .venv/Lib/site-packages/packaging/tags.py create mode 100644 .venv/Lib/site-packages/packaging/utils.py create mode 100644 .venv/Lib/site-packages/packaging/version.py create mode 100644 .venv/Lib/site-packages/pathspec-0.12.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/pathspec-0.12.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/pathspec-0.12.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/pathspec-0.12.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/pathspec-0.12.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/pathspec/__init__.py create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/_meta.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/gitignore.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/pathspec.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/pattern.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/__pycache__/util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/_meta.py create mode 100644 .venv/Lib/site-packages/pathspec/gitignore.py create mode 100644 .venv/Lib/site-packages/pathspec/pathspec.py create mode 100644 .venv/Lib/site-packages/pathspec/pattern.py create mode 100644 .venv/Lib/site-packages/pathspec/patterns/__init__.py create mode 100644 .venv/Lib/site-packages/pathspec/patterns/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/patterns/__pycache__/gitwildmatch.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pathspec/patterns/gitwildmatch.py create mode 100644 .venv/Lib/site-packages/pathspec/py.typed create mode 100644 .venv/Lib/site-packages/pathspec/util.py create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/AUTHORS.txt create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/LICENSE.txt create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/pip-23.2.1.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/pip-23.2.1.virtualenv create mode 100644 .venv/Lib/site-packages/pip/__init__.py create mode 100644 .venv/Lib/site-packages/pip/__main__.py create mode 100644 .venv/Lib/site-packages/pip/__pip-runner__.py create mode 100644 .venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/build_env.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cache.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/command_context.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/main.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/req_command.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/spinners.py create mode 100644 .venv/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/cache.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/debug.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/index.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/inspect.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 .venv/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/configuration.py create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/base.py create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/installed.py create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/sdist.py create mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 .venv/Lib/site-packages/pip/_internal/index/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/index/collector.py create mode 100644 .venv/Lib/site-packages/pip/_internal/index/package_finder.py create mode 100644 .venv/Lib/site-packages/pip/_internal/index/sources.py create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/_distutils.py create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 .venv/Lib/site-packages/pip/_internal/locations/base.py create mode 100644 .venv/Lib/site-packages/pip/_internal/main.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/_json.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/base.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py create mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/direct_url.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/index.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/installation_report.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/link.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/scheme.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/search_scope.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/target_python.py create mode 100644 .venv/Lib/site-packages/pip/_internal/models/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/network/auth.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/cache.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/download.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/session.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/utils.py create mode 100644 .venv/Lib/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 .venv/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/base.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 .venv/Lib/site-packages/pip/_internal/self_outdated_check.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/_log.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/datetime.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/egg_link.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/filetypes.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/models.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/subprocess.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/unpacking.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/urls.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 .venv/Lib/site-packages/pip/_internal/utils/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 .venv/Lib/site-packages/pip/_internal/wheel_builder.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachinedict.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/enums.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/johabfreq.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/johabprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/macromanprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/resultdict.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/utf1632prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/chardet/version.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/ansi_test.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/initialise_test.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/isatty_test.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/utils.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/tests/winterm_test.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/win32.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__main__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/distro.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/tags.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/console.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filter.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/style.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/token.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/util.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/common.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/core.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/helpers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/results.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/testing.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/unicode.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyparsing/util.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_compat.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__main__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_export_format.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_extension.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_fileno.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_loop.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_null_file.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_pick.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_stack.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_timer.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_windows.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/abc.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/align.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/ansi.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/bar.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/box.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/cells.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/color.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/columns.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/console.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/constrain.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/containers.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/control.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/emoji.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/errors.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/filesize.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/json.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/layout.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/live.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/live_render.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/logging.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/markup.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/measure.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/padding.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/pager.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/palette.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/panel.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/pretty.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/progress.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/prompt.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/protocol.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/region.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/repr.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/rule.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/scope.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/screen.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/segment.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/spinner.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/status.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/style.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/styled.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/syntax.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/table.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/text.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/theme.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/themes.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/traceback.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/tree.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/six.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/_utils.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/after.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/before.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/nap.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/retry.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/stop.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tenacity/wait.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_re.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_types.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/typing_extensions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/vendor.txt create mode 100644 .venv/Lib/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 .venv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 .venv/Lib/site-packages/pip/py.typed create mode 100644 .venv/Lib/site-packages/platformdirs-4.2.2.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/platformdirs-4.2.2.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/platformdirs-4.2.2.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/platformdirs-4.2.2.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/platformdirs-4.2.2.dist-info/licenses/LICENSE create mode 100644 .venv/Lib/site-packages/platformdirs/__init__.py create mode 100644 .venv/Lib/site-packages/platformdirs/__main__.py create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/__main__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/android.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/api.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/macos.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/unix.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/__pycache__/windows.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/platformdirs/android.py create mode 100644 .venv/Lib/site-packages/platformdirs/api.py create mode 100644 .venv/Lib/site-packages/platformdirs/macos.py create mode 100644 .venv/Lib/site-packages/platformdirs/py.typed create mode 100644 .venv/Lib/site-packages/platformdirs/unix.py create mode 100644 .venv/Lib/site-packages/platformdirs/version.py create mode 100644 .venv/Lib/site-packages/platformdirs/windows.py create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/python_dateutil-2.9.0.post0.dist-info/zip-safe create mode 100644 .venv/Lib/site-packages/pyyaml_env_tag-0.1.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/pyyaml_env_tag-0.1.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/pyyaml_env_tag-0.1.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/pyyaml_env_tag-0.1.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/pyyaml_env_tag-0.1.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/six-1.16.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/six.py create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/AUTHORS create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/COPYING create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/INSTALLER create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/LICENSE create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/METADATA create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/RECORD create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/WHEEL create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/entry_points.txt create mode 100644 .venv/Lib/site-packages/watchdog-5.0.0.dist-info/top_level.txt create mode 100644 .venv/Lib/site-packages/watchdog/__init__.py create mode 100644 .venv/Lib/site-packages/watchdog/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/__pycache__/events.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/__pycache__/version.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/__pycache__/watchmedo.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/events.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/__init__.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/api.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/fsevents.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/fsevents2.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/inotify.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/inotify_buffer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/inotify_c.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/kqueue.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/polling.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/read_directory_changes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/__pycache__/winapi.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/observers/api.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/fsevents.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/fsevents2.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/inotify.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/inotify_buffer.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/inotify_c.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/kqueue.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/polling.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/read_directory_changes.py create mode 100644 .venv/Lib/site-packages/watchdog/observers/winapi.py create mode 100644 .venv/Lib/site-packages/watchdog/py.typed create mode 100644 .venv/Lib/site-packages/watchdog/tricks/__init__.py create mode 100644 .venv/Lib/site-packages/watchdog/tricks/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__init__.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/bricks.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/delayed_queue.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/dirsnapshot.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/echo.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/event_debouncer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/patterns.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/platform.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/__pycache__/process_watcher.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/watchdog/utils/bricks.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/delayed_queue.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/dirsnapshot.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/echo.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/event_debouncer.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/patterns.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/platform.py create mode 100644 .venv/Lib/site-packages/watchdog/utils/process_watcher.py create mode 100644 .venv/Lib/site-packages/watchdog/version.py create mode 100644 .venv/Lib/site-packages/watchdog/watchmedo.py create mode 100644 .venv/Lib/site-packages/yaml/__init__.py create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/__init__.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/composer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/constructor.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/cyaml.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/dumper.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/emitter.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/error.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/events.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/loader.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/nodes.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/parser.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/reader.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/representer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/resolver.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/scanner.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/serializer.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/__pycache__/tokens.cpython-312.pyc create mode 100644 .venv/Lib/site-packages/yaml/_yaml.cp312-win_amd64.pyd create mode 100644 .venv/Lib/site-packages/yaml/composer.py create mode 100644 .venv/Lib/site-packages/yaml/constructor.py create mode 100644 .venv/Lib/site-packages/yaml/cyaml.py create mode 100644 .venv/Lib/site-packages/yaml/dumper.py create mode 100644 .venv/Lib/site-packages/yaml/emitter.py create mode 100644 .venv/Lib/site-packages/yaml/error.py create mode 100644 .venv/Lib/site-packages/yaml/events.py create mode 100644 .venv/Lib/site-packages/yaml/loader.py create mode 100644 .venv/Lib/site-packages/yaml/nodes.py create mode 100644 .venv/Lib/site-packages/yaml/parser.py create mode 100644 .venv/Lib/site-packages/yaml/reader.py create mode 100644 .venv/Lib/site-packages/yaml/representer.py create mode 100644 .venv/Lib/site-packages/yaml/resolver.py create mode 100644 .venv/Lib/site-packages/yaml/scanner.py create mode 100644 .venv/Lib/site-packages/yaml/serializer.py create mode 100644 .venv/Lib/site-packages/yaml/tokens.py create mode 100644 .venv/Lib/site-packages/yaml_env_tag.py create mode 100644 .venv/Scripts/activate create mode 100644 .venv/Scripts/activate.bat create mode 100644 .venv/Scripts/activate.fish create mode 100644 .venv/Scripts/activate.nu create mode 100644 .venv/Scripts/activate.ps1 create mode 100644 .venv/Scripts/activate_this.py create mode 100644 .venv/Scripts/deactivate.bat create mode 100644 .venv/Scripts/ghp-import.exe create mode 100644 .venv/Scripts/markdown_py.exe create mode 100644 .venv/Scripts/mkdocs-get-deps.exe create mode 100644 .venv/Scripts/mkdocs.exe create mode 100644 .venv/Scripts/pip-3.12.exe create mode 100644 .venv/Scripts/pip.exe create mode 100644 .venv/Scripts/pip3.12.exe create mode 100644 .venv/Scripts/pip3.exe create mode 100644 .venv/Scripts/pydoc.bat create mode 100644 .venv/Scripts/python.exe create mode 100644 .venv/Scripts/pythonw.exe create mode 100644 .venv/Scripts/watchmedo.exe create mode 100644 .venv/pyvenv.cfg diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/INSTALLER b/.venv/Lib/site-packages/Markdown-3.7.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/LICENSE.md b/.venv/Lib/site-packages/Markdown-3.7.dist-info/LICENSE.md new file mode 100644 index 00000000..6249d60c --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/LICENSE.md @@ -0,0 +1,30 @@ +BSD 3-Clause License + +Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later) +Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) +Copyright 2004 Manfred Stienstra (the original version) + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/METADATA b/.venv/Lib/site-packages/Markdown-3.7.dist-info/METADATA new file mode 100644 index 00000000..233bc55b --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/METADATA @@ -0,0 +1,146 @@ +Metadata-Version: 2.1 +Name: Markdown +Version: 3.7 +Summary: Python implementation of John Gruber's Markdown. +Author: Manfred Stienstra, Yuri Takhteyev +Author-email: Waylan limberg +Maintainer: Isaac Muse +Maintainer-email: Waylan Limberg +License: BSD 3-Clause License + + Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later) + Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) + Copyright 2004 Manfred Stienstra (the original version) + + 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: Homepage, https://Python-Markdown.github.io/ +Project-URL: Documentation, https://Python-Markdown.github.io/ +Project-URL: Repository, https://github.com/Python-Markdown/markdown +Project-URL: Issue Tracker, https://github.com/Python-Markdown/markdown/issues +Project-URL: Changelog, https://python-markdown.github.io/changelog/ +Keywords: markdown,markdown-parser,python-markdown,markdown-to-html +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Communications :: Email :: Filters +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries +Classifier: Topic :: Internet :: WWW/HTTP :: Site Management +Classifier: Topic :: Software Development :: Documentation +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Filters +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Topic :: Text Processing :: Markup :: Markdown +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE.md +Requires-Dist: importlib-metadata >=4.4 ; python_version < "3.10" +Provides-Extra: docs +Requires-Dist: mkdocs >=1.5 ; extra == 'docs' +Requires-Dist: mkdocs-nature >=0.6 ; extra == 'docs' +Requires-Dist: mdx-gh-links >=0.2 ; extra == 'docs' +Requires-Dist: mkdocstrings[python] ; extra == 'docs' +Requires-Dist: mkdocs-gen-files ; extra == 'docs' +Requires-Dist: mkdocs-section-index ; extra == 'docs' +Requires-Dist: mkdocs-literate-nav ; extra == 'docs' +Provides-Extra: testing +Requires-Dist: coverage ; extra == 'testing' +Requires-Dist: pyyaml ; extra == 'testing' + +[Python-Markdown][] +=================== + +[![Build Status][build-button]][build] +[![Coverage Status][codecov-button]][codecov] +[![Latest Version][mdversion-button]][md-pypi] +[![Python Versions][pyversion-button]][md-pypi] +[![BSD License][bsdlicense-button]][bsdlicense] +[![Code of Conduct][codeofconduct-button]][Code of Conduct] + +[build-button]: https://github.com/Python-Markdown/markdown/workflows/CI/badge.svg?event=push +[build]: https://github.com/Python-Markdown/markdown/actions?query=workflow%3ACI+event%3Apush +[codecov-button]: https://codecov.io/gh/Python-Markdown/markdown/branch/master/graph/badge.svg +[codecov]: https://codecov.io/gh/Python-Markdown/markdown +[mdversion-button]: https://img.shields.io/pypi/v/Markdown.svg +[md-pypi]: https://pypi.org/project/Markdown/ +[pyversion-button]: https://img.shields.io/pypi/pyversions/Markdown.svg +[bsdlicense-button]: https://img.shields.io/badge/license-BSD-yellow.svg +[bsdlicense]: https://opensource.org/licenses/BSD-3-Clause +[codeofconduct-button]: https://img.shields.io/badge/code%20of%20conduct-contributor%20covenant-green.svg?style=flat-square +[Code of Conduct]: https://github.com/Python-Markdown/markdown/blob/master/CODE_OF_CONDUCT.md + +This is a Python implementation of John Gruber's [Markdown][]. +It is almost completely compliant with the reference implementation, +though there are a few known issues. See [Features][] for information +on what exactly is supported and what is not. Additional features are +supported by the [Available Extensions][]. + +[Python-Markdown]: https://Python-Markdown.github.io/ +[Markdown]: https://daringfireball.net/projects/markdown/ +[Features]: https://Python-Markdown.github.io#Features +[Available Extensions]: https://Python-Markdown.github.io/extensions + +Documentation +------------- + +```bash +pip install markdown +``` +```python +import markdown +html = markdown.markdown(your_text_string) +``` + +For more advanced [installation] and [usage] documentation, see the `docs/` directory +of the distribution or the project website at . + +[installation]: https://python-markdown.github.io/install/ +[usage]: https://python-markdown.github.io/reference/ + +See the change log at . + +Support +------- + +You may report bugs, ask for help, and discuss various other issues on the [bug tracker][]. + +[bug tracker]: https://github.com/Python-Markdown/markdown/issues + +Code of Conduct +--------------- + +Everyone interacting in the Python-Markdown project's code bases, issue trackers, +and mailing lists is expected to follow the [Code of Conduct]. diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/RECORD b/.venv/Lib/site-packages/Markdown-3.7.dist-info/RECORD new file mode 100644 index 00000000..08af844e --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/RECORD @@ -0,0 +1,74 @@ +../../Scripts/markdown_py.exe,sha256=ZnZMw_QSJtOf4tH9y-cgtuvZW2l94PV03773KaHPmI8,108391 +Markdown-3.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Markdown-3.7.dist-info/LICENSE.md,sha256=e6TrbRCzKy0R3OE4ITQDUc27swuozMZ4Qdsv_Ybnmso,1650 +Markdown-3.7.dist-info/METADATA,sha256=nY8sewcY6R1akyROqkyO-Jk_eUDY8am_C4MkRP79sWA,7040 +Markdown-3.7.dist-info/RECORD,, +Markdown-3.7.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91 +Markdown-3.7.dist-info/entry_points.txt,sha256=lMEyiiA_ZZyfPCBlDviBl-SiU0cfoeuEKpwxw361sKQ,1102 +Markdown-3.7.dist-info/top_level.txt,sha256=IAxs8x618RXoH1uCqeLLxXsDefJvE_mIibr_M4sOlyk,9 +markdown/__init__.py,sha256=dfzwwdpG9L8QLEPBpLFPIHx_BN056aZXp9xZifTxYIU,1777 +markdown/__main__.py,sha256=innFBxRqwPBNxG1zhKktJji4bnRKtVyYYd30ID13Tcw,5859 +markdown/__meta__.py,sha256=RhwfJ30zyGvJaJXLHwQdNH5jw69-5fVKu2p-CVaJz0U,1712 +markdown/__pycache__/__init__.cpython-312.pyc,, +markdown/__pycache__/__main__.cpython-312.pyc,, +markdown/__pycache__/__meta__.cpython-312.pyc,, +markdown/__pycache__/blockparser.cpython-312.pyc,, +markdown/__pycache__/blockprocessors.cpython-312.pyc,, +markdown/__pycache__/core.cpython-312.pyc,, +markdown/__pycache__/htmlparser.cpython-312.pyc,, +markdown/__pycache__/inlinepatterns.cpython-312.pyc,, +markdown/__pycache__/postprocessors.cpython-312.pyc,, +markdown/__pycache__/preprocessors.cpython-312.pyc,, +markdown/__pycache__/serializers.cpython-312.pyc,, +markdown/__pycache__/test_tools.cpython-312.pyc,, +markdown/__pycache__/treeprocessors.cpython-312.pyc,, +markdown/__pycache__/util.cpython-312.pyc,, +markdown/blockparser.py,sha256=j4CQImVpiq7g9pz8wCxvzT61X_T2iSAjXupHJk8P3eA,5728 +markdown/blockprocessors.py,sha256=koY5rq8DixzBCHcquvZJp6x2JYyBGjrwxMWNZhd6D2U,27013 +markdown/core.py,sha256=DyyzDsmd-KcuEp8ZWUKJAeUCt7B7G3J3NeqZqp3LphI,21335 +markdown/extensions/__init__.py,sha256=9z1khsdKCVrmrJ_2GfxtPAdjD3FyMe5vhC7wmM4O9m0,4822 +markdown/extensions/__pycache__/__init__.cpython-312.pyc,, +markdown/extensions/__pycache__/abbr.cpython-312.pyc,, +markdown/extensions/__pycache__/admonition.cpython-312.pyc,, +markdown/extensions/__pycache__/attr_list.cpython-312.pyc,, +markdown/extensions/__pycache__/codehilite.cpython-312.pyc,, +markdown/extensions/__pycache__/def_list.cpython-312.pyc,, +markdown/extensions/__pycache__/extra.cpython-312.pyc,, +markdown/extensions/__pycache__/fenced_code.cpython-312.pyc,, +markdown/extensions/__pycache__/footnotes.cpython-312.pyc,, +markdown/extensions/__pycache__/legacy_attrs.cpython-312.pyc,, +markdown/extensions/__pycache__/legacy_em.cpython-312.pyc,, +markdown/extensions/__pycache__/md_in_html.cpython-312.pyc,, +markdown/extensions/__pycache__/meta.cpython-312.pyc,, +markdown/extensions/__pycache__/nl2br.cpython-312.pyc,, +markdown/extensions/__pycache__/sane_lists.cpython-312.pyc,, +markdown/extensions/__pycache__/smarty.cpython-312.pyc,, +markdown/extensions/__pycache__/tables.cpython-312.pyc,, +markdown/extensions/__pycache__/toc.cpython-312.pyc,, +markdown/extensions/__pycache__/wikilinks.cpython-312.pyc,, +markdown/extensions/abbr.py,sha256=Gqt9TUtLWez2cbsy3SQk5152RZekops2fUJj01bfkfw,6903 +markdown/extensions/admonition.py,sha256=Hqcn3I8JG0i-OPWdoqI189TmlQRgH6bs5PmpCANyLlg,6547 +markdown/extensions/attr_list.py,sha256=t3PrgAr5Ebldnq3nJNbteBt79bN0ccXS5RemmQfUZ9g,7820 +markdown/extensions/codehilite.py,sha256=ChlmpM6S--j-UK7t82859UpYjm8EftdiLqmgDnknyes,13503 +markdown/extensions/def_list.py,sha256=J3NVa6CllfZPsboJCEycPyRhtjBHnOn8ET6omEvVlDo,4029 +markdown/extensions/extra.py,sha256=1vleT284kued4HQBtF83IjSumJVo0q3ng6MjTkVNfNQ,2163 +markdown/extensions/fenced_code.py,sha256=-fYSmRZ9DTYQ8HO9b_78i47kVyVu6mcVJlqVTMdzvo4,8300 +markdown/extensions/footnotes.py,sha256=bRFlmIBOKDI5efG1jZfDkMoV2osfqWip1rN1j2P-mMg,16710 +markdown/extensions/legacy_attrs.py,sha256=oWcyNrfP0F6zsBoBOaD5NiwrJyy4kCpgQLl12HA7JGU,2788 +markdown/extensions/legacy_em.py,sha256=-Z_w4PEGSS-Xg-2-BtGAnXwwy5g5GDgv2tngASnPgxg,1693 +markdown/extensions/md_in_html.py,sha256=y4HEWEnkvfih22fojcaJeAmjx1AtF8N-a_jb6IDFfts,16546 +markdown/extensions/meta.py,sha256=v_4Uq7nbcQ76V1YAvqVPiNLbRLIQHJsnfsk-tN70RmY,2600 +markdown/extensions/nl2br.py,sha256=9KKcrPs62c3ENNnmOJZs0rrXXqUtTCfd43j1_OPpmgU,1090 +markdown/extensions/sane_lists.py,sha256=ogAKcm7gEpcXV7fSTf8JZH5YdKAssPCEOUzdGM3C9Tw,2150 +markdown/extensions/smarty.py,sha256=yqT0OiE2AqYrqqZtcUFFmp2eJsQHomiKzgyG2JFb9rI,11048 +markdown/extensions/tables.py,sha256=oTDvGD1qp9xjVWPGYNgDBWe9NqsX5gS6UU5wUsQ1bC8,8741 +markdown/extensions/toc.py,sha256=PGg-EqbBubm3n0b633r8Xa9kc6JIdbo20HGAOZ6GEl8,18322 +markdown/extensions/wikilinks.py,sha256=j7D2sozica6sqXOUa_GuAXqIzxp-7Hi60bfXymiuma8,3285 +markdown/htmlparser.py,sha256=dEr6IE7i9b6Tc1gdCLZGeWw6g6-E-jK1Z4KPj8yGk8Q,14332 +markdown/inlinepatterns.py,sha256=7_HF5nTOyQag_CyBgU4wwmuI6aMjtadvGadyS9IP21w,38256 +markdown/postprocessors.py,sha256=eYi6eW0mGudmWpmsW45hduLwX66Zr8Bf44WyU9vKp-I,4807 +markdown/preprocessors.py,sha256=pq5NnHKkOSVQeIo-ajC-Yt44kvyMV97D04FBOQXctJM,3224 +markdown/serializers.py,sha256=YtAFYQoOdp_TAmYGow6nBo0eB6I-Sl4PTLdLDfQJHwQ,7174 +markdown/test_tools.py,sha256=MtN4cf3ZPDtb83wXLTol-3q3aIGRIkJ2zWr6fd-RgVE,8662 +markdown/treeprocessors.py,sha256=o4dnoZZsIeVV8qR45Njr8XgwKleWYDS5pv8dKQhJvv8,17651 +markdown/util.py,sha256=vJ1E0xjMzDAlTqLUSJWgdEvxdQfLXDEYUssOQMw9kPQ,13929 diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/WHEEL b/.venv/Lib/site-packages/Markdown-3.7.dist-info/WHEEL new file mode 100644 index 00000000..71360e02 --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (72.2.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/entry_points.txt b/.venv/Lib/site-packages/Markdown-3.7.dist-info/entry_points.txt new file mode 100644 index 00000000..be3bd8ff --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/entry_points.txt @@ -0,0 +1,22 @@ +[console_scripts] +markdown_py = markdown.__main__:run + +[markdown.extensions] +abbr = markdown.extensions.abbr:AbbrExtension +admonition = markdown.extensions.admonition:AdmonitionExtension +attr_list = markdown.extensions.attr_list:AttrListExtension +codehilite = markdown.extensions.codehilite:CodeHiliteExtension +def_list = markdown.extensions.def_list:DefListExtension +extra = markdown.extensions.extra:ExtraExtension +fenced_code = markdown.extensions.fenced_code:FencedCodeExtension +footnotes = markdown.extensions.footnotes:FootnoteExtension +legacy_attrs = markdown.extensions.legacy_attrs:LegacyAttrExtension +legacy_em = markdown.extensions.legacy_em:LegacyEmExtension +md_in_html = markdown.extensions.md_in_html:MarkdownInHtmlExtension +meta = markdown.extensions.meta:MetaExtension +nl2br = markdown.extensions.nl2br:Nl2BrExtension +sane_lists = markdown.extensions.sane_lists:SaneListExtension +smarty = markdown.extensions.smarty:SmartyExtension +tables = markdown.extensions.tables:TableExtension +toc = markdown.extensions.toc:TocExtension +wikilinks = markdown.extensions.wikilinks:WikiLinkExtension diff --git a/.venv/Lib/site-packages/Markdown-3.7.dist-info/top_level.txt b/.venv/Lib/site-packages/Markdown-3.7.dist-info/top_level.txt new file mode 100644 index 00000000..0918c976 --- /dev/null +++ b/.venv/Lib/site-packages/Markdown-3.7.dist-info/top_level.txt @@ -0,0 +1 @@ +markdown diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/METADATA b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/METADATA new file mode 100644 index 00000000..dfe37d52 --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/METADATA @@ -0,0 +1,93 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 2.1.5 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/markupsafe/ +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + + >>> # escape replaces special characters and wraps in Markup + >>> escape("") + Markup('<script>alert(document.cookie);</script>') + + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup("Hello") + Markup('hello') + + >>> escape(Markup("Hello")) + Markup('hello') + + >>> # Markup is a str subclass + >>> # methods and operators escape their arguments + >>> template = Markup("Hello {name}") + >>> template.format(name='"World"') + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Chat: https://discord.gg/pallets diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/RECORD b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/RECORD new file mode 100644 index 00000000..1b43b962 --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/RECORD @@ -0,0 +1,14 @@ +MarkupSafe-2.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-2.1.5.dist-info/LICENSE.rst,sha256=RjHsDbX9kKVH4zaBcmTGeYIUM4FG-KyUtKV_lu6MnsQ,1503 +MarkupSafe-2.1.5.dist-info/METADATA,sha256=icNlaniV7YIQZ1BScCVqNaRtm7MAgfw8d3OBmoSVyAY,3096 +MarkupSafe-2.1.5.dist-info/RECORD,, +MarkupSafe-2.1.5.dist-info/WHEEL,sha256=j9Aissza3750LQHFAQyYerNjmkEON1-8w_RaZNFtKSs,102 +MarkupSafe-2.1.5.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=m1ysNeqf55zbEoJtaovca40ivrkEFolPlw5bGoC5Gi4,11290 +markupsafe/__pycache__/__init__.cpython-312.pyc,, +markupsafe/__pycache__/_native.cpython-312.pyc,, +markupsafe/_native.py,sha256=_Q7UsXCOvgdonCgqG3l5asANI6eo50EKnDM-mlwEC5M,1776 +markupsafe/_speedups.c,sha256=n3jzzaJwXcoN8nTFyA53f3vSqsWK2vujI-v6QYifjhQ,7403 +markupsafe/_speedups.cp312-win_amd64.pyd,sha256=CLz8k0mpvM-dgLP0eSHpGYHm8shlGxXoCinA12zgHsY,15872 +markupsafe/_speedups.pyi,sha256=f5QtwIOP0eLrxh2v5p6SmaYmlcHIGIfmz0DovaqL0OU,238 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL new file mode 100644 index 00000000..1c1a93de --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.42.0) +Root-Is-Purelib: false +Tag: cp312-cp312-win_amd64 + diff --git a/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/.venv/Lib/site-packages/MarkupSafe-2.1.5.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/INSTALLER b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/LICENSE b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/LICENSE new file mode 100644 index 00000000..2f1b8e15 --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017-2021 Ingy döt Net +Copyright (c) 2006-2016 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/METADATA b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/METADATA new file mode 100644 index 00000000..db029b77 --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/METADATA @@ -0,0 +1,46 @@ +Metadata-Version: 2.1 +Name: PyYAML +Version: 6.0.2 +Summary: YAML parser and emitter for Python +Home-page: https://pyyaml.org/ +Download-URL: https://pypi.org/project/PyYAML/ +Author: Kirill Simonov +Author-email: xi@resolvent.net +License: MIT +Project-URL: Bug Tracker, https://github.com/yaml/pyyaml/issues +Project-URL: CI, https://github.com/yaml/pyyaml/actions +Project-URL: Documentation, https://pyyaml.org/wiki/PyYAMLDocumentation +Project-URL: Mailing lists, http://lists.sourceforge.net/lists/listinfo/yaml-core +Project-URL: Source Code, https://github.com/yaml/pyyaml +Platform: Any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Cython +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup +Requires-Python: >=3.8 +License-File: LICENSE + +YAML is a data serialization format designed for human readability +and interaction with scripting languages. PyYAML is a YAML parser +and emitter for Python. + +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle +support, capable extension API, and sensible error messages. PyYAML +supports standard YAML tags and provides Python-specific tags that +allow to represent an arbitrary Python object. + +PyYAML is applicable for a broad range of tasks from complex +configuration files to object serialization and persistence. diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/RECORD b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/RECORD new file mode 100644 index 00000000..61653255 --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/RECORD @@ -0,0 +1,43 @@ +PyYAML-6.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +PyYAML-6.0.2.dist-info/LICENSE,sha256=jTko-dxEkP1jVwfLiOsmvXZBAqcoKVQwfT5RZ6V36KQ,1101 +PyYAML-6.0.2.dist-info/METADATA,sha256=9lwXqTOrXPts-jI2Lo5UwuaAYo0hiRA0BZqjch0WjAk,2106 +PyYAML-6.0.2.dist-info/RECORD,, +PyYAML-6.0.2.dist-info/WHEEL,sha256=c7SWG1_hRvc9HXHEkmWlTu1Jr4WpzRucfzqTP-_8q0s,102 +PyYAML-6.0.2.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11 +_yaml/__init__.py,sha256=04Ae_5osxahpJHa3XBZUAf4wi6XX32gR8D6X6p64GEA,1402 +_yaml/__pycache__/__init__.cpython-312.pyc,, +yaml/__init__.py,sha256=N35S01HMesFTe0aRRMWkPj0Pa8IEbHpE9FK7cr5Bdtw,12311 +yaml/__pycache__/__init__.cpython-312.pyc,, +yaml/__pycache__/composer.cpython-312.pyc,, +yaml/__pycache__/constructor.cpython-312.pyc,, +yaml/__pycache__/cyaml.cpython-312.pyc,, +yaml/__pycache__/dumper.cpython-312.pyc,, +yaml/__pycache__/emitter.cpython-312.pyc,, +yaml/__pycache__/error.cpython-312.pyc,, +yaml/__pycache__/events.cpython-312.pyc,, +yaml/__pycache__/loader.cpython-312.pyc,, +yaml/__pycache__/nodes.cpython-312.pyc,, +yaml/__pycache__/parser.cpython-312.pyc,, +yaml/__pycache__/reader.cpython-312.pyc,, +yaml/__pycache__/representer.cpython-312.pyc,, +yaml/__pycache__/resolver.cpython-312.pyc,, +yaml/__pycache__/scanner.cpython-312.pyc,, +yaml/__pycache__/serializer.cpython-312.pyc,, +yaml/__pycache__/tokens.cpython-312.pyc,, +yaml/_yaml.cp312-win_amd64.pyd,sha256=Bx7e_LEQx7cnd1_A9_nClp3X77g-_Lw1aoAAtYZbwWk,263680 +yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883 +yaml/constructor.py,sha256=kNgkfaeLUkwQYY_Q6Ff1Tz2XVw_pG1xVE9Ak7z-viLA,28639 +yaml/cyaml.py,sha256=6ZrAG9fAYvdVe2FK_w0hmXoG7ZYsoYUwapG8CiC72H0,3851 +yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837 +yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006 +yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533 +yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445 +yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061 +yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440 +yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495 +yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794 +yaml/representer.py,sha256=IuWP-cAW9sHKEnS0gCqSa894k1Bg4cgTxaDwIcbRQ-Y,14190 +yaml/resolver.py,sha256=9L-VYfm4mWHxUD1Vg4X7rjDRK_7VZd6b92wzq7Y2IKY,9004 +yaml/scanner.py,sha256=YEM3iLZSaQwXcQRg2l2R4MdT0zGP2F9eHkKGKnHyWQY,51279 +yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165 +yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573 diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/WHEEL b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/WHEEL new file mode 100644 index 00000000..a4e7d83d --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.44.0) +Root-Is-Purelib: false +Tag: cp312-cp312-win_amd64 + diff --git a/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/top_level.txt b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/top_level.txt new file mode 100644 index 00000000..e6475e91 --- /dev/null +++ b/.venv/Lib/site-packages/PyYAML-6.0.2.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_yaml +yaml diff --git a/.venv/Lib/site-packages/__pycache__/_virtualenv.cpython-312.pyc b/.venv/Lib/site-packages/__pycache__/_virtualenv.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28c3f272aa63b9df9dcaf47fff8e72a12c7318a5 GIT binary patch literal 4220 zcma)9Z)_CD6`%ccxAzyHjsHNv_JYCYQaCqCNCF}T7n?s4xCA?Cav@nQw`+UPd$-q_ zIU8Gd#HoXatceB_Bge+DQFkW01{;NUoB6=(nS;L`D0dZ}x8Q z93X1vq?tEwX5PFv``+)p`)fEHK+rCIbaU{>wFrI9CT{bT2yXSyKujYI#gWEoyve2b zIL|R!Fon3_jAC4bQ8Ya%Z`{ivT}ZBT#Z<>6-0*PI{a3gWFCNf5=TJPTdE+4-9Y&gT z4r#tCe0epji^)>6D(PvA;91QO*vk>9j>vYFKH~2Xi0EW-?eO zBvH1KX5SW}{ z-!LU-Gco7N?|c{L+u%9e>VJTEpPNQJdPmBkA$aNEa36UMl;eNP{esI2@a~m2u6`Yj zyHe)nMUBsiqX<7sE8mcc?#`swrK)4nU!`4&I#I}G$&kydj_zH9aFfRGg9T0KL9e$U zl=o<2&hr8KHJ|t9yi5Z^3SwuOZA4NTVwp9Lzwig^2-Yx2} zr40CpX`BYaRH;J@>#C+>VoM}}jSMBWsHs%7edWVS)MwWW=~S^YEG87qNKm`s<)bGD zUg|#9+xN0^qI=-r5#`X)W4$(S!Rd@jhiyqcO&mfX;{^LaS6j$f8IUCs-5j(<@C{;n zN5)Dc#8=j&SYrFc(<;$zVMHId8!b~)GAbszQgS)P@ioHav2cJk`Cxa?-cuQDCG`Y7 z1%7-gHVR>V>X>o*6fvm2E2Abx)FGXmQp!;etKjN(-J^0R+Ck;SFqlYaY@cZ*RFibY z9^Kan*OQ+?_peEGr?%s=IA7a!ncl4Jx;DB{+co7~u4`PXYhS2qpB-PUdumEr39c`U zEd*Qc%Dex7KNp}Bir zeBz&Cz|&aVfOd9G_AH4F3u41Ar$v$UQIa1#l5R>et<{GmXt#brtrk! zZaJk>Rc4+CK*4zBbWlP|$6_Nr~ZE|nV`H~x4x;koNWxqe?$Gj${In9#~&`s{1$DhjuD(8Z5E(EqSXMU)q zgTQB={!q(@a=~0E%K?sWahE7_cc-~;!>pv+UGDek0d{+HAkWq33X3Ob@S4ug<-?2l zGu7I1KbWe*y~EM z2k9rqsu|qDn9{IHR7$b!WtZ#NmLTge28Pf;ILbN}miD@CU^1lBdoi|PA7BmJ7Y$>E z%=ibat7AL86w-@Mag1?xv5s9|x=wVg4j4p9>tl+VF-lr0C8Hqm*do)Ku$W?rrqUer zbYx7_mVqZ$dB)wao9uxaViGL}*WYUDxEbuY+;jE#-0_8--QNJ5KQq1O!k(X>ovpoD zv-Qh}ywW63pS^H)v8kgV7DK4EVcLJezZ8)dBJyngtw{T~q3BnkAFcp@Wx1wdD(u+j+!_twZa8HJlrkzQiXBpv zpTfU5rUJ|)MSC7qr-Ekl58e68o`HQV2TfB zDHPwJA@fGe{xjoxXQ})b2;k5GxDs}WNy|txuVN)H9E!00TUqD$7n5!KS+xTNG8Eii zDA#pN@lm#e6=jZ_J@D--`Cb=hp3nZ}wx57)PegV}NUc4xM L;J=NwIv4*JR#V;s literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/__pycache__/ghp_import.cpython-312.pyc b/.venv/Lib/site-packages/__pycache__/ghp_import.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f731523855f2900eb043de0033cc06e61ce6fe95 GIT binary patch literal 14812 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 Qg8I0^(ca8{+(bkEKWrJKW&i*H literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/__pycache__/six.cpython-312.pyc b/.venv/Lib/site-packages/__pycache__/six.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc5249c72c9054be745883fb413b2582bff9639c GIT binary patch literal 41160 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%0D)tI zcL92ayH#txIJNin({G)AM|=;1GMaBIHQ$Y=VnWTVur96nZn|+U-u_5@^COA!)3?f3 z$9)~teD|9^LG$f2O+QVorjvK7ljy|aP1I!2zYw+YR%#gZkr4tu#8)w8z+r6wVYLe` z!R^!N!uhZ6*)+=LwKv2)P9PRnu4jnY4^`bO0|xSgw=a$H9_Zhb5!)XfT; z(sJDPPE)+|$@ums6Xk(hn z5x2knJ1d6uoE3~Jq(KW%5jk($4&SR#&Mb$inax_$yxzpY`Eir0;M=7Ds1uA(Jg(K6GP zsMr=0O6N-(qg`{QjTotC@)M;SpfJo=u9~vXRj!IxuEJnjxg#c&<%o#BmX~7%(TM6Z zS?icXWoVeV%&(Mt{h@?s^?28vqLtCgxuTWvqLr^-P86*jKXj+CA!?s1Y={>&yxx~6 z^gVNs3hkv7Sc0|WtIbTykE>`h(;7<@ZOlvy`!m*$AN)YDPgKTB_Rk6jz^REP@v=j+ z!eR1O-Etfvo*gj}4!(}k*D(`@30@plh@w00!twp@i$(LEWfK=)x^nf(tEX^)e$LYv z_cY>yJUf0$dIgn{&K6FuOL!UpEUKC-s*M-bjvtyYEFC}izUZcVx^No-LLRO>x_jR|7X~HMf?p!@=ZR6{{y)x0bBG>iJ+fF5ba+J$<)a^$>%K z7VrZn9VYD0AK#B3Pa0>UvV?fG^iE-I)G=3B8^=tr`Ay&Jz8iIk!p%fS$$VAqTvbcF z3K_SIcTHU4B;2ZMjfv&AN}9%x+$#5tA0ze@;Yavpg_<-k(l)grSJN(Xwvw}hG3ypK z?si`9p6q^of5NqDyz>(gzh3@vWxjO-4QKfu3Rb6hSFl>G$wIJp&QcP$ltlMNABb5h zUah}rslFvT7|zFpvrqu(N3!`v(X#8+lhvyx@M;Jtvgj6iTC~-xF$noIJQ(C|v%LV0JWrP+r9h zR$n-fwBqxp$vqyyUW6c1)hFn$sxVnFRs9sT$$`gB1U+sd@NxXk8(ru0ot^HH4Z;ss sm@nFdA2ymVRtO(&a97fK6rTNc90$k5!A;EHf~crXW1v3>5JE&GB+$f24Jv9BwA$>9({-HPbatIK z=~{}~9*l$pktzjLP^eU?pj0J2)jbvU+DjbM+TEs7BzoayHN6y7YTp`foL2O2q}li8 z{e17uym_0=Vnr!;El6GXS9DTQjvXoi@Qra$pWX|PI2Gu)xX;YV(qWQ=jRZhhJj zGlqf*b$H#t#1Sd6vQ$@DFBhObm>kUYDoA0+Opdh}Pj55UhHaYnqz#((&Z{9pi**kg zwo%%@Nl|BQX0eVx#^gBt-v5YJtJ|LuH=@02Gf%5Rj<;Gp51aQQV|Kg;A=(KUZuPVc zYV(-ugr#SlV?n}TE{bxz&G(?Ig368|mAw>3C@1{QE(Onfj=i#tM>#Gh=*KplW?Lhk z$ECM#ug1Tiy7%`l!)~&D-o5aupt1}a zLOinBA*dV!Gbg--V&cr9ZqwApbm*!~mPkfQ>P^13(PA4tNU)?>lG{XyaEn&iza^ew5`KQE1DE$HX0j-?oT;Y=*#G;5}&o0bA54nM6- zWE{aoHl6078b;FX)sSj{4b7^S`~=x)8LH#f^g=CRhszLsv#l|jhJ>8JhPOeT&}k3K zpuLoWgw?Rq3>i>Mo>1tx!y2aJtG_Xhj}p_!Op%zMx@DyBMk2?DNlM9PEQg2Z#{~R0 zv<#M?q%G7I4hI?pUvWI!7oF*S>HO)BcR zGDgf1_c&xw$pDdAEvs*n8I~MNa1XD$!?etGDTLG@gHD?L^;qt^G?cUlZ#w zgl|KM<<|Z@Uu^CFDcDvH?kWa%m4gS1!GlZu60QVK6fS&q@ym;av&$`KDlMU_=P#dM z7ueRFRmA#tt~a4jd!DNVf*&gXmA+B)VFbBT}JKZ$-6 zE$=x}+;gNL6mq4u!Tjk;xU(FN7sK&SU%Gev?(y=0Q^fWBmNe~Nn#Yt^`m)&5)Bc21~bB%%kwBaty= (3, 6) else ImportError + raise exc("No module named '_yaml'") +else: + from yaml._yaml import * + import warnings + warnings.warn( + 'The _yaml extension module is now located at yaml._yaml' + ' and its location is subject to change. To use the' + ' LibYAML-based parser and emitter, import from `yaml`:' + ' `from yaml import CLoader as Loader, CDumper as Dumper`.', + DeprecationWarning + ) + del warnings + # Don't `del yaml` here because yaml is actually an existing + # namespace member of _yaml. + +__name__ = '_yaml' +# If the module is top-level (i.e. not a part of any specific package) +# then the attribute should be set to ''. +# https://docs.python.org/3.8/library/types.html +__package__ = '' diff --git a/.venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/_yaml/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..092b5d3cb811fb0c8332befc374251188c10ab56 GIT binary patch literal 835 zcmYjP&rcLF6mDl`cV~ZrK#&+UDW_!(EJqD7CWe)0!g3-pE|YX;w`CcanQq!Hu$;h) z9=-W5Xo$w6|AQAq4^m@dq8Dy!@I*Y=&PcF_w%>c-_uiYY^PyZW0KNXaJzn3-0Pw?r zi=}b0&R*!_B_M#n5Hx`WD5QW`#6GlBf|$}dC$u8FX+uD5lG*YA;1+daNHfi>R%A)` z5T@*>P_uJk?u`Z0nr_q840m%p&Huj>mlh7KGy=hzOY+SkDKtw1SS_BK@QS*E@lGH& za2T`)eiUN7RE4UvO}PkIjDvWcRjpGq=xJ7Ods8b6MU3=Aief*a1XZw+RkR4++B;d@ zpeP9-x+`gHYFy9*fnv6ULe}x6*7*_{VJ&6*F+qV8Y1W7|TlCwTv?GyZsI%e6U0OqE zm7%_%Na{ArLHo)5#`0X-7rI=}=Yn!%>d+{VlJZ#;L_NkOTIVc6Ez_*EfLaMM;3B=a z%zR>`0;RWEv{>&)y)=~GS~ZnP234S1R*sRYT$f5;O0H}%5Zuw`sEJ16%nFlBtRIsH zoHMS9kCHJ`VAI`>DqMcJa(8?l2XR*@$K2F-o%T4@7HJb6rzz!PY`n%;6*2Dloh`qs z!E11)dxG;j^#!lTnX$?vtmDA81TkEd^cEZls*w!e5%C?Abf zJ{4w;oSC1_jjztc7iVn$;j_j;V`$m=IvlznfBknco5>DGKz>Za(!{>2kI}J%BA?RT F{sL(W{Tl!P literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/INSTALLER b/.venv/Lib/site-packages/click-8.1.7.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/LICENSE.rst b/.venv/Lib/site-packages/click-8.1.7.dist-info/LICENSE.rst new file mode 100644 index 00000000..d12a8491 --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/METADATA b/.venv/Lib/site-packages/click-8.1.7.dist-info/METADATA new file mode 100644 index 00000000..7a6bbb24 --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/METADATA @@ -0,0 +1,103 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.1.7 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: colorama ; platform_system == "Windows" +Requires-Dist: importlib-metadata ; python_version < "3.8" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Chat: https://discord.gg/pallets diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/RECORD b/.venv/Lib/site-packages/click-8.1.7.dist-info/RECORD new file mode 100644 index 00000000..95ff8c6c --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/RECORD @@ -0,0 +1,39 @@ +click-8.1.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.7.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.7.dist-info/METADATA,sha256=qIMevCxGA9yEmJOM_4WHuUJCwWpsIEVbCPOhs45YPN4,3014 +click-8.1.7.dist-info/RECORD,, +click-8.1.7.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92 +click-8.1.7.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click/__init__.py,sha256=YDDbjm406dTOA0V8bTtdGnhN7zj5j-_dFRewZF_pLvw,3138 +click/__pycache__/__init__.cpython-312.pyc,, +click/__pycache__/_compat.cpython-312.pyc,, +click/__pycache__/_termui_impl.cpython-312.pyc,, +click/__pycache__/_textwrap.cpython-312.pyc,, +click/__pycache__/_winconsole.cpython-312.pyc,, +click/__pycache__/core.cpython-312.pyc,, +click/__pycache__/decorators.cpython-312.pyc,, +click/__pycache__/exceptions.cpython-312.pyc,, +click/__pycache__/formatting.cpython-312.pyc,, +click/__pycache__/globals.cpython-312.pyc,, +click/__pycache__/parser.cpython-312.pyc,, +click/__pycache__/shell_completion.cpython-312.pyc,, +click/__pycache__/termui.cpython-312.pyc,, +click/__pycache__/testing.cpython-312.pyc,, +click/__pycache__/types.cpython-312.pyc,, +click/__pycache__/utils.cpython-312.pyc,, +click/_compat.py,sha256=5318agQpbt4kroKsbqDOYpTSWzL_YCZVUQiTT04yXmc,18744 +click/_termui_impl.py,sha256=3dFYv4445Nw-rFvZOTBMBPYwB1bxnmNk9Du6Dm_oBSU,24069 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=j6oEWtGgGna8JarD6WxhXmNnxLnfRjwXglbBc-8jr7U,114086 +click/decorators.py,sha256=-ZlbGYgV-oI8jr_oH4RpuL1PFS-5QmeuEAsLDAYgxtw,18719 +click/exceptions.py,sha256=fyROO-47HWFDjt2qupo7A3J32VlpM-ovJnfowu92K3s,9273 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961 +click/parser.py,sha256=LKyYQE9ZLj5KgIDXkrcTHQRXIggfoivX14_UVIn56YA,19067 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=Ty3VM_ts0sQhj6u7eFTiLwHPoTgcXTGEAUg2OpLqYKw,18460 +click/termui.py,sha256=H7Q8FpmPelhJ2ovOhfCRhjMtCpNyjFXryAMLZODqsdc,28324 +click/testing.py,sha256=1Qd4kS5bucn1hsNIRryd0WtTMuCpkA93grkWxT8POsU,16084 +click/types.py,sha256=TZvz3hKvBztf-Hpa2enOmP4eznSPLzijjig5b_0XMxE,36391 +click/utils.py,sha256=1476UduUNY6UePGU4m18uzVHLt1sKM2PP3yWsQhbItM,20298 diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/WHEEL b/.venv/Lib/site-packages/click-8.1.7.dist-info/WHEEL new file mode 100644 index 00000000..2c08da08 --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/click-8.1.7.dist-info/top_level.txt b/.venv/Lib/site-packages/click-8.1.7.dist-info/top_level.txt new file mode 100644 index 00000000..dca9a909 --- /dev/null +++ b/.venv/Lib/site-packages/click-8.1.7.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/.venv/Lib/site-packages/click/__init__.py b/.venv/Lib/site-packages/click/__init__.py new file mode 100644 index 00000000..9a1dab04 --- /dev/null +++ b/.venv/Lib/site-packages/click/__init__.py @@ -0,0 +1,73 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.7" diff --git a/.venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8369f5b1ebc245f139a2033295597c6a33584fbe GIT binary patch literal 2672 zcmY+_OHUhD6bJAz_=Rm=AtdBMm_QO@9_A6kD+GcKB(y1@1U5%Vqw#pKr`(T1DMdUG#sBd9*D4{O+0in7O|8{M6f<)A0Atk3XN43!3&D zH!lCWF7SDzThqSRY8q*^M6JtBcwN+$V0Xja)GbcJNlJ=SaEemmG@PciI0I)WBhJEE z%8Gm79_kV2;2h<|c{lGBs30!Dz0@o2h5M*a+z0nlzqlVBpaJm!JV=A$LHGvU5Z{1@ zXh=K+-=v%3oA59Vi-+M`bW428z3q+Ai1;>qhwg|+;Jb8JdBjy0PCcS$J~eBIE{;Sc!DOx58X%JV|pwecb|BZG%22NpL#_qiXXvK zG$novPt&yc2|PnH;z@XxX2nn85|zY7c#h`8Q}8^^i>KiQS`g2`i?k@7g`d$gaS2|c zCGnj5+*_t)@jSdjE8+!sl~%=z@EWa&pTX<2E?$CP&qqBtBk*-Es5Q}Y{3vvkUDK=Qdfc$} zD6Y9qRS&{AG*x8laiDwV2RrvkIkDr{bt~{Z)352S{`xLK@%gdZe;stA4{6CUJL9<_k)-xxAjj>+`zI}w`n!7c-^sd zUeSqixE=SuonRPB1czK^zw z{=f2eHBkJ317)*zxl<>RS+`N^L#^|8mz4r4|9#9pIX=7JSoYOyBS ztP;uQr!3btd84rNvfcbFw$%uXkB*7$tV^$?U32)!GnmwBNdL5JHhrssVk$J75${1h zR6$+YQB>{pK+_B5L_|Czca7q6m%C<~{w0&;!^5{Ir7MlVvG`(k$BgY`$73gXkMKXW z_x5o67|89pff>IuecATz{R1v$_x-C<=WHFHhcf)gjQJkZ?~mW@AH3#?j+^-A0{N4J zqj!gu-S_WzchF3pob1d0i(BnKlbtoru)dG8$|HD7%`h}-4)53?H>-|ss&gZXm2G+` z_H&Uxg6mRG5Zb=X^KELiv`|_(D86lF45JoUhS5smtlA2%UQH!AQXFZH3`druhlAhX zDvxO8t`2yl@HW>}FGn9oKgR&aAjb`kAI!yLB|t(<*%4kLA&t0NqDIPP-X4AIJUwuOJcl+M+MT+P(oplZ628s}Czl+&dqq=B>PH68VcJ3r=l!ZFG5l%vQo z#WBq>!!gTI;+R9UQZYWwNX>I$fn$;58OIXGbB<+>6^>PoHI8+T7aSWLFA=R&Gj?#N zn_Sr9c*U{JQRb*1T6x2`{Qet1XrEEi{$AZ#KgE&$8ozm``0P$gA8r5R>076I8ac5& z8=BS!d|jebi(eCShT-^5Y#62R{O{~W=MAx`-eDsCv5kH~{L!6AB>wD5C6a#?w8Ugv zn`vv0+S;n5-quQOZM>~LmHJd$E4Q^LZEaD2;*!+Yr9bK$0u(VE1JQ)%+uE`;x5StY zJyFNx0MM} D<$Cfh literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7aaf77e48e0a9ec27cb120b0d80a5acb76de5efb GIT binary patch literal 27416 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 bdnoWb>U+Q+rb4Uzr9h+@i2Q?K<7D^`nTjX) literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05c68df5c924f7c4a245aabc7ace617b8a93d96a GIT binary patch literal 11952 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c767a8c0996d9c4ccb3df7d990e1d8cfae0b481 GIT binary patch literal 135630 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27a9c045e5d043af690b5f3b093df3e9290ffcfe GIT binary patch literal 14707 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fcbf53a94b6b77252fbc118880bdbd6028900e8 GIT binary patch literal 14032 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 Z5Ln;*?(fULE5C1Tf9*Se$F+9Ue*m@6;-LTl literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a11abfb6b61864431d13a4960ecc7b17f2e2e224 GIT binary patch literal 21450 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 Nlw-#u2ih`p{6Fo7(K!GB literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc b/.venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..292d4be18c673ce0d6ad29084ed71e230b42ae6d GIT binary patch literal 32761 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 RrROKxE}gntfEdPi{y(IrhF<^x literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/click/_compat.py b/.venv/Lib/site-packages/click/_compat.py new file mode 100644 index 00000000..23f88665 --- /dev/null +++ b/.venv/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( # noqa: F811 + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO[t.Any]) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.Optional[t.TextIO]], + wrapper_func: t.Callable[[], t.TextIO], +) -> t.Callable[[], t.Optional[t.TextIO]]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.Optional[t.TextIO]: + stream = src_func() + + if stream is None: + return None + + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/.venv/Lib/site-packages/click/_termui_impl.py b/.venv/Lib/site-packages/click/_termui_impl.py new file mode 100644 index 00000000..f7446577 --- /dev/null +++ b/.venv/Lib/site-packages/click/_termui_impl.py @@ -0,0 +1,739 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ +from io import StringIO +from types import TracebackType + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label: str = label or "" + + if file is None: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + file = StringIO() + + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width: int = width + self.autowidth: bool = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter: t.Iterable[V] = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.last_eta: float + self.start: float + self.start = self.last_eta = time.time() + self.eta_known: bool = False + self.finished: bool = False + self.max_width: t.Optional[int] = None + self.entered: bool = False + self.current_item: t.Optional[V] = None + self.is_hidden: bool = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar[V]": + self.entered = True + self.render_progress() + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if stdout is None: + stdout = StringIO() + + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + return _tempfilepager(generator, pager_cmd, color) + return _pipepager(generator, pager_cmd, color) + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if WIN or sys.platform.startswith("os2"): + return _tempfilepager(generator, "more <", color) + if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: + return _pipepager(generator, "less", color) + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: + return _pipepager(generator, "more", color) + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) + try: + for text in generator: + if not color: + text = strip_ansi(text) + + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): + pass + else: + stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: + """Page through text by invoking a program on a temporary file.""" + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + os.system(f'{cmd} "{filename}"') + finally: + os.close(fd) + os.unlink(filename) + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if os.system(f"which {editor} >/dev/null 2>&1") == 0: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url.replace('"', "")) + args = f'explorer /select,"{url}"' + else: + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' + return os.system(args) + elif CYGWIN: + if locate: + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' + else: + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' + return os.system(args) + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import tty + import termios + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/.venv/Lib/site-packages/click/_textwrap.py b/.venv/Lib/site-packages/click/_textwrap.py new file mode 100644 index 00000000..b47dcbd4 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/click/_winconsole.py b/.venv/Lib/site-packages/click/_winconsole.py new file mode 100644 index 00000000..6b20df31 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/click/core.py b/.venv/Lib/site-packages/click/core.py new file mode 100644 index 00000000..cc65e896 --- /dev/null +++ b/.venv/Lib/site-packages/click/core.py @@ -0,0 +1,3042 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat +from types import TracebackType + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.MutableMapping[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.MutableMapping[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[ + t.Callable[[str], str] + ] = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional["Context"] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + @t.overload + def invoke( + __self, # noqa: B902 + __callback: "t.Callable[..., V]", + *args: t.Any, + **kwargs: t.Any, + ) -> V: + ... + + @t.overload + def invoke( + __self, # noqa: B902 + __callback: "Command", + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: + ... + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", "t.Callable[..., V]"], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Union[t.Any, V]: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = t.cast("t.Callable[..., V]", other_cmd.callback) + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.MutableMapping[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, info_name=info_name, parent=parent, **extra # type: ignore + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invocable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt) as e: + echo(file=sys.stderr) + raise Abort() from e + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + + .. versionchanged:: 8.2.0 + Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). + """ + if complete_var is None: + complete_name = prog_name.replace("-", "_").replace(".", "_") + complete_var = f"_{complete_name}_COMPLETE".upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List["Parameter"] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + return Option( + help_options, + is_flag=True, + is_eager=True, + expose_value=False, + callback=show_help, + help=_("Show this message and exit."), + ) + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + if self.help is not None: + # truncate the help text to the first form feed + text = inspect.cleandoc(self.help).partition("\f")[0] + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + :param attrs: Other command arguments described in :class:`Command`. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[ + t.Union[t.MutableMapping[str, Command], t.Sequence[Command]] + ] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.MutableMapping[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: + ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: + ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": + ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: + ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + + See :class:`MultiCommand` and :class:`Command` for the description of + ``name`` and ``attrs``. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The latter is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name: t.Optional[str] + self.opts: t.List[str] + self.secondary_opts: t.List[str] + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type: types.ParamType = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator[t.Any]: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + + def convert(value: t.Any) -> t.Any: + return self.type(value, param=self, ctx=ctx) + + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + :param attrs: Other command arguments described in :class:`Parameter`. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + self.default: t.Union[t.Any, t.Callable[[], t.Any]] + + if is_flag and default_is_missing and not self.required: + if multiple: + self.default = () + else: + self.default = False + + if flag_value is None: + flag_value = not self.default + + self.type: types.ParamType + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag: bool = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError("Could not determine name for option") + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if self.default else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return t.cast(Option, param).flag_value + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the constructor of :class:`Parameter`. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Could not determine name for argument") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/.venv/Lib/site-packages/click/decorators.py b/.venv/Lib/site-packages/click/decorators.py new file mode 100644 index 00000000..d9bba950 --- /dev/null +++ b/.venv/Lib/site-packages/click/decorators.py @@ -0,0 +1,561 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") +T = t.TypeVar("T") +_AnyCallable = t.Callable[..., t.Any] +FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) + + +def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(new_func, f) + + +def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + +def make_pass_decorator( + object_type: t.Type[T], ensure: bool = False +) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + ctx = get_current_context() + + obj: t.Optional[T] + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + return decorator # type: ignore[return-value] + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator # type: ignore[return-value] + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +# variant: no call, directly as decorator for a function. +@t.overload +def command(name: _AnyCallable) -> Command: + ... + + +# variant: with positional name and with positional or keyword cls argument: +# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) +@t.overload +def command( + name: t.Optional[str], + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: + ... + + +# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) +@t.overload +def command( + name: None = None, + *, + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: + ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def command( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Command]: + ... + + +def command( + name: t.Union[t.Optional[str], _AnyCallable] = None, + cls: t.Optional[t.Type[CmdType]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = t.cast(t.Type[CmdType], Command) + + def decorator(f: _AnyCallable) -> CmdType: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + if t.TYPE_CHECKING: + assert cls is not None + assert not callable(name) + + cmd = cls( + name=name or f.__name__.lower().replace("_", "-"), + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +GrpType = t.TypeVar("GrpType", bound=Group) + + +# variant: no call, directly as decorator for a function. +@t.overload +def group(name: _AnyCallable) -> Group: + ... + + +# variant: with positional name and with positional or keyword cls argument: +# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) +@t.overload +def group( + name: t.Optional[str], + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: + ... + + +# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) +@t.overload +def group( + name: None = None, + *, + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: + ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def group( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Group]: + ... + + +def group( + name: t.Union[str, _AnyCallable, None] = None, + cls: t.Optional[t.Type[GrpType]] = None, + **attrs: t.Any, +) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if cls is None: + cls = t.cast(t.Type[GrpType], Group) + + if callable(name): + return command(cls=cls, **attrs)(name) + + return command(name, cls, **attrs) + + +def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument( + *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default argument class, refer to :class:`Argument` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Argument + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def option( + *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default option class, refer to :class:`Option` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Option + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + message % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/.venv/Lib/site-packages/click/exceptions.py b/.venv/Lib/site-packages/click/exceptions.py new file mode 100644 index 00000000..fe68a361 --- /dev/null +++ b/.venv/Lib/site-packages/click/exceptions.py @@ -0,0 +1,288 @@ +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .utils import echo +from .utils import format_filename + +if t.TYPE_CHECKING: + from .core import Command + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + + echo(_("Error: {message}").format(message=self.format_message()), file=file) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd: t.Optional["Command"] = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename: str = format_filename(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code: int = code diff --git a/.venv/Lib/site-packages/click/formatting.py b/.venv/Lib/site-packages/click/formatting.py new file mode 100644 index 00000000..ddd2a2f8 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/click/globals.py b/.venv/Lib/site-packages/click/globals.py new file mode 100644 index 00000000..480058f1 --- /dev/null +++ b/.venv/Lib/site-packages/click/globals.py @@ -0,0 +1,68 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/.venv/Lib/site-packages/click/parser.py b/.venv/Lib/site-packages/click/parser.py new file mode 100644 index 00000000..5fa7adfa --- /dev/null +++ b/.venv/Lib/site-packages/click/parser.py @@ -0,0 +1,529 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes: t.Set[str] = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: t.Any, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List["CoreParameter"] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args: bool = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options: bool = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we recombine the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/.venv/Lib/site-packages/click/py.typed b/.venv/Lib/site-packages/click/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/.venv/Lib/site-packages/click/shell_completion.py b/.venv/Lib/site-packages/click/shell_completion.py new file mode 100644 index 00000000..dc9e00b9 --- /dev/null +++ b/.venv/Lib/site-packages/click/shell_completion.py @@ -0,0 +1,596 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value: t.Any = value + self.type: str = type + self.help: t.Optional[str] = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + %(complete_func)s "$@" +else + # eval/source/. command, register function for later + compdef %(complete_func)s %(prog_name)s +fi +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + @staticmethod + def _check_version() -> None: + import subprocess + + output = subprocess.run( + ["bash", "-c", 'echo "${BASH_VERSION}"'], stdout=subprocess.PIPE + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + echo( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ), + err=True, + ) + else: + echo( + _("Couldn't detect Bash version, shell completion is not supported."), + err=True, + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: ShellCompleteType, name: t.Optional[str] = None +) -> ShellCompleteType: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + return cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + # Will be None if expose_value is False. + value = ctx.params.get(param.name) + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + args: t.List[str], +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + sub_ctx = ctx + + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/.venv/Lib/site-packages/click/termui.py b/.venv/Lib/site-packages/click/termui.py new file mode 100644 index 00000000..db7a4b28 --- /dev/null +++ b/.venv/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) # noqa: B306 + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + + # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor + echo("\033[2J\033[1;1H", nl=False) + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/.venv/Lib/site-packages/click/testing.py b/.venv/Lib/site-packages/click/testing.py new file mode 100644 index 00000000..e0df0d2a --- /dev/null +++ b/.venv/Lib/site-packages/click/testing.py @@ -0,0 +1,479 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(input) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env: t.Mapping[str, t.Optional[str]] = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) + os.chdir(dt) + + try: + yield dt + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: # noqa: B014 + pass diff --git a/.venv/Lib/site-packages/click/types.py b/.venv/Lib/site-packages/click/types.py new file mode 100644 index 00000000..2b1d1797 --- /dev/null +++ b/.venv/Lib/site-packages/click/types.py @@ -0,0 +1,1089 @@ +import os +import stat +import sys +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import format_filename +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name: str = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = sys.getfilesystemencoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats: t.Sequence[str] = formats or [ + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%d %H:%M:%S", + ] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type[t.Any]] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Starting with Click 2.0, files can also be opened atomically in which + case all writes go into a separate file in the same folder and upon + completion the file will be moved over to the original location. This + is useful if a file regularly read by other users is modified. + + See :ref:`file-args` for more information. + """ + + name = "filename" + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: "t.Union[str, os.PathLike[str]]") -> bool: + if self.lazy is not None: + return self.lazy + if os.fspath(value) == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, + value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> t.IO[t.Any]: + if _is_file_like(value): + return value + + value = t.cast("t.Union[str, os.PathLike[str]]", value) + + try: + lazy = self.resolve_lazy_flag(value) + + if lazy: + lf = LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + if ctx is not None: + ctx.call_on_close(lf.close_intelligently) + + return t.cast(t.IO[t.Any], lf) + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: # noqa: B014 + self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": + return hasattr(value, "read") or hasattr(value, "write") + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``path_type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type[t.Any]] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name: str = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result( + self, value: "t.Union[str, os.PathLike[str]]" + ) -> "t.Union[str, bytes, os.PathLike[str]]": + if self.type is not None and not isinstance(value, self.type): + if self.type is str: + return os.fsdecode(value) + elif self.type is bytes: + return os.fsencode(value) + else: + return t.cast("os.PathLike[str]", self.type(value)) + + return value + + def convert( + self, + value: "t.Union[str, os.PathLike[str]]", + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> "t.Union[str, bytes, os.PathLike[str]]": + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} '{filename}' is a directory.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type[t.Any], ParamType]]) -> None: + self.types: t.Sequence[ParamType] = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/.venv/Lib/site-packages/click/utils.py b/.venv/Lib/site-packages/click/utils.py new file mode 100644 index 00000000..d536434f --- /dev/null +++ b/.venv/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: # noqa: E402 + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO[t.Any]) -> None: + self._file: t.IO[t.Any] = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + return + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO[t.Any]: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast( + t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) + ) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO[t.Any], KeepOpenFile(f)) + + return f + + +def format_filename( + filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", + shorten: bool = False, +) -> str: + """Format a filename as a string for display. Ensures the filename can be + displayed by replacing any invalid bytes or surrogate escapes in the name + with the replacement character ``�``. + + Invalid bytes or surrogate escapes will raise an error when written to a + stream with ``errors="strict". This will typically happen with ``stdout`` + when the locale is something like ``en_GB.UTF-8``. + + Many scenarios *are* safe to write surrogates though, due to PEP 538 and + PEP 540, including: + + - Writing to ``stderr``, which uses ``errors="backslashreplace"``. + - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens + stdout and stderr with ``errors="surrogateescape"``. + - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. + - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. + Python opens stdout and stderr with ``errors="surrogateescape"``. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + else: + filename = os.fspath(filename) + + if isinstance(filename, bytes): + filename = filename.decode(sys.getfilesystemencoding(), "replace") + else: + filename = filename.encode("utf-8", "surrogateescape").decode( + "utf-8", "replace" + ) + + return filename + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no effect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO[t.Any]) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + # It is set to "" inside a Shiv or PEX zipapp. + if getattr(_main, "__package__", None) in {None, ""} or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/.venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA new file mode 100644 index 00000000..a1b5c575 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD new file mode 100644 index 00000000..cd6b130d --- /dev/null +++ b/.venv/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-312.pyc,, +colorama/__pycache__/ansi.cpython-312.pyc,, +colorama/__pycache__/ansitowin32.cpython-312.pyc,, +colorama/__pycache__/initialise.cpython-312.pyc,, +colorama/__pycache__/win32.cpython-312.pyc,, +colorama/__pycache__/winterm.cpython-312.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-312.pyc,, +colorama/tests/__pycache__/ansi_test.cpython-312.pyc,, +colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc,, +colorama/tests/__pycache__/initialise_test.cpython-312.pyc,, +colorama/tests/__pycache__/isatty_test.cpython-312.pyc,, +colorama/tests/__pycache__/utils.cpython-312.pyc,, +colorama/tests/__pycache__/winterm_test.cpython-312.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/.venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL new file mode 100644 index 00000000..d79189fd --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt b/.venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt new file mode 100644 index 00000000..3105888e --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/__init__.py b/.venv/Lib/site-packages/colorama/__init__.py new file mode 100644 index 00000000..383101cd --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bfda9084ae4a30a17e885409fd94dcb586620641 GIT binary patch literal 456 zcmXv~J4*vW5Z=x0T`sxALKL*OIm9T5Sf~g-5DT$U5tf7HyxYje+uN{vdD;0Z{0%n# z5j(|ZK@=>+PDmFl-1RZVH;<2*`DX6x^(rv-b@$M&LIB=u@^7WTV0>VL8<2t&W`IKs zc?p-egB^}A;x2ZfEQGOE4Z zo>W4HPzT$&VkhE^<*nwGyV6)~tR00@x@woPIAe-R$LNsAf@{IEP&S}ZYnlgxrF$DS^qx-g?xPqC=A+N<|Vi`ZVuHhwMBu&2*`2 z1jiRtMgONR6Jli%(&&yR{w5b`FQZ#>#>}$6Qu78r9SGq&IDG=AFJSQzEIxyU*Qwd- IKu#O>8^uq62LJ#7 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc b/.venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bce0868a28520172a6e94d4c023cdfca7c4fde08 GIT binary patch literal 3909 zcmcgv&2JmW6`%d)Hzm?vlGB8aou*72%1(+Vm5aI*Ny&;S$`GZx-pJi^PVi+j$f8=5{NZ|~8>uGOx$&=AT-#Si=L>5VuCa8nuJ{zF}^Sfi*s0jd1G- zSVsq}QIXi;`(0=C7-*5c76&cb*G51K^|jGvBE4^;6P1kl( z*;08nRarHuS#fQesx&Mxx{cI2t=8RYeFZGF2IVGbU#r&5nv)5YZF@4c>bmQb6BBkl z^HKFmb=|hAW~M<`CQzHeaShw4nCrHIgN8Q5!yiDo_*Bp;LU$Ed$xtwK?c)Hqi3{jI zZa1KWY?AxkH#VTj5)jKIEtZ(Dc28tdt~|>m$E9h3$$SCWJN5M4{N(aFZCti1?y}XW zEN8CS^=r$;>W9lt)wSPRH!D}n728?nD>T>43A650GwV$j#X$_WVPISwiqwffY3~PU zkw@X!7s>6#&&O_@-YM^fQxD`+8yd*aszfmGRs8~l!BzR*ZxURCi@o^MU(ts6_Ng>1 zX}+9e(o~@cOH$mbTeBU$CJN*wEa=#-!L4)@^f(mf008%Gd*6-89c4HCv%Au6_~--q zC`I3gocm!Rf1hH;+=EyHnTGs|RBExk#YKm!z1+&119IkOFdI9LqxAqo)(d`X1 zK+`O41_Jl!Oodzf-QM{F?{5nCyOj7;bhX|aXm@er`LikZ-tL_u z0=e~`OqzZ|7-@w`R+X}lTFi<&aYhvh95F!rBbzO{b|rhz@z zVAlmW>NQJ*T83JJT7g=ITD1aj{KIkIRMSBg;(@qIod&J+#={BzpQP$8T?WVeE<3>|BN>St;4JmyWbM2^i(*-gfraFwA3Zm z$4qDrr?_-(zPu3|*hA3Y0#}@)0PscGL$ABJFNMEN@5bNwvb-BV@gQ)bo56yI=U`f- zS*SRq1N7%8b3Wi_ke)!m)T8erOd|Xaf$tKs#ZPMx7>X_ytq__m>EkkN6x@M_*z|!=f70^RgP!C%nJz|CRs1?y;R#cB$ zF@3~}>!a3)p0GysB;2QxEPxT4Zcy8M87A;vK}aDSLBK5bFn}H|!NYX*Fb-YVJKAmHa;Y(G2Z46je4Z}>QVu< zIM=#UJ!{4(QS-;*Q-iv9V{@=Hih#$1a{*wBJUnoyRY1t~rD>G%2s3?&cPTtp$-%MK z99qvJaH)h+5n;Y3U7z!5fpb-$^q-%E7E^Gu^pNo$65D$N0SW3IN5JIr@GSKv5HJ*; zgwib}C1`nmvNe^o>ffr$ZnI|dQ^LdVgNJuT4+<%zwY|hwrxuXAOv=yBF|{YIsSFp^5YQEVlC;R8bt`Tq<^b|a0KC48zl~%KtPz>Ryzc$ z&Vi6{a{EAsK-C#f3S*x&I|QoE@uV>B%j2EnvXIygb_i5YA|#Z!Io^`L3y%6#;^yI& P@?9`_^QG%5kJWzxpI$3% literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc b/.venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b829362e94432eadd7c19f38a2de833cdf6a225e GIT binary patch literal 16370 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc b/.venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2e73be4b61a913838f3fa23e21a7c219650100c GIT binary patch literal 3514 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/ansi.py b/.venv/Lib/site-packages/colorama/ansi.py new file mode 100644 index 00000000..11ec695f --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/ansitowin32.py b/.venv/Lib/site-packages/colorama/ansitowin32.py new file mode 100644 index 00000000..abf209e6 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/initialise.py b/.venv/Lib/site-packages/colorama/initialise.py new file mode 100644 index 00000000..d5fd4b71 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/__init__.py b/.venv/Lib/site-packages/colorama/tests/__init__.py new file mode 100644 index 00000000..8c5661e9 --- /dev/null +++ b/.venv/Lib/site-packages/colorama/tests/__init__.py @@ -0,0 +1 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25638c8cd1d944132fa00a06c480046ecb732669 GIT binary patch literal 162 zcmX@j%ge<81b^0DO7jNNk3k%C@R-ietdjpUS>&r kyk0@&FAkgB{FKt1RJ$Tppoxq?Tnu7-WM*V!EMf+-0IXjsMgRZ+ literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fceed206168e229b97307b2c21d0c9fb6398a8a2 GIT binary patch literal 5431 zcmeHL&2JM&6rc6(+M75Igpd-)X&VZ(HROW?m*9YC6JkP2Fj5GjIFT%qU8s#6r?VTV z)2hmWN>pmqV-yLARI1dVR6X|(=&dKyM9@*IR^m``ixN(#hrT!C?<`b%Y?V2@H}htG zZ$5W_Z{}y8ubx2q`-g|u_jw6xtNRjTx5jk?mI;H7_L=W*kg^x zE?v9%HX&4V5kp=rG?z$D%1Obxr&x{#T}+!WOzTX-G?>>FoBq)lbB1F?vR+QyFeB+f+9;R`ZFofx%4|IhKi4)oS5yT?-l%y(a!G_5yOcip9un>}R7jtF3TEJRb z(YA_{gd{of%(q?Oit=TibL4>(4Z2xl!ZZzPMYC4qqq#(yDOPUQV6vGrncKAV?3_jG zz#lIdls=G{VjAh|CJwse`Oxsd)GW=WjA?61&rVNu-!f)yO^qe5O_@o{=$eI1O58Ba zsp)JwOB0zyj|EF<_9S4R;+XB8%`w$9tjn|Wjm4Gj=H*84ZypD+KsMZ@&i6 zeq1IxTOhx+bbKj)SiN?t0sj*;*%PN+zSt4Xkn4&Ad_%e4Vop~b;PF(}B;D-*kGoovbdLi(o~4?kYYy->|82d_ z0sfVm&Y`H+JHXrUgYI>JZ?oyY!2!PA2Jdr#f6WHp=m6hggWu%<|Aq~Iw*&k^8+=n4 zpCiFN(Rnp6dF*J0t6rh{ggPcvNT_#&IxbYdP+_jZ0v;Cduz-gJJS^a00S^m!xIYtY zW?sQXoQS9ghRW2TvB5LvnLHjDX6ndzBobxrtC6v>i&r257`q%{o(qE`k?6!AQ_fr+ zj577gxzULTQ^zBhA`{FvHac={g1d-EK44y61XoxPb=)Nu8+n~@jpc>{^l}7CyLhS4 zRk<3w#FFsEyN2SnfBhb0I*e2XEsG|v%|UTKQ1REVt@Ojp%@2WK7YOIK*1XnwZ}0uK zrMBhRns&6(*1FWXJg}y9SK92_1(pKKsWq*)vYmg)zx@81)>CO~Uus{TU(@<3ZFcSK z`Y758bS*~x$bTg7Ke7VjK2hQGkw2LC2UlR^$E&RNZ9DV+&J`GaxT@{py#MeDjK9Ci z+LiZrt-uUKWKbM~eOuAnx^`lRS9f@I+mCUFSIfNcf(uSLF5KbO?dQjiS3`mrLxLDX zf*3=B7(;>>LxLDXf*3=BS3|(7?!aX4QNVKz4!8ynT!Ra)!3Wpiglq7^HS#Nc6$VK$ zgr^wC(AQCPpxBQBV+(o!1x5+<5Q;ZZyoCa8>VyVS;2oMCLD7k#3q?1I+B**CJ-nyC zkoT%9d%(&6jQ1vMS&Q@D$y(OpOth^n=e^P`w~EWo*YYXny-(J(lT~cUd2d@=(c8Kf zehKgW1bgw{zfVFut3>COz@+%l`anUUHxpFFw}97CCJ&EZVD9L}@e6}v%sn)YG2^zg z+>9|Ce`l&V%W z#N(_!9?xX;xisb*;&FVo5j7OAXEcBUza`p>0^d*`5blOQJy3WRBwXNS*u>U%$flyG zCpQ~h>i*68W;MLo*{lw1b;@d=z##+&fG=?IcyKp=>R{U3Owz)2q4)$r6>Ov=;Auzv zV=#cHe1*Mew6eGHU5>vd@mCUxaW3VrBY3S74&u+*>Y2zLJ19Z4~G5`Po literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d76cfe6bda15f05b31f54e016034ef6c305466c GIT binary patch literal 18053 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 U@G+BXX{2pcfvwEs78>aP0D}prxBvhE literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccb325a7f752c11eef04807bb474db0567dacf9d GIT binary patch literal 11717 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 v$KF|+elCo$r>_4aq5rk zok_ci3gV$iMMVOHP?4I4AS&%fsbK#Av{ECUmKThT+#OXyf(O*MG(oZy@xVEEJmZf# zX?Nj?y^_y8_uM;Y=HA~qzd4?-!r>r+_VZ`oy!L#6kRNd1HnFO#zX{4Uq7$9VkRs0$$d zx(G6$`$0+!b9qjR$#(E0+aw~`aFlog>?r>QO8rr~NA(7GspU~xZj6#k+;a69-JT;B zM6}afKSu~h{ufUW^L3y?Op-n15HY!nK8~CPpJ@3Tf0kV2XdB!yCQt=BJE)naL9Gco zYp{c-c=Ag=TQH5xYc>yfm>4I$y|f*dO9)pA;%vU7c2EPZaT_c#Pk;c_wmow7{1yJT zq`cSmPTPXC*l|5vlJ?&T@3?yQ9^vHv+e+lU)9;*Kcy95`^*@)C0~H>O6`Wzy8|xwP z^LclogTK`wCe*<19gQ#^Z^%JoT+09`mBKvP!Kf}$?Gym+n{9VjV-h)x{Q zi6c7k4H^Y+ts(gyW?Ci4!vwa4X~x>LP=NJxz6{tZei z9N*w9oM)|`v|15e6?2c|-0KLjkY`wHMT^ZiG>`8mw|Cnea@(5pL`HfJXc!PRb&sOcQy@G-^s=mfA-Fhnz3l;9SVxFVT}6W2SlNdA$BLcoRkk&q)^RFR5n!O#esJ4Bub3_@E#HJ1qE%XAs?`z` z%DZZ-NkC0@l=Olwe_n!rJCOnknHy z;}(>$t2Jf3+tb?KSU*X1;f7nLwU}eU$leLaw6qUIJ^8CGBGB;SuW#%4^A^U?>qj8G zmx3T4yR*Ifw-S-F|K33Xu^q*F7&v7=m9obQi^cEt$H#+~Z_tTzIBwlB^`NZ-- zaraZD$S@eMwSCZbL%P|u++FNFQi>d{1i)7X9aea_#VP?&@xgEvZ5wQ+s(SMq<}f_j zRb^y|zov}ziJvAO9qA6N_$1I*f)bcly2X*bp_SeMTKdG1xV-X20PREK$nj06>i|@u zn}z;^O6L0uZ8scSRT|S?5W_aAtvM7o4P!6aHV@-pbx-f@>pmI0O>6gzxYlVb*qhpK zvge1rKUSSh?bqMGInD1+>&7$<)m3Q7TTTJ69W^{DCu>>4BAwIyDE6Uf&e~{m*4F=< z*XJMKB5fO1#=*Jy8Hl>P9pl`>?N2x5!*~5hklr3&<%zJ1dH)3sf`K0Z literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6200a945d85907a1802777f470a925d8f430ada4 GIT binary patch literal 2452 zcmds2-A^1<6u);qc4wD`QkE5iNSDxxi@F4jVw&1yTa-$5Yb-BpHW`PVDK5_L;JriX zHjp4$Vj4|KU&McbpvE^}eBs%b*7`sOOiZkazAaf2g!I94W@bO2#MD>sWX?V3chCJe zzx#21YHbY@D38DU`NoJu$nR*>itH=ZuR&QOI?<^~3N%A0>Vhd0#Ej_bqA6u0z(iBd z$O0K7x>P2*Y=|48H%2Dlq5(jIO=!@dx>6<^{zMrC>`;>(0z2Gfhrw=XvRg`GBJvmZ zPEe;UXBBPZmR-<_+O)v{QLfu8Uz~pTS~};?;8xT(svV%L5rbr?PBMZ{%OoR~goNmX zprfG`CMG6xHRsv@7*G|Mf{rDc5YiLtWSu$^H_RIxedC80N6%+xnKfhN?5u9(vdNo9 z@n-hD{8X0bZR3?$E%ynmk7sk1X)&#!4cP{_`Ouu5H+gclV#FbVCi!v>Je4_bWSt978U_trl4p=(SjmS6NvL5 zh%%`PRPOYAu=zjI7V%b`wu(=~+&kWa+^AgUyk+51Z%3O)^25iK*TeS~nPzPO9uF*v z7z!M!DX^Fq7`7bQRsn#1_^Tg*xJoE&tqq!2X0Y{GS)>b19%}uF=;SN92Df8@Hu^VO zOXOQ|p03k$LU06&I}+|qLSWCr=#FHu{4~e8;&GP;Ctz`OVBLVV!_VU&{v>}dkw-19 zcSr7wERAlpb(Ala$F`-AtF4S3a6FmIFDL2A0e%CmPZwY#fEgU}SXmTKCg2EKC+^>A zSr8g?sr5b{S?n2@81AFUOWX-?Tes$Hw>B7C7g57&>a-wvs^45Uz=z{)jn^0rGh^1& za)vrpVz}R3@beK69;+R(wZVIXOILSl%GT+w^5yclUm?qGx zMK|k#xbQLY81)_&(1B1@WoMAJBfLgyyy72x6FUIxkQ%2{TgiW&bU4lFZX5 z@Bt6Urz0Vz9Xjl^eK2|XO6tS+)hpMoPrN;vkQp9iCkR<4&#a>R^10{R-2+I2!J<`E zA)|Qt$$MRbv!&d}8Y{3Q^nD3_Zh&wv!f*XAlrMcg{@M8bQ)eDX@twBrFN#ZJJE7?6 z*uzlIE}?SUFTKOx4?OHW?;6`m>%Iu!KDInk!gs@W!uO;750ta}G9VR%58Xyreav5l znU)i&H|RzrH7Ncdr+Vcd70@=NZU8rX<amJKg!WxQqS2}dS_QRA#KnU2c^?C<(&1x$b*#_FWO~lU Kb_LMf1oaQ@vCm-u literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc b/.venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a06cbdbb9aa91a397b4c39fed61233eb6325b4c1 GIT binary patch literal 6576 zcmeHLU2GKB6~6PcyR*Bq%NG0(HFg4miDDZ}3baH;#yGAkuv@%{va&QLp1J2cKllDI5(yC~|NQXdv0G6>KF1Hc_$rO{ccF2gC`4hhB!M-X zWpZqS&2b4X$0vA(1hJRP`f~n+KNm;@7^3isFB{5*6XBeg5Oa}4gdr^HCyM_zQ35La zh_kpSqUs(+xN(#aDzHT59#uAF$P_chyi8Q#5TRk@Dp78#9iPQbn%PSoJGhr7Ofcz zyT zOtZ4nKg~`v8C+FU2-BMT^Bn;Vdod@&)W|cqN zW?jtQrCKWvD8V*~8UmVQ<5E#$RARvk`J zRn4E97#maRKz^)Xh*Z@lXkNaV%uc8jf8GcuHBF^@-YEd3s%mW@lTw(}QVsxN4r;;#?N34Bo}gs_ zv`iJW=9dF|^UHxNK+FLw3Sbogxd&ivK!aa&pr$(z_VR~rDPCl!?YVnO;Q?`w!uk8% zm%=5Z$KDECga}iFV|7Wp*FNV=o!zR|AnjMuj!Pa7H{lxHR$6^q88`k9xD9TQ;t{VP zPbq8~JZ*$FZ9>wFqydN#yr$}M63khn2s^`nweP}(p({q%Vzlz9*aWU1n{~_~7(MXXno@31?tdx&Cme{_uu*%VO;A z;OyX{c;JaxcXw!Z=-un(*3MFE=i|Ml))OW1#4{fo{MIvpG#9u zUlmGX-xt87pP}vWhu%@`x8OEB9mK9gwaw9Tnv?Bx3Q{KcLRV!L^9y52^$X*QSs)JX zv)k3$b~a`-tFQLktu3PG#wh5$&ciI+Q4m~&_c||w@m0-w%XMZhZp&@e8MKC)qWG)4 zz@!3$D-z6D`4^NG^#2r3jG|q}CDDw>6wi&K51}Y=CC+MKVks*w*Vv#DgqVT`n9W+| z=ubgYRcH&Wc0#Mm#xCLXo@{orjoBkzxbi(9UoJpC-GA`sCujI2p=r4ujSo!Gsv4Tm z2tE_UyV2Pw3`6V1BI%NF)Me1+W~tOHm79;1nvXp`^oelFvKDtZ#f-uXr+5&9Z*Z&o43UW3OBdq)+XgGrlJh`kqq2|bOZ9ms}6^ncWHB-?V( zhkIBKrX7aQywPlT?mVNmAatugl0o?-FKpHsa~aH5 zYl^+=7@H$l?{2qb6z`KE;+z&~e66z(S)yT%oyb>$~fdhL*R-DnZx^y-PxigQ{h* zzASc>#E!CfswAFTjy9H~t)*z|L;k(!FQbcX#}*>TA9pW^C%^D<7*h-PZTEeK7Jv3(Vo4N5UXkmYPslI2`MnaE;Wlx2KuvPLN0 zK4=>f%y6HksD1(^qg(H0P(?au ztsQX5ZI7(6&@vr^d0413e9M<*DMm5LFoX$shC?t?Ot&d!7nZ6b_CO~-23j{C)TR+0 z$c-1^Ns&@`=jUF)wzx=ZBvGe2dR(A?2y1nbodM|g3j_%YY~Ctmo; r8>{fy@{iR?jtKkyMi^Y#R^r=`W&3jt!`GZ}hWswl6XyO9Vu1b|;(dCl literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/colorama/tests/ansi_test.py b/.venv/Lib/site-packages/colorama/tests/ansi_test.py new file mode 100644 index 00000000..0a20c80f --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/ansitowin32_test.py b/.venv/Lib/site-packages/colorama/tests/ansitowin32_test.py new file mode 100644 index 00000000..91ca551f --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/initialise_test.py b/.venv/Lib/site-packages/colorama/tests/initialise_test.py new file mode 100644 index 00000000..89f9b075 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/isatty_test.py b/.venv/Lib/site-packages/colorama/tests/isatty_test.py new file mode 100644 index 00000000..0f84e4be --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/utils.py b/.venv/Lib/site-packages/colorama/tests/utils.py new file mode 100644 index 00000000..472fafb4 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/tests/winterm_test.py b/.venv/Lib/site-packages/colorama/tests/winterm_test.py new file mode 100644 index 00000000..d0955f9e --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/win32.py b/.venv/Lib/site-packages/colorama/win32.py new file mode 100644 index 00000000..841b0e27 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/colorama/winterm.py b/.venv/Lib/site-packages/colorama/winterm.py new file mode 100644 index 00000000..aad867e8 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/dateutil/__init__.py b/.venv/Lib/site-packages/dateutil/__init__.py new file mode 100644 index 00000000..a2c19c06 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +import sys + +try: + from ._version import version as __version__ +except ImportError: + __version__ = 'unknown' + +__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz', + 'utils', 'zoneinfo'] + +def __getattr__(name): + import importlib + + if name in __all__: + return importlib.import_module("." + name, __name__) + raise AttributeError( + "module {!r} has not attribute {!r}".format(__name__, name) + ) + + +def __dir__(): + # __dir__ should include all the lazy-importable modules as well. + return [x for x in globals() if x not in sys.modules] + __all__ diff --git a/.venv/Lib/site-packages/dateutil/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..829ffdcf3a94a0c2bf8381c93d9a0d21df13cedf GIT binary patch literal 1102 zcmYjQ&1)1{5U2ANS22X>>7OQK;hB%-3^5-(0>X*%;dvz_#G5AVIq znAr)N4YCKxvMU~Pje?*=^y0yT|A7~ifC=p`Ea)Y-khy5^V7;DcW5KJhuBunBe${Wf zx;g>r%kzzCUjg_ajfAwe(!7Ss3Q(ZLhdguuRjBHdvXWN`lz^rlk$j5kcOkD+1GzCz zPJ^qR0hS^_wY+*8mb+_k2W5@q%pF;Fe1{;hMeuii{%!^QPuR%bnAs4zFAZnee@-$gpk4_ia1sYWeI| zfylJ&z$v@<;qXY3euc3Rhd3RwvLkXzq{#@D#;du!Ka<(NG==>*m1AYp>|0Ioebe zOWy@0r8lt#6eUYY0u)18L1hKRH<;Jj5o7Q-6qOR5U$B)0_#Wh$WRa6?y;JA(tpo zPmbjzTGGSMAzOrxJtrT`zq5w^$*zt(n|Lw#baLa&;JuLzYv}dWb!+skHu@QLZes9X zJp;#$!aQjDL@-=e!Z5tuCuE+Zk;~h5?!x3Np6j(3D$8GJK!>z7=W~b37 z`{jekc2z>i2k6|@RMPjKc45yXR%X%I(+#3GyA?7U0Y}Twi6`y1ilMNv;>=XKAeD;OKmwMyFCjJAJu8AQ&c+S10Sge!u+%xB6&Ya(z zbNX{*qo2U~`@7@0ZzV#0$IaPNDonW(m;y0KgfQ|RG3X{Sm`V4+9#@2ArLer#=f9p_ zT1uz1c-kM=Y(y@nU4FU!Jy+p}t#i$*MK)6{glax>>}41xQy2Bbi8 zG)Hvc+?8Xnqi4G;*`w2YjH5Z1frKSn7G`qpTq01XY1--N#AtMxrx(n)6*bcF=+KIp zT8Vy`n2m~rWxlo?i!a9Rnj&h%EHh&zl2`S(1JBTM*7oXpB9*XoeJxnI_0XBb2gi#b zkPT97>&(j!0>zdW^75Bz8Du1Wh8J$|f=*&lVBEwOP<~-8UV&sF%^8v-3uu2~ffP@= zuyS<25^IKV6_jDgLB#gydOR5uLf0Ko!i;-C>*xe}Xd1^HFvoZ-nXJvxl{A80^Z|h! z8vcsI4%zJ+|BPc<|BS0sSR3d=wbw4PaY8^#`CS5Fe%n+{Kln z^`wi}AbbaS{2R=QD|pnAq6ep0>LXd!O{^+hJ%me?+#y-INKI{DjF4|s{IKp^YD z$bog3dy;z^n8;Hs$Cdjl#ZYU0>RIU0F5P|W@yMf*ozI_!`i}zr4l3>d@#9QL#g+g= z+pp{H9|G_JUB8!!B`X@3FCv+?aK88<9LERa*aQ3}BnTGoM$(Q1CxbI@+^Ryfaaf6d zAe*Gv^7790qoB6&epzNp=)@~4Z=M8HrS&8zD-934EOM{{bwbdGG)L literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/__pycache__/_version.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/__pycache__/_version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..512733a8d3214bae32b3ac6a7bc729970510b546 GIT binary patch literal 278 zcmX@j%ge<81b^0DN?Qh`AA>kBzyxJ{76CG*Go&z7Fh(&%F{UsAX{IRVN+wO_DsCe^ zOFaX literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/__pycache__/easter.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/__pycache__/easter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbe2acda1c25b9ebe848794d2290e3f460dee059 GIT binary patch literal 2822 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

yB- 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 N@VFya6t}X;`9FTtJ#YX3 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/__pycache__/rrule.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/__pycache__/rrule.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b00773ae5d21c7338fafd9c49a58c5877d7c4bd GIT binary patch literal 68874 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 E0Ap4z^#A|> literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/__pycache__/utils.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e5a247124387b1e129e6e57a08713917a1c580f GIT binary patch literal 2534 zcmbVO&2Jk;6rWw&v12DqQxKxGMWcdLuV{=DC{!yNXlbdaP!A-%Sdr}U&aA!Zde_X1 zlh|^lRH{S^hlW!@9O$73suaZk!6l^#suc$$4v1SJaH%-(X1uoJC{&1%cRU|&-h1;t zes8{=oXjFVWd zp6|&vc3XiXy)Y2i4LPQa_+C)MtDdZ9DUnQi4JHcNY@vWxfE^GLN*T3nJXd(VP|W_O zbhnIXe=G2ukg_r`Rq}*oMwvc?D5=<7bd30->JN;767X$*1l=tp2YbtXbHIAPbRfm8;Qb%vc5=P<>Tv@wym;nBdW)n!&QvzvsI29_N!a6?-!DH)4! zP8kPx!T?4g9F)YV<2;x!#4W+7TBHn&+VB*`s2mGiquAJ7>pJ9ndM}*|L*>KjGIQh; z?=aAD$6X3~kt?&^HKMWJZLAbmo`@1bxEiIMuu%m~qofkXQ?Ox~JfrqaDup_U@#B+c z?WHCUl@3cZbe0Mbn=4E2dDSHW@iWsT&Sg?#VoC8(k@~XgM4{P^QZfYl@_oQ(5l*ir%{WRSj!bd~h_tyDm=xM^ zl}gWGl?v9;puCF100+cdVGuTPy1|m)?)g(ktVG9$^ zFxYa%gS^CKzy>5L$3ZOC$qLhoFvx0@pur2$FXQZ3=+{30=fzn z<761Anw^jwmg5KnfB;8ICZuimbXRdXKR=IM9yYXA%7+EnQNlwmAr%0k1e2QA-o#2W zC>$TqvnNpN80iyJ=8~2#%RP&aoT9E?$EOA=;n_L+l_I{h`1UdDIF2P)Lr%LX?PBqzViEfPE$ctanJJ!7aAEw1n;+BX^r`~WN-fls^$-8yFeV^Pfg$K z-00kX=6dJBRDLUy=TkuF>;w=sR^Rqn=ysOEuDRJSdjLFLqXTbRINfm8DPx_N)K4=lYXG3@aBuG_Q$tXePtm@{X6lK07QFh2iB;kT8(|e|z zP_GOxC~G=?5cb}JPZXd7M9-qh{Tr!|FRY(?IQ{g7_~hXFg@+T<*I(Nx{gBJwK5;*n z-%93ty*8<3T(mM#x?BbrDwm^dx$L%}ezS6!E92@CrOT179olbN=3S(ZYn2{n-srua u=DG5zGQKzp-J^tI7{4b|M)I!-WaNKEFKmxZ8gKrAv0-h$W26mB^Y{m9=BUyD literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/_common.py b/.venv/Lib/site-packages/dateutil/_common.py new file mode 100644 index 00000000..4eb2659b --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/_common.py @@ -0,0 +1,43 @@ +""" +Common code used in multiple modules. +""" + + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __hash__(self): + return hash(( + self.weekday, + self.n, + )) + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +# vim:ts=4:sw=4:et diff --git a/.venv/Lib/site-packages/dateutil/_version.py b/.venv/Lib/site-packages/dateutil/_version.py new file mode 100644 index 00000000..ddda9809 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/_version.py @@ -0,0 +1,4 @@ +# file generated by setuptools_scm +# don't change, don't track in version control +__version__ = version = '2.9.0.post0' +__version_tuple__ = version_tuple = (2, 9, 0) diff --git a/.venv/Lib/site-packages/dateutil/easter.py b/.venv/Lib/site-packages/dateutil/easter.py new file mode 100644 index 00000000..f74d1f74 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/easter.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +This module offers a generic Easter computing method for any given year, using +Western, Orthodox or Julian algorithms. +""" + +import datetime + +__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] + +EASTER_JULIAN = 1 +EASTER_ORTHODOX = 2 +EASTER_WESTERN = 3 + + +def easter(year, method=EASTER_WESTERN): + """ + This method was ported from the work done by GM Arts, + on top of the algorithm by Claus Tondering, which was + based in part on the algorithm of Ouding (1940), as + quoted in "Explanatory Supplement to the Astronomical + Almanac", P. Kenneth Seidelmann, editor. + + This algorithm implements three different Easter + calculation methods: + + 1. Original calculation in Julian calendar, valid in + dates after 326 AD + 2. Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3. Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well + + These methods are represented by the constants: + + * ``EASTER_JULIAN = 1`` + * ``EASTER_ORTHODOX = 2`` + * ``EASTER_WESTERN = 3`` + + The default method is method 3. + + More about the algorithm may be found at: + + `GM Arts: Easter Algorithms `_ + + and + + `The Calendar FAQ: Easter `_ + + """ + + if not (1 <= method <= 3): + raise ValueError("invalid method") + + # g - Golden year - 1 + # c - Century + # h - (23 - Epact) mod 30 + # i - Number of days from March 21 to Paschal Full Moon + # j - Weekday for PFM (0=Sunday, etc) + # p - Number of days from March 21 to Sunday on or before PFM + # (-6 to 28 methods 1 & 3, to 56 for method 2) + # e - Extra days to add for method 2 (converting Julian + # date to Gregorian date) + + y = year + g = y % 19 + e = 0 + if method < 3: + # Old method + i = (19*g + 15) % 30 + j = (y + y//4 + i) % 7 + if method == 2: + # Extra dates to convert Julian to Gregorian date + e = 10 + if y > 1600: + e = e + y//100 - 16 - (y//100 - 16)//4 + else: + # New method + c = y//100 + h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 + i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) + j = (y + y//4 + i + 2 - c + c//4) % 7 + + # p can be from -6 to 56 corresponding to dates 22 March to 23 May + # (later dates apply to method 2, although 23 May never actually occurs) + p = i - j + e + d = 1 + (p + 27 + (p + 6)//40) % 31 + m = 3 + (p + 26)//30 + return datetime.date(int(y), int(m), int(d)) diff --git a/.venv/Lib/site-packages/dateutil/parser/__init__.py b/.venv/Lib/site-packages/dateutil/parser/__init__.py new file mode 100644 index 00000000..d174b0e4 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/parser/__init__.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +from ._parser import parse, parser, parserinfo, ParserError +from ._parser import DEFAULTPARSER, DEFAULTTZPARSER +from ._parser import UnknownTimezoneWarning + +from ._parser import __doc__ + +from .isoparser import isoparser, isoparse + +__all__ = ['parse', 'parser', 'parserinfo', + 'isoparse', 'isoparser', + 'ParserError', + 'UnknownTimezoneWarning'] + + +### +# Deprecate portions of the private interface so that downstream code that +# is improperly relying on it is given *some* notice. + + +def __deprecated_private_func(f): + from functools import wraps + import warnings + + msg = ('{name} is a private function and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=f.__name__) + + @wraps(f) + def deprecated_func(*args, **kwargs): + warnings.warn(msg, DeprecationWarning) + return f(*args, **kwargs) + + return deprecated_func + +def __deprecate_private_class(c): + import warnings + + msg = ('{name} is a private class and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=c.__name__) + + class private_class(c): + __doc__ = c.__doc__ + + def __init__(self, *args, **kwargs): + warnings.warn(msg, DeprecationWarning) + super(private_class, self).__init__(*args, **kwargs) + + private_class.__name__ = c.__name__ + + return private_class + + +from ._parser import _timelex, _resultbase +from ._parser import _tzparser, _parsetz + +_timelex = __deprecate_private_class(_timelex) +_tzparser = __deprecate_private_class(_tzparser) +_resultbase = __deprecate_private_class(_resultbase) +_parsetz = __deprecated_private_func(_parsetz) diff --git a/.venv/Lib/site-packages/dateutil/parser/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/parser/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5d9aaaf91e27544f4f9c27a7f708e22eebed7fe GIT binary patch literal 2628 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 QsM0fYDNDyit7lq|WD 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 +- `W3C Date and Time Formats `_ +- `Time Formats (Planetary Rings Node) `_ +- `CPAN ParseDate module + `_ +- `Java SimpleDateFormat Class + `_ +""" +from __future__ import unicode_literals + +import datetime +import re +import string +import time +import warnings + +from calendar import monthrange +from io import StringIO + +import six +from six import integer_types, text_type + +from decimal import Decimal + +from warnings import warn + +from .. import relativedelta +from .. import tz + +__all__ = ["parse", "parserinfo", "ParserError"] + + +# TODO: pandas.core.tools.datetimes imports this explicitly. Might be worth +# making public and/or figuring out if there is something we can +# take off their plate. +class _timelex(object): + # Fractional seconds are sometimes split by a comma + _split_decimal = re.compile("([.,])") + + def __init__(self, instream): + if isinstance(instream, (bytes, bytearray)): + instream = instream.decode() + + if isinstance(instream, text_type): + instream = StringIO(instream) + elif getattr(instream, 'read', None) is None: + raise TypeError('Parser must be a string or character stream, not ' + '{itype}'.format(itype=instream.__class__.__name__)) + + self.instream = instream + self.charstack = [] + self.tokenstack = [] + self.eof = False + + def get_token(self): + """ + This function breaks the time string into lexical units (tokens), which + can be parsed by the parser. Lexical units are demarcated by changes in + the character set, so any continuous string of letters is considered + one unit, any continuous string of numbers is considered one unit. + + The main complication arises from the fact that dots ('.') can be used + both as separators (e.g. "Sep.20.2009") or decimal points (e.g. + "4:30:21.447"). As such, it is necessary to read the full context of + any dot-separated strings before breaking it into tokens; as such, this + function maintains a "token stack", for when the ambiguous context + demands that multiple tokens be parsed at once. + """ + if self.tokenstack: + return self.tokenstack.pop(0) + + seenletters = False + token = None + state = None + + while not self.eof: + # We only realize that we've reached the end of a token when we + # find a character that's not part of the current token - since + # that character may be part of the next token, it's stored in the + # charstack. + if self.charstack: + nextchar = self.charstack.pop(0) + else: + nextchar = self.instream.read(1) + while nextchar == '\x00': + nextchar = self.instream.read(1) + + if not nextchar: + self.eof = True + break + elif not state: + # First character of the token - determines if we're starting + # to parse a word, a number or something else. + token = nextchar + if self.isword(nextchar): + state = 'a' + elif self.isnum(nextchar): + state = '0' + elif self.isspace(nextchar): + token = ' ' + break # emit token + else: + break # emit token + elif state == 'a': + # If we've already started reading a word, we keep reading + # letters until we find something that's not part of a word. + seenletters = True + if self.isword(nextchar): + token += nextchar + elif nextchar == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0': + # If we've already started reading a number, we keep reading + # numbers until we find something that doesn't fit. + if self.isnum(nextchar): + token += nextchar + elif nextchar == '.' or (nextchar == ',' and len(token) >= 2): + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == 'a.': + # If we've seen some letters and a dot separator, continue + # parsing, and the tokens will be broken up later. + seenletters = True + if nextchar == '.' or self.isword(nextchar): + token += nextchar + elif self.isnum(nextchar) and token[-1] == '.': + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0.': + # If we've seen at least one dot separator, keep going, we'll + # break up the tokens later. + if nextchar == '.' or self.isnum(nextchar): + token += nextchar + elif self.isword(nextchar) and token[-1] == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + + if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or + token[-1] in '.,')): + l = self._split_decimal.split(token) + token = l[0] + for tok in l[1:]: + if tok: + self.tokenstack.append(tok) + + if state == '0.' and token.count('.') == 0: + token = token.replace(',', '.') + + return token + + def __iter__(self): + return self + + def __next__(self): + token = self.get_token() + if token is None: + raise StopIteration + + return token + + def next(self): + return self.__next__() # Python 2.x support + + @classmethod + def split(cls, s): + return list(cls(s)) + + @classmethod + def isword(cls, nextchar): + """ Whether or not the next character is part of a word """ + return nextchar.isalpha() + + @classmethod + def isnum(cls, nextchar): + """ Whether the next character is part of a number """ + return nextchar.isdigit() + + @classmethod + def isspace(cls, nextchar): + """ Whether the next character is whitespace """ + return nextchar.isspace() + + +class _resultbase(object): + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def _repr(self, classname): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (classname, ", ".join(l)) + + def __len__(self): + return (sum(getattr(self, attr) is not None + for attr in self.__slots__)) + + def __repr__(self): + return self._repr(self.__class__.__name__) + + +class parserinfo(object): + """ + Class which handles what inputs are accepted. Subclass this to customize + the language and acceptable values for each parameter. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. Default is ``False``. + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + Default is ``False``. + """ + + # m from a.m/p.m, t from ISO T separator + JUMP = [" ", ".", ",", ";", "-", "/", "'", + "at", "on", "and", "ad", "m", "t", "of", + "st", "nd", "rd", "th"] + + WEEKDAYS = [("Mon", "Monday"), + ("Tue", "Tuesday"), # TODO: "Tues" + ("Wed", "Wednesday"), + ("Thu", "Thursday"), # TODO: "Thurs" + ("Fri", "Friday"), + ("Sat", "Saturday"), + ("Sun", "Sunday")] + MONTHS = [("Jan", "January"), + ("Feb", "February"), # TODO: "Febr" + ("Mar", "March"), + ("Apr", "April"), + ("May", "May"), + ("Jun", "June"), + ("Jul", "July"), + ("Aug", "August"), + ("Sep", "Sept", "September"), + ("Oct", "October"), + ("Nov", "November"), + ("Dec", "December")] + HMS = [("h", "hour", "hours"), + ("m", "minute", "minutes"), + ("s", "second", "seconds")] + AMPM = [("am", "a"), + ("pm", "p")] + UTCZONE = ["UTC", "GMT", "Z", "z"] + PERTAIN = ["of"] + TZOFFSET = {} + # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate", + # "Anno Domini", "Year of Our Lord"] + + def __init__(self, dayfirst=False, yearfirst=False): + self._jump = self._convert(self.JUMP) + self._weekdays = self._convert(self.WEEKDAYS) + self._months = self._convert(self.MONTHS) + self._hms = self._convert(self.HMS) + self._ampm = self._convert(self.AMPM) + self._utczone = self._convert(self.UTCZONE) + self._pertain = self._convert(self.PERTAIN) + + self.dayfirst = dayfirst + self.yearfirst = yearfirst + + self._year = time.localtime().tm_year + self._century = self._year // 100 * 100 + + def _convert(self, lst): + dct = {} + for i, v in enumerate(lst): + if isinstance(v, tuple): + for v in v: + dct[v.lower()] = i + else: + dct[v.lower()] = i + return dct + + def jump(self, name): + return name.lower() in self._jump + + def weekday(self, name): + try: + return self._weekdays[name.lower()] + except KeyError: + pass + return None + + def month(self, name): + try: + return self._months[name.lower()] + 1 + except KeyError: + pass + return None + + def hms(self, name): + try: + return self._hms[name.lower()] + except KeyError: + return None + + def ampm(self, name): + try: + return self._ampm[name.lower()] + except KeyError: + return None + + def pertain(self, name): + return name.lower() in self._pertain + + def utczone(self, name): + return name.lower() in self._utczone + + def tzoffset(self, name): + if name in self._utczone: + return 0 + + return self.TZOFFSET.get(name) + + def convertyear(self, year, century_specified=False): + """ + Converts two-digit years to year within [-50, 49] + range of self._year (current local time) + """ + + # Function contract is that the year is always positive + assert year >= 0 + + if year < 100 and not century_specified: + # assume current century to start + year += self._century + + if year >= self._year + 50: # if too far in future + year -= 100 + elif year < self._year - 50: # if too far in past + year += 100 + + return year + + def validate(self, res): + # move to info + if res.year is not None: + res.year = self.convertyear(res.year, res.century_specified) + + if ((res.tzoffset == 0 and not res.tzname) or + (res.tzname == 'Z' or res.tzname == 'z')): + res.tzname = "UTC" + res.tzoffset = 0 + elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): + res.tzoffset = 0 + return True + + +class _ymd(list): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + self.century_specified = False + self.dstridx = None + self.mstridx = None + self.ystridx = None + + @property + def has_year(self): + return self.ystridx is not None + + @property + def has_month(self): + return self.mstridx is not None + + @property + def has_day(self): + return self.dstridx is not None + + def could_be_day(self, value): + if self.has_day: + return False + elif not self.has_month: + return 1 <= value <= 31 + elif not self.has_year: + # Be permissive, assume leap year + month = self[self.mstridx] + return 1 <= value <= monthrange(2000, month)[1] + else: + month = self[self.mstridx] + year = self[self.ystridx] + return 1 <= value <= monthrange(year, month)[1] + + def append(self, val, label=None): + if hasattr(val, '__len__'): + if val.isdigit() and len(val) > 2: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + elif val > 100: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + + super(self.__class__, self).append(int(val)) + + if label == 'M': + if self.has_month: + raise ValueError('Month is already set') + self.mstridx = len(self) - 1 + elif label == 'D': + if self.has_day: + raise ValueError('Day is already set') + self.dstridx = len(self) - 1 + elif label == 'Y': + if self.has_year: + raise ValueError('Year is already set') + self.ystridx = len(self) - 1 + + def _resolve_from_stridxs(self, strids): + """ + Try to resolve the identities of year/month/day elements using + ystridx, mstridx, and dstridx, if enough of these are specified. + """ + if len(self) == 3 and len(strids) == 2: + # we can back out the remaining stridx value + missing = [x for x in range(3) if x not in strids.values()] + key = [x for x in ['y', 'm', 'd'] if x not in strids] + assert len(missing) == len(key) == 1 + key = key[0] + val = missing[0] + strids[key] = val + + assert len(self) == len(strids) # otherwise this should not be called + out = {key: self[strids[key]] for key in strids} + return (out.get('y'), out.get('m'), out.get('d')) + + def resolve_ymd(self, yearfirst, dayfirst): + len_ymd = len(self) + year, month, day = (None, None, None) + + strids = (('y', self.ystridx), + ('m', self.mstridx), + ('d', self.dstridx)) + + strids = {key: val for key, val in strids if val is not None} + if (len(self) == len(strids) > 0 or + (len(self) == 3 and len(strids) == 2)): + return self._resolve_from_stridxs(strids) + + mstridx = self.mstridx + + if len_ymd > 3: + raise ValueError("More than three YMD values") + elif len_ymd == 1 or (mstridx is not None and len_ymd == 2): + # One member, or two members with a month string + if mstridx is not None: + month = self[mstridx] + # since mstridx is 0 or 1, self[mstridx-1] always + # looks up the other element + other = self[mstridx - 1] + else: + other = self[0] + + if len_ymd > 1 or mstridx is None: + if other > 31: + year = other + else: + day = other + + elif len_ymd == 2: + # Two members with numbers + if self[0] > 31: + # 99-01 + year, month = self + elif self[1] > 31: + # 01-99 + month, year = self + elif dayfirst and self[1] <= 12: + # 13-01 + day, month = self + else: + # 01-13 + month, day = self + + elif len_ymd == 3: + # Three members + if mstridx == 0: + if self[1] > 31: + # Apr-2003-25 + month, year, day = self + else: + month, day, year = self + elif mstridx == 1: + if self[0] > 31 or (yearfirst and self[2] <= 31): + # 99-Jan-01 + year, month, day = self + else: + # 01-Jan-01 + # Give precedence to day-first, since + # two-digit years is usually hand-written. + day, month, year = self + + elif mstridx == 2: + # WTF!? + if self[1] > 31: + # 01-99-Jan + day, year, month = self + else: + # 99-01-Jan + year, day, month = self + + else: + if (self[0] > 31 or + self.ystridx == 0 or + (yearfirst and self[1] <= 12 and self[2] <= 31)): + # 99-01-01 + if dayfirst and self[2] <= 12: + year, day, month = self + else: + year, month, day = self + elif self[0] > 12 or (dayfirst and self[1] <= 12): + # 13-01-01 + day, month, year = self + else: + # 01-13-01 + month, day, year = self + + return year, month, day + + +class parser(object): + def __init__(self, info=None): + self.info = info or parserinfo() + + def parse(self, timestr, default=None, + ignoretz=False, tzinfos=None, **kwargs): + """ + Parse the date/time string into a :class:`datetime.datetime` object. + + :param timestr: + Any date/time string using the supported formats. + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a + naive :class:`datetime.datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param \\*\\*kwargs: + Keyword arguments as passed to ``_parse()``. + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ParserError: + Raised for invalid or unknown string format, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date + would be created. + + :raises TypeError: + Raised for non-string or character stream input. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + + if default is None: + default = datetime.datetime.now().replace(hour=0, minute=0, + second=0, microsecond=0) + + res, skipped_tokens = self._parse(timestr, **kwargs) + + if res is None: + raise ParserError("Unknown string format: %s", timestr) + + if len(res) == 0: + raise ParserError("String does not contain a date: %s", timestr) + + try: + ret = self._build_naive(res, default) + except ValueError as e: + six.raise_from(ParserError(str(e) + ": %s", timestr), e) + + if not ignoretz: + ret = self._build_tzaware(ret, res, tzinfos) + + if kwargs.get('fuzzy_with_tokens', False): + return ret, skipped_tokens + else: + return ret + + class _result(_resultbase): + __slots__ = ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond", + "tzname", "tzoffset", "ampm","any_unused_tokens"] + + def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, + fuzzy_with_tokens=False): + """ + Private method which performs the heavy lifting of parsing, called from + ``parse()``, which passes on its ``kwargs`` to this function. + + :param timestr: + The string to parse. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. If set to ``None``, this value is retrieved from the + current :class:`parserinfo` object (which itself defaults to + ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + If this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + """ + if fuzzy_with_tokens: + fuzzy = True + + info = self.info + + if dayfirst is None: + dayfirst = info.dayfirst + + if yearfirst is None: + yearfirst = info.yearfirst + + res = self._result() + l = _timelex.split(timestr) # Splits the timestr into tokens + + skipped_idxs = [] + + # year/month/day list + ymd = _ymd() + + len_l = len(l) + i = 0 + try: + while i < len_l: + + # Check if it's a number + value_repr = l[i] + try: + value = float(value_repr) + except ValueError: + value = None + + if value is not None: + # Numeric token + i = self._parse_numeric_token(l, i, info, ymd, res, fuzzy) + + # Check weekday + elif info.weekday(l[i]) is not None: + value = info.weekday(l[i]) + res.weekday = value + + # Check month name + elif info.month(l[i]) is not None: + value = info.month(l[i]) + ymd.append(value, 'M') + + if i + 1 < len_l: + if l[i + 1] in ('-', '/'): + # Jan-01[-99] + sep = l[i + 1] + ymd.append(l[i + 2]) + + if i + 3 < len_l and l[i + 3] == sep: + # Jan-01-99 + ymd.append(l[i + 4]) + i += 2 + + i += 2 + + elif (i + 4 < len_l and l[i + 1] == l[i + 3] == ' ' and + info.pertain(l[i + 2])): + # Jan of 01 + # In this case, 01 is clearly year + if l[i + 4].isdigit(): + # Convert it here to become unambiguous + value = int(l[i + 4]) + year = str(info.convertyear(value)) + ymd.append(year, 'Y') + else: + # Wrong guess + pass + # TODO: not hit in tests + i += 4 + + # Check am/pm + elif info.ampm(l[i]) is not None: + value = info.ampm(l[i]) + val_is_ampm = self._ampm_valid(res.hour, res.ampm, fuzzy) + + if val_is_ampm: + res.hour = self._adjust_ampm(res.hour, value) + res.ampm = value + + elif fuzzy: + skipped_idxs.append(i) + + # Check for a timezone name + elif self._could_be_tzname(res.hour, res.tzname, res.tzoffset, l[i]): + res.tzname = l[i] + res.tzoffset = info.tzoffset(res.tzname) + + # Check for something like GMT+3, or BRST+3. Notice + # that it doesn't mean "I am 3 hours after GMT", but + # "my time +3 is GMT". If found, we reverse the + # logic so that timezone parsing code will get it + # right. + if i + 1 < len_l and l[i + 1] in ('+', '-'): + l[i + 1] = ('+', '-')[l[i + 1] == '+'] + res.tzoffset = None + if info.utczone(res.tzname): + # With something like GMT+3, the timezone + # is *not* GMT. + res.tzname = None + + # Check for a numbered timezone + elif res.hour is not None and l[i] in ('+', '-'): + signal = (-1, 1)[l[i] == '+'] + len_li = len(l[i + 1]) + + # TODO: check that l[i + 1] is integer? + if len_li == 4: + # -0300 + hour_offset = int(l[i + 1][:2]) + min_offset = int(l[i + 1][2:]) + elif i + 2 < len_l and l[i + 2] == ':': + # -03:00 + hour_offset = int(l[i + 1]) + min_offset = int(l[i + 3]) # TODO: Check that l[i+3] is minute-like? + i += 2 + elif len_li <= 2: + # -[0]3 + hour_offset = int(l[i + 1][:2]) + min_offset = 0 + else: + raise ValueError(timestr) + + res.tzoffset = signal * (hour_offset * 3600 + min_offset * 60) + + # Look for a timezone name between parenthesis + if (i + 5 < len_l and + info.jump(l[i + 2]) and l[i + 3] == '(' and + l[i + 5] == ')' and + 3 <= len(l[i + 4]) and + self._could_be_tzname(res.hour, res.tzname, + None, l[i + 4])): + # -0300 (BRST) + res.tzname = l[i + 4] + i += 4 + + i += 1 + + # Check jumps + elif not (info.jump(l[i]) or fuzzy): + raise ValueError(timestr) + + else: + skipped_idxs.append(i) + i += 1 + + # Process year/month/day + year, month, day = ymd.resolve_ymd(yearfirst, dayfirst) + + res.century_specified = ymd.century_specified + res.year = year + res.month = month + res.day = day + + except (IndexError, ValueError): + return None, None + + if not info.validate(res): + return None, None + + if fuzzy_with_tokens: + skipped_tokens = self._recombine_skipped(l, skipped_idxs) + return res, tuple(skipped_tokens) + else: + return res, None + + def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): + # Token is a number + value_repr = tokens[idx] + try: + value = self._to_decimal(value_repr) + except Exception as e: + six.raise_from(ValueError('Unknown numeric token'), e) + + len_li = len(value_repr) + + len_l = len(tokens) + + if (len(ymd) == 3 and len_li in (2, 4) and + res.hour is None and + (idx + 1 >= len_l or + (tokens[idx + 1] != ':' and + info.hms(tokens[idx + 1]) is None))): + # 19990101T23[59] + s = tokens[idx] + res.hour = int(s[:2]) + + if len_li == 4: + res.minute = int(s[2:]) + + elif len_li == 6 or (len_li > 6 and tokens[idx].find('.') == 6): + # YYMMDD or HHMMSS[.ss] + s = tokens[idx] + + if not ymd and '.' not in tokens[idx]: + ymd.append(s[:2]) + ymd.append(s[2:4]) + ymd.append(s[4:]) + else: + # 19990101T235959[.59] + + # TODO: Check if res attributes already set. + res.hour = int(s[:2]) + res.minute = int(s[2:4]) + res.second, res.microsecond = self._parsems(s[4:]) + + elif len_li in (8, 12, 14): + # YYYYMMDD + s = tokens[idx] + ymd.append(s[:4], 'Y') + ymd.append(s[4:6]) + ymd.append(s[6:8]) + + if len_li > 8: + res.hour = int(s[8:10]) + res.minute = int(s[10:12]) + + if len_li > 12: + res.second = int(s[12:]) + + elif self._find_hms_idx(idx, tokens, info, allow_jump=True) is not None: + # HH[ ]h or MM[ ]m or SS[.ss][ ]s + hms_idx = self._find_hms_idx(idx, tokens, info, allow_jump=True) + (idx, hms) = self._parse_hms(idx, tokens, info, hms_idx) + if hms is not None: + # TODO: checking that hour/minute/second are not + # already set? + self._assign_hms(res, value_repr, hms) + + elif idx + 2 < len_l and tokens[idx + 1] == ':': + # HH:MM[:SS[.ss]] + res.hour = int(value) + value = self._to_decimal(tokens[idx + 2]) # TODO: try/except for this? + (res.minute, res.second) = self._parse_min_sec(value) + + if idx + 4 < len_l and tokens[idx + 3] == ':': + res.second, res.microsecond = self._parsems(tokens[idx + 4]) + + idx += 2 + + idx += 2 + + elif idx + 1 < len_l and tokens[idx + 1] in ('-', '/', '.'): + sep = tokens[idx + 1] + ymd.append(value_repr) + + if idx + 2 < len_l and not info.jump(tokens[idx + 2]): + if tokens[idx + 2].isdigit(): + # 01-01[-01] + ymd.append(tokens[idx + 2]) + else: + # 01-Jan[-01] + value = info.month(tokens[idx + 2]) + + if value is not None: + ymd.append(value, 'M') + else: + raise ValueError() + + if idx + 3 < len_l and tokens[idx + 3] == sep: + # We have three members + value = info.month(tokens[idx + 4]) + + if value is not None: + ymd.append(value, 'M') + else: + ymd.append(tokens[idx + 4]) + idx += 2 + + idx += 1 + idx += 1 + + elif idx + 1 >= len_l or info.jump(tokens[idx + 1]): + if idx + 2 < len_l and info.ampm(tokens[idx + 2]) is not None: + # 12 am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 2])) + idx += 1 + else: + # Year, month or day + ymd.append(value) + idx += 1 + + elif info.ampm(tokens[idx + 1]) is not None and (0 <= value < 24): + # 12am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 1])) + idx += 1 + + elif ymd.could_be_day(value): + ymd.append(value) + + elif not fuzzy: + raise ValueError() + + return idx + + def _find_hms_idx(self, idx, tokens, info, allow_jump): + len_l = len(tokens) + + if idx+1 < len_l and info.hms(tokens[idx+1]) is not None: + # There is an "h", "m", or "s" label following this token. We take + # assign the upcoming label to the current token. + # e.g. the "12" in 12h" + hms_idx = idx + 1 + + elif (allow_jump and idx+2 < len_l and tokens[idx+1] == ' ' and + info.hms(tokens[idx+2]) is not None): + # There is a space and then an "h", "m", or "s" label. + # e.g. the "12" in "12 h" + hms_idx = idx + 2 + + elif idx > 0 and info.hms(tokens[idx-1]) is not None: + # There is a "h", "m", or "s" preceding this token. Since neither + # of the previous cases was hit, there is no label following this + # token, so we use the previous label. + # e.g. the "04" in "12h04" + hms_idx = idx-1 + + elif (1 < idx == len_l-1 and tokens[idx-1] == ' ' and + info.hms(tokens[idx-2]) is not None): + # If we are looking at the final token, we allow for a + # backward-looking check to skip over a space. + # TODO: Are we sure this is the right condition here? + hms_idx = idx - 2 + + else: + hms_idx = None + + return hms_idx + + def _assign_hms(self, res, value_repr, hms): + # See GH issue #427, fixing float rounding + value = self._to_decimal(value_repr) + + if hms == 0: + # Hour + res.hour = int(value) + if value % 1: + res.minute = int(60*(value % 1)) + + elif hms == 1: + (res.minute, res.second) = self._parse_min_sec(value) + + elif hms == 2: + (res.second, res.microsecond) = self._parsems(value_repr) + + def _could_be_tzname(self, hour, tzname, tzoffset, token): + return (hour is not None and + tzname is None and + tzoffset is None and + len(token) <= 5 and + (all(x in string.ascii_uppercase for x in token) + or token in self.info.UTCZONE)) + + def _ampm_valid(self, hour, ampm, fuzzy): + """ + For fuzzy parsing, 'a' or 'am' (both valid English words) + may erroneously trigger the AM/PM flag. Deal with that + here. + """ + val_is_ampm = True + + # If there's already an AM/PM flag, this one isn't one. + if fuzzy and ampm is not None: + val_is_ampm = False + + # If AM/PM is found and hour is not, raise a ValueError + if hour is None: + if fuzzy: + val_is_ampm = False + else: + raise ValueError('No hour specified with AM or PM flag.') + elif not 0 <= hour <= 12: + # If AM/PM is found, it's a 12 hour clock, so raise + # an error for invalid range + if fuzzy: + val_is_ampm = False + else: + raise ValueError('Invalid hour specified for 12-hour clock.') + + return val_is_ampm + + def _adjust_ampm(self, hour, ampm): + if hour < 12 and ampm == 1: + hour += 12 + elif hour == 12 and ampm == 0: + hour = 0 + return hour + + def _parse_min_sec(self, value): + # TODO: Every usage of this function sets res.second to the return + # value. Are there any cases where second will be returned as None and + # we *don't* want to set res.second = None? + minute = int(value) + second = None + + sec_remainder = value % 1 + if sec_remainder: + second = int(60 * sec_remainder) + return (minute, second) + + def _parse_hms(self, idx, tokens, info, hms_idx): + # TODO: Is this going to admit a lot of false-positives for when we + # just happen to have digits and "h", "m" or "s" characters in non-date + # text? I guess hex hashes won't have that problem, but there's plenty + # of random junk out there. + if hms_idx is None: + hms = None + new_idx = idx + elif hms_idx > idx: + hms = info.hms(tokens[hms_idx]) + new_idx = hms_idx + else: + # Looking backwards, increment one. + hms = info.hms(tokens[hms_idx]) + 1 + new_idx = idx + + return (new_idx, hms) + + # ------------------------------------------------------------------ + # Handling for individual tokens. These are kept as methods instead + # of functions for the sake of customizability via subclassing. + + def _parsems(self, value): + """Parse a I[.F] seconds value into (seconds, microseconds).""" + if "." not in value: + return int(value), 0 + else: + i, f = value.split(".") + return int(i), int(f.ljust(6, "0")[:6]) + + def _to_decimal(self, val): + try: + decimal_value = Decimal(val) + # See GH 662, edge case, infinite value should not be converted + # via `_to_decimal` + if not decimal_value.is_finite(): + raise ValueError("Converted decimal value is infinite or NaN") + except Exception as e: + msg = "Could not convert %s to decimal" % val + six.raise_from(ValueError(msg), e) + else: + return decimal_value + + # ------------------------------------------------------------------ + # Post-Parsing construction of datetime output. These are kept as + # methods instead of functions for the sake of customizability via + # subclassing. + + def _build_tzinfo(self, tzinfos, tzname, tzoffset): + if callable(tzinfos): + tzdata = tzinfos(tzname, tzoffset) + else: + tzdata = tzinfos.get(tzname) + # handle case where tzinfo is paased an options that returns None + # eg tzinfos = {'BRST' : None} + if isinstance(tzdata, datetime.tzinfo) or tzdata is None: + tzinfo = tzdata + elif isinstance(tzdata, text_type): + tzinfo = tz.tzstr(tzdata) + elif isinstance(tzdata, integer_types): + tzinfo = tz.tzoffset(tzname, tzdata) + else: + raise TypeError("Offset must be tzinfo subclass, tz string, " + "or int offset.") + return tzinfo + + def _build_tzaware(self, naive, res, tzinfos): + if (callable(tzinfos) or (tzinfos and res.tzname in tzinfos)): + tzinfo = self._build_tzinfo(tzinfos, res.tzname, res.tzoffset) + aware = naive.replace(tzinfo=tzinfo) + aware = self._assign_tzname(aware, res.tzname) + + elif res.tzname and res.tzname in time.tzname: + aware = naive.replace(tzinfo=tz.tzlocal()) + + # Handle ambiguous local datetime + aware = self._assign_tzname(aware, res.tzname) + + # This is mostly relevant for winter GMT zones parsed in the UK + if (aware.tzname() != res.tzname and + res.tzname in self.info.UTCZONE): + aware = aware.replace(tzinfo=tz.UTC) + + elif res.tzoffset == 0: + aware = naive.replace(tzinfo=tz.UTC) + + elif res.tzoffset: + aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) + + elif not res.tzname and not res.tzoffset: + # i.e. no timezone information was found. + aware = naive + + elif res.tzname: + # tz-like string was parsed but we don't know what to do + # with it + warnings.warn("tzname {tzname} identified but not understood. " + "Pass `tzinfos` argument in order to correctly " + "return a timezone-aware datetime. In a future " + "version, this will raise an " + "exception.".format(tzname=res.tzname), + category=UnknownTimezoneWarning) + aware = naive + + return aware + + def _build_naive(self, res, default): + repl = {} + for attr in ("year", "month", "day", "hour", + "minute", "second", "microsecond"): + value = getattr(res, attr) + if value is not None: + repl[attr] = value + + if 'day' not in repl: + # If the default day exceeds the last day of the month, fall back + # to the end of the month. + cyear = default.year if res.year is None else res.year + cmonth = default.month if res.month is None else res.month + cday = default.day if res.day is None else res.day + + if cday > monthrange(cyear, cmonth)[1]: + repl['day'] = monthrange(cyear, cmonth)[1] + + naive = default.replace(**repl) + + if res.weekday is not None and not res.day: + naive = naive + relativedelta.relativedelta(weekday=res.weekday) + + return naive + + def _assign_tzname(self, dt, tzname): + if dt.tzname() != tzname: + new_dt = tz.enfold(dt, fold=1) + if new_dt.tzname() == tzname: + return new_dt + + return dt + + def _recombine_skipped(self, tokens, skipped_idxs): + """ + >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] + >>> skipped_idxs = [0, 1, 2, 5] + >>> _recombine_skipped(tokens, skipped_idxs) + ["foo bar", "baz"] + """ + skipped_tokens = [] + for i, idx in enumerate(sorted(skipped_idxs)): + if i > 0 and idx - 1 == skipped_idxs[i - 1]: + skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] + else: + skipped_tokens.append(tokens[idx]) + + return skipped_tokens + + +DEFAULTPARSER = parser() + + +def parse(timestr, parserinfo=None, **kwargs): + """ + + Parse a string in one of the supported formats, using the + ``parserinfo`` parameters. + + :param timestr: + A string containing a date/time stamp. + + :param parserinfo: + A :class:`parserinfo` object containing parameters for the parser. + If ``None``, the default arguments to the :class:`parserinfo` + constructor are used. + + The ``**kwargs`` parameter takes the following keyword arguments: + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM and + YMD. If set to ``None``, this value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken to + be the year, otherwise the last number is taken to be the year. If + this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ParserError: + Raised for invalid or unknown string formats, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date would + be created. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + if parserinfo: + return parser(parserinfo).parse(timestr, **kwargs) + else: + return DEFAULTPARSER.parse(timestr, **kwargs) + + +class _tzparser(object): + + class _result(_resultbase): + + __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", + "start", "end"] + + class _attr(_resultbase): + __slots__ = ["month", "week", "weekday", + "yday", "jyday", "day", "time"] + + def __repr__(self): + return self._repr("") + + def __init__(self): + _resultbase.__init__(self) + self.start = self._attr() + self.end = self._attr() + + def parse(self, tzstr): + res = self._result() + l = [x for x in re.split(r'([,:.]|[a-zA-Z]+|[0-9]+)',tzstr) if x] + used_idxs = list() + try: + + len_l = len(l) + + i = 0 + while i < len_l: + # BRST+3[BRDT[+2]] + j = i + while j < len_l and not [x for x in l[j] + if x in "0123456789:,-+"]: + j += 1 + if j != i: + if not res.stdabbr: + offattr = "stdoffset" + res.stdabbr = "".join(l[i:j]) + else: + offattr = "dstoffset" + res.dstabbr = "".join(l[i:j]) + + for ii in range(j): + used_idxs.append(ii) + i = j + if (i < len_l and (l[i] in ('+', '-') or l[i][0] in + "0123456789")): + if l[i] in ('+', '-'): + # Yes, that's right. See the TZ variable + # documentation. + signal = (1, -1)[l[i] == '+'] + used_idxs.append(i) + i += 1 + else: + signal = -1 + len_li = len(l[i]) + if len_li == 4: + # -0300 + setattr(res, offattr, (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) * signal) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + setattr(res, offattr, + (int(l[i]) * 3600 + + int(l[i + 2]) * 60) * signal) + used_idxs.append(i) + i += 2 + elif len_li <= 2: + # -[0]3 + setattr(res, offattr, + int(l[i][:2]) * 3600 * signal) + else: + return None + used_idxs.append(i) + i += 1 + if res.dstabbr: + break + else: + break + + + if i < len_l: + for j in range(i, len_l): + if l[j] == ';': + l[j] = ',' + + assert l[i] == ',' + + i += 1 + + if i >= len_l: + pass + elif (8 <= l.count(',') <= 9 and + not [y for x in l[i:] if x != ',' + for y in x if y not in "0123456789+-"]): + # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] + for x in (res.start, res.end): + x.month = int(l[i]) + used_idxs.append(i) + i += 2 + if l[i] == '-': + value = int(l[i + 1]) * -1 + used_idxs.append(i) + i += 1 + else: + value = int(l[i]) + used_idxs.append(i) + i += 2 + if value: + x.week = value + x.weekday = (int(l[i]) - 1) % 7 + else: + x.day = int(l[i]) + used_idxs.append(i) + i += 2 + x.time = int(l[i]) + used_idxs.append(i) + i += 2 + if i < len_l: + if l[i] in ('-', '+'): + signal = (-1, 1)[l[i] == "+"] + used_idxs.append(i) + i += 1 + else: + signal = 1 + used_idxs.append(i) + res.dstoffset = (res.stdoffset + int(l[i]) * signal) + + # This was a made-up format that is not in normal use + warn(('Parsed time zone "%s"' % tzstr) + + 'is in a non-standard dateutil-specific format, which ' + + 'is now deprecated; support for parsing this format ' + + 'will be removed in future versions. It is recommended ' + + 'that you switch to a standard format like the GNU ' + + 'TZ variable format.', tz.DeprecatedTzFormatWarning) + elif (l.count(',') == 2 and l[i:].count('/') <= 2 and + not [y for x in l[i:] if x not in (',', '/', 'J', 'M', + '.', '-', ':') + for y in x if y not in "0123456789"]): + for x in (res.start, res.end): + if l[i] == 'J': + # non-leap year day (1 based) + used_idxs.append(i) + i += 1 + x.jyday = int(l[i]) + elif l[i] == 'M': + # month[-.]week[-.]weekday + used_idxs.append(i) + i += 1 + x.month = int(l[i]) + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.week = int(l[i]) + if x.week == 5: + x.week = -1 + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.weekday = (int(l[i]) - 1) % 7 + else: + # year day (zero based) + x.yday = int(l[i]) + 1 + + used_idxs.append(i) + i += 1 + + if i < len_l and l[i] == '/': + used_idxs.append(i) + i += 1 + # start time + len_li = len(l[i]) + if len_li == 4: + # -0300 + x.time = (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + x.time = int(l[i]) * 3600 + int(l[i + 2]) * 60 + used_idxs.append(i) + i += 2 + if i + 1 < len_l and l[i + 1] == ':': + used_idxs.append(i) + i += 2 + x.time += int(l[i]) + elif len_li <= 2: + # -[0]3 + x.time = (int(l[i][:2]) * 3600) + else: + return None + used_idxs.append(i) + i += 1 + + assert i == len_l or l[i] == ',' + + i += 1 + + assert i >= len_l + + except (IndexError, ValueError, AssertionError): + return None + + unused_idxs = set(range(len_l)).difference(used_idxs) + res.any_unused_tokens = not {l[n] for n in unused_idxs}.issubset({",",":"}) + return res + + +DEFAULTTZPARSER = _tzparser() + + +def _parsetz(tzstr): + return DEFAULTTZPARSER.parse(tzstr) + + +class ParserError(ValueError): + """Exception subclass used for any failure to parse a datetime string. + + This is a subclass of :py:exc:`ValueError`, and should be raised any time + earlier versions of ``dateutil`` would have raised ``ValueError``. + + .. versionadded:: 2.8.1 + """ + def __str__(self): + try: + return self.args[0] % self.args[1:] + except (TypeError, IndexError): + return super(ParserError, self).__str__() + + def __repr__(self): + args = ", ".join("'%s'" % arg for arg in self.args) + return "%s(%s)" % (self.__class__.__name__, args) + + +class UnknownTimezoneWarning(RuntimeWarning): + """Raised when the parser finds a timezone it cannot parse into a tzinfo. + + .. versionadded:: 2.7.0 + """ +# vim:ts=4:sw=4:et diff --git a/.venv/Lib/site-packages/dateutil/parser/isoparser.py b/.venv/Lib/site-packages/dateutil/parser/isoparser.py new file mode 100644 index 00000000..7060087d --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/parser/isoparser.py @@ -0,0 +1,416 @@ +# -*- coding: utf-8 -*- +""" +This module offers a parser for ISO-8601 strings + +It is intended to support all valid date, time and datetime formats per the +ISO-8601 specification. + +..versionadded:: 2.7.0 +""" +from datetime import datetime, timedelta, time, date +import calendar +from dateutil import tz + +from functools import wraps + +import re +import six + +__all__ = ["isoparse", "isoparser"] + + +def _takes_ascii(f): + @wraps(f) + def func(self, str_in, *args, **kwargs): + # If it's a stream, read the whole thing + str_in = getattr(str_in, 'read', lambda: str_in)() + + # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII + if isinstance(str_in, six.text_type): + # ASCII is the same in UTF-8 + try: + str_in = str_in.encode('ascii') + except UnicodeEncodeError as e: + msg = 'ISO-8601 strings should contain only ASCII characters' + six.raise_from(ValueError(msg), e) + + return f(self, str_in, *args, **kwargs) + + return func + + +class isoparser(object): + def __init__(self, sep=None): + """ + :param sep: + A single character that separates date and time portions. If + ``None``, the parser will accept any single character. + For strict ISO-8601 adherence, pass ``'T'``. + """ + if sep is not None: + if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'): + raise ValueError('Separator must be a single, non-numeric ' + + 'ASCII character') + + sep = sep.encode('ascii') + + self._sep = sep + + @_takes_ascii + def isoparse(self, dt_str): + """ + Parse an ISO-8601 datetime string into a :class:`datetime.datetime`. + + An ISO-8601 datetime string consists of a date portion, followed + optionally by a time portion - the date and time portions are separated + by a single character separator, which is ``T`` in the official + standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be + combined with a time portion. + + Supported date formats are: + + Common: + + - ``YYYY`` + - ``YYYY-MM`` + - ``YYYY-MM-DD`` or ``YYYYMMDD`` + + Uncommon: + + - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0) + - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day + + The ISO week and day numbering follows the same logic as + :func:`datetime.date.isocalendar`. + + Supported time formats are: + + - ``hh`` + - ``hh:mm`` or ``hhmm`` + - ``hh:mm:ss`` or ``hhmmss`` + - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) + + Midnight is a special case for `hh`, as the standard supports both + 00:00 and 24:00 as a representation. The decimal separator can be + either a dot or a comma. + + + .. caution:: + + Support for fractional components other than seconds is part of the + ISO-8601 standard, but is not currently implemented in this parser. + + Supported time zone offset formats are: + + - `Z` (UTC) + - `±HH:MM` + - `±HHMM` + - `±HH` + + Offsets will be represented as :class:`dateutil.tz.tzoffset` objects, + with the exception of UTC, which will be represented as + :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such + as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`. + + :param dt_str: + A string or stream containing only an ISO-8601 datetime string + + :return: + Returns a :class:`datetime.datetime` representing the string. + Unspecified components default to their lowest value. + + .. warning:: + + As of version 2.7.0, the strictness of the parser should not be + considered a stable part of the contract. Any valid ISO-8601 string + that parses correctly with the default settings will continue to + parse correctly in future versions, but invalid strings that + currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not + guaranteed to continue failing in future versions if they encode + a valid date. + + .. versionadded:: 2.7.0 + """ + components, pos = self._parse_isodate(dt_str) + + if len(dt_str) > pos: + if self._sep is None or dt_str[pos:pos + 1] == self._sep: + components += self._parse_isotime(dt_str[pos + 1:]) + else: + raise ValueError('String contains unknown ISO components') + + if len(components) > 3 and components[3] == 24: + components[3] = 0 + return datetime(*components) + timedelta(days=1) + + return datetime(*components) + + @_takes_ascii + def parse_isodate(self, datestr): + """ + Parse the date portion of an ISO string. + + :param datestr: + The string portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.date` object + """ + components, pos = self._parse_isodate(datestr) + if pos < len(datestr): + raise ValueError('String contains unknown ISO ' + + 'components: {!r}'.format(datestr.decode('ascii'))) + return date(*components) + + @_takes_ascii + def parse_isotime(self, timestr): + """ + Parse the time portion of an ISO string. + + :param timestr: + The time portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.time` object + """ + components = self._parse_isotime(timestr) + if components[0] == 24: + components[0] = 0 + return time(*components) + + @_takes_ascii + def parse_tzstr(self, tzstr, zero_as_utc=True): + """ + Parse a valid ISO time zone string. + + See :func:`isoparser.isoparse` for details on supported formats. + + :param tzstr: + A string representing an ISO time zone offset + + :param zero_as_utc: + Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones + + :return: + Returns :class:`dateutil.tz.tzoffset` for offsets and + :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is + specified) offsets equivalent to UTC. + """ + return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc) + + # Constants + _DATE_SEP = b'-' + _TIME_SEP = b':' + _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') + + def _parse_isodate(self, dt_str): + try: + return self._parse_isodate_common(dt_str) + except ValueError: + return self._parse_isodate_uncommon(dt_str) + + def _parse_isodate_common(self, dt_str): + len_str = len(dt_str) + components = [1, 1, 1] + + if len_str < 4: + raise ValueError('ISO string too short') + + # Year + components[0] = int(dt_str[0:4]) + pos = 4 + if pos >= len_str: + return components, pos + + has_sep = dt_str[pos:pos + 1] == self._DATE_SEP + if has_sep: + pos += 1 + + # Month + if len_str - pos < 2: + raise ValueError('Invalid common month') + + components[1] = int(dt_str[pos:pos + 2]) + pos += 2 + + if pos >= len_str: + if has_sep: + return components, pos + else: + raise ValueError('Invalid ISO format') + + if has_sep: + if dt_str[pos:pos + 1] != self._DATE_SEP: + raise ValueError('Invalid separator in ISO string') + pos += 1 + + # Day + if len_str - pos < 2: + raise ValueError('Invalid common day') + components[2] = int(dt_str[pos:pos + 2]) + return components, pos + 2 + + def _parse_isodate_uncommon(self, dt_str): + if len(dt_str) < 4: + raise ValueError('ISO string too short') + + # All ISO formats start with the year + year = int(dt_str[0:4]) + + has_sep = dt_str[4:5] == self._DATE_SEP + + pos = 4 + has_sep # Skip '-' if it's there + if dt_str[pos:pos + 1] == b'W': + # YYYY-?Www-?D? + pos += 1 + weekno = int(dt_str[pos:pos + 2]) + pos += 2 + + dayno = 1 + if len(dt_str) > pos: + if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep: + raise ValueError('Inconsistent use of dash separator') + + pos += has_sep + + dayno = int(dt_str[pos:pos + 1]) + pos += 1 + + base_date = self._calculate_weekdate(year, weekno, dayno) + else: + # YYYYDDD or YYYY-DDD + if len(dt_str) - pos < 3: + raise ValueError('Invalid ordinal day') + + ordinal_day = int(dt_str[pos:pos + 3]) + pos += 3 + + if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)): + raise ValueError('Invalid ordinal day' + + ' {} for year {}'.format(ordinal_day, year)) + + base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1) + + components = [base_date.year, base_date.month, base_date.day] + return components, pos + + def _calculate_weekdate(self, year, week, day): + """ + Calculate the day of corresponding to the ISO year-week-day calendar. + + This function is effectively the inverse of + :func:`datetime.date.isocalendar`. + + :param year: + The year in the ISO calendar + + :param week: + The week in the ISO calendar - range is [1, 53] + + :param day: + The day in the ISO calendar - range is [1 (MON), 7 (SUN)] + + :return: + Returns a :class:`datetime.date` + """ + if not 0 < week < 54: + raise ValueError('Invalid week: {}'.format(week)) + + if not 0 < day < 8: # Range is 1-7 + raise ValueError('Invalid weekday: {}'.format(day)) + + # Get week 1 for the specific year: + jan_4 = date(year, 1, 4) # Week 1 always has January 4th in it + week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1) + + # Now add the specific number of weeks and days to get what we want + week_offset = (week - 1) * 7 + (day - 1) + return week_1 + timedelta(days=week_offset) + + def _parse_isotime(self, timestr): + len_str = len(timestr) + components = [0, 0, 0, 0, None] + pos = 0 + comp = -1 + + if len_str < 2: + raise ValueError('ISO time too short') + + has_sep = False + + while pos < len_str and comp < 5: + comp += 1 + + if timestr[pos:pos + 1] in b'-+Zz': + # Detect time zone boundary + components[-1] = self._parse_tzstr(timestr[pos:]) + pos = len_str + break + + if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: + has_sep = True + pos += 1 + elif comp == 2 and has_sep: + if timestr[pos:pos+1] != self._TIME_SEP: + raise ValueError('Inconsistent use of colon separator') + pos += 1 + + if comp < 3: + # Hour, minute, second + components[comp] = int(timestr[pos:pos + 2]) + pos += 2 + + if comp == 3: + # Fraction of a second + frac = self._FRACTION_REGEX.match(timestr[pos:]) + if not frac: + continue + + us_str = frac.group(1)[:6] # Truncate to microseconds + components[comp] = int(us_str) * 10**(6 - len(us_str)) + pos += len(frac.group()) + + if pos < len_str: + raise ValueError('Unused components in ISO string') + + if components[0] == 24: + # Standard supports 00:00 and 24:00 as representations of midnight + if any(component != 0 for component in components[1:4]): + raise ValueError('Hour may only be 24 at 24:00:00.000') + + return components + + def _parse_tzstr(self, tzstr, zero_as_utc=True): + if tzstr == b'Z' or tzstr == b'z': + return tz.UTC + + if len(tzstr) not in {3, 5, 6}: + raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') + + if tzstr[0:1] == b'-': + mult = -1 + elif tzstr[0:1] == b'+': + mult = 1 + else: + raise ValueError('Time zone offset requires sign') + + hours = int(tzstr[1:3]) + if len(tzstr) == 3: + minutes = 0 + else: + minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) + + if zero_as_utc and hours == 0 and minutes == 0: + return tz.UTC + else: + if minutes > 59: + raise ValueError('Invalid minutes in time zone offset') + + if hours > 23: + raise ValueError('Invalid hours in time zone offset') + + return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60) + + +DEFAULT_ISOPARSER = isoparser() +isoparse = DEFAULT_ISOPARSER.isoparse diff --git a/.venv/Lib/site-packages/dateutil/relativedelta.py b/.venv/Lib/site-packages/dateutil/relativedelta.py new file mode 100644 index 00000000..cd323a54 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/relativedelta.py @@ -0,0 +1,599 @@ +# -*- coding: utf-8 -*- +import datetime +import calendar + +import operator +from math import copysign + +from six import integer_types +from warnings import warn + +from ._common import weekday + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + +__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + + +class relativedelta(object): + """ + The relativedelta type is designed to be applied to an existing datetime and + can replace specific components of that datetime, or represents an interval + of time. + + It is based on the specification of the excellent work done by M.-A. Lemburg + in his + `mx.DateTime `_ extension. + However, notice that this type does *NOT* implement the same algorithm as + his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. + + There are two different ways to build a relativedelta instance. The + first one is passing it two date/datetime classes:: + + relativedelta(datetime1, datetime2) + + The second one is passing it any number of the following keyword arguments:: + + relativedelta(arg1=x,arg2=y,arg3=z...) + + year, month, day, hour, minute, second, microsecond: + Absolute information (argument is singular); adding or subtracting a + relativedelta with absolute information does not perform an arithmetic + operation, but rather REPLACES the corresponding value in the + original datetime with the value(s) in relativedelta. + + years, months, weeks, days, hours, minutes, seconds, microseconds: + Relative information, may be negative (argument is plural); adding + or subtracting a relativedelta with relative information performs + the corresponding arithmetic operation on the original datetime value + with the information in the relativedelta. + + weekday: + One of the weekday instances (MO, TU, etc) available in the + relativedelta module. These instances may receive a parameter N, + specifying the Nth weekday, which could be positive or negative + (like MO(+1) or MO(-2)). Not specifying it is the same as specifying + +1. You can also use an integer, where 0=MO. This argument is always + relative e.g. if the calculated date is already Monday, using MO(1) + or MO(-1) won't change the day. To effectively make it absolute, use + it in combination with the day argument (e.g. day=1, MO(1) for first + Monday of the month). + + leapdays: + Will add given days to the date found, if year is a leap + year, and the date found is post 28 of february. + + yearday, nlyearday: + Set the yearday or the non-leap year day (jump leap days). + These are converted to day/month/leapdays information. + + There are relative and absolute forms of the keyword + arguments. The plural is relative, and the singular is + absolute. For each argument in the order below, the absolute form + is applied first (by setting each attribute to that value) and + then the relative form (by adding the value to the attribute). + + The order of attributes considered when this relativedelta is + added to a datetime is: + + 1. Year + 2. Month + 3. Day + 4. Hours + 5. Minutes + 6. Seconds + 7. Microseconds + + Finally, weekday is applied, using the rule described above. + + For example + + >>> from datetime import datetime + >>> from dateutil.relativedelta import relativedelta, MO + >>> dt = datetime(2018, 4, 9, 13, 37, 0) + >>> delta = relativedelta(hours=25, day=1, weekday=MO(1)) + >>> dt + delta + datetime.datetime(2018, 4, 2, 14, 37) + + First, the day is set to 1 (the first of the month), then 25 hours + are added, to get to the 2nd day and 14th hour, finally the + weekday is applied, but since the 2nd is already a Monday there is + no effect. + + """ + + def __init__(self, dt1=None, dt2=None, + years=0, months=0, days=0, leapdays=0, weeks=0, + hours=0, minutes=0, seconds=0, microseconds=0, + year=None, month=None, day=None, weekday=None, + yearday=None, nlyearday=None, + hour=None, minute=None, second=None, microsecond=None): + + if dt1 and dt2: + # datetime is a subclass of date. So both must be date + if not (isinstance(dt1, datetime.date) and + isinstance(dt2, datetime.date)): + raise TypeError("relativedelta only diffs datetime/date") + + # We allow two dates, or two datetimes, so we coerce them to be + # of the same type + if (isinstance(dt1, datetime.datetime) != + isinstance(dt2, datetime.datetime)): + if not isinstance(dt1, datetime.datetime): + dt1 = datetime.datetime.fromordinal(dt1.toordinal()) + elif not isinstance(dt2, datetime.datetime): + dt2 = datetime.datetime.fromordinal(dt2.toordinal()) + + self.years = 0 + self.months = 0 + self.days = 0 + self.leapdays = 0 + self.hours = 0 + self.minutes = 0 + self.seconds = 0 + self.microseconds = 0 + self.year = None + self.month = None + self.day = None + self.weekday = None + self.hour = None + self.minute = None + self.second = None + self.microsecond = None + self._has_time = 0 + + # Get year / month delta between the two + months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month) + self._set_months(months) + + # Remove the year/month delta so the timedelta is just well-defined + # time units (seconds, days and microseconds) + dtm = self.__radd__(dt2) + + # If we've overshot our target, make an adjustment + if dt1 < dt2: + compare = operator.gt + increment = 1 + else: + compare = operator.lt + increment = -1 + + while compare(dt1, dtm): + months += increment + self._set_months(months) + dtm = self.__radd__(dt2) + + # Get the timedelta between the "months-adjusted" date and dt1 + delta = dt1 - dtm + self.seconds = delta.seconds + delta.days * 86400 + self.microseconds = delta.microseconds + else: + # Check for non-integer values in integer-only quantities + if any(x is not None and x != int(x) for x in (years, months)): + raise ValueError("Non-integer years and months are " + "ambiguous and not currently supported.") + + # Relative information + self.years = int(years) + self.months = int(months) + self.days = days + weeks * 7 + self.leapdays = leapdays + self.hours = hours + self.minutes = minutes + self.seconds = seconds + self.microseconds = microseconds + + # Absolute information + self.year = year + self.month = month + self.day = day + self.hour = hour + self.minute = minute + self.second = second + self.microsecond = microsecond + + if any(x is not None and int(x) != x + for x in (year, month, day, hour, + minute, second, microsecond)): + # For now we'll deprecate floats - later it'll be an error. + warn("Non-integer value passed as absolute information. " + + "This is not a well-defined condition and will raise " + + "errors in future versions.", DeprecationWarning) + + if isinstance(weekday, integer_types): + self.weekday = weekdays[weekday] + else: + self.weekday = weekday + + yday = 0 + if nlyearday: + yday = nlyearday + elif yearday: + yday = yearday + if yearday > 59: + self.leapdays = -1 + if yday: + ydayidx = [31, 59, 90, 120, 151, 181, 212, + 243, 273, 304, 334, 366] + for idx, ydays in enumerate(ydayidx): + if yday <= ydays: + self.month = idx+1 + if idx == 0: + self.day = yday + else: + self.day = yday-ydayidx[idx-1] + break + else: + raise ValueError("invalid year day (%d)" % yday) + + self._fix() + + def _fix(self): + if abs(self.microseconds) > 999999: + s = _sign(self.microseconds) + div, mod = divmod(self.microseconds * s, 1000000) + self.microseconds = mod * s + self.seconds += div * s + if abs(self.seconds) > 59: + s = _sign(self.seconds) + div, mod = divmod(self.seconds * s, 60) + self.seconds = mod * s + self.minutes += div * s + if abs(self.minutes) > 59: + s = _sign(self.minutes) + div, mod = divmod(self.minutes * s, 60) + self.minutes = mod * s + self.hours += div * s + if abs(self.hours) > 23: + s = _sign(self.hours) + div, mod = divmod(self.hours * s, 24) + self.hours = mod * s + self.days += div * s + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years += div * s + if (self.hours or self.minutes or self.seconds or self.microseconds + or self.hour is not None or self.minute is not None or + self.second is not None or self.microsecond is not None): + self._has_time = 1 + else: + self._has_time = 0 + + @property + def weeks(self): + return int(self.days / 7.0) + + @weeks.setter + def weeks(self, value): + self.days = self.days - (self.weeks * 7) + value * 7 + + def _set_months(self, months): + self.months = months + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years = div * s + else: + self.years = 0 + + def normalized(self): + """ + Return a version of this object represented entirely using integer + values for the relative attributes. + + >>> relativedelta(days=1.5, hours=2).normalized() + relativedelta(days=+1, hours=+14) + + :return: + Returns a :class:`dateutil.relativedelta.relativedelta` object. + """ + # Cascade remainders down (rounding each to roughly nearest microsecond) + days = int(self.days) + + hours_f = round(self.hours + 24 * (self.days - days), 11) + hours = int(hours_f) + + minutes_f = round(self.minutes + 60 * (hours_f - hours), 10) + minutes = int(minutes_f) + + seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8) + seconds = int(seconds_f) + + microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds)) + + # Constructor carries overflow back up with call to _fix() + return self.__class__(years=self.years, months=self.months, + days=days, hours=hours, minutes=minutes, + seconds=seconds, microseconds=microseconds, + leapdays=self.leapdays, year=self.year, + month=self.month, day=self.day, + weekday=self.weekday, hour=self.hour, + minute=self.minute, second=self.second, + microsecond=self.microsecond) + + def __add__(self, other): + if isinstance(other, relativedelta): + return self.__class__(years=other.years + self.years, + months=other.months + self.months, + days=other.days + self.days, + hours=other.hours + self.hours, + minutes=other.minutes + self.minutes, + seconds=other.seconds + self.seconds, + microseconds=(other.microseconds + + self.microseconds), + leapdays=other.leapdays or self.leapdays, + year=(other.year if other.year is not None + else self.year), + month=(other.month if other.month is not None + else self.month), + day=(other.day if other.day is not None + else self.day), + weekday=(other.weekday if other.weekday is not None + else self.weekday), + hour=(other.hour if other.hour is not None + else self.hour), + minute=(other.minute if other.minute is not None + else self.minute), + second=(other.second if other.second is not None + else self.second), + microsecond=(other.microsecond if other.microsecond + is not None else + self.microsecond)) + if isinstance(other, datetime.timedelta): + return self.__class__(years=self.years, + months=self.months, + days=self.days + other.days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds + other.seconds, + microseconds=self.microseconds + other.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + if not isinstance(other, datetime.date): + return NotImplemented + elif self._has_time and not isinstance(other, datetime.datetime): + other = datetime.datetime.fromordinal(other.toordinal()) + year = (self.year or other.year)+self.years + month = self.month or other.month + if self.months: + assert 1 <= abs(self.months) <= 12 + month += self.months + if month > 12: + year += 1 + month -= 12 + elif month < 1: + year -= 1 + month += 12 + day = min(calendar.monthrange(year, month)[1], + self.day or other.day) + repl = {"year": year, "month": month, "day": day} + for attr in ["hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + repl[attr] = value + days = self.days + if self.leapdays and month > 2 and calendar.isleap(year): + days += self.leapdays + ret = (other.replace(**repl) + + datetime.timedelta(days=days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds, + microseconds=self.microseconds)) + if self.weekday: + weekday, nth = self.weekday.weekday, self.weekday.n or 1 + jumpdays = (abs(nth) - 1) * 7 + if nth > 0: + jumpdays += (7 - ret.weekday() + weekday) % 7 + else: + jumpdays += (ret.weekday() - weekday) % 7 + jumpdays *= -1 + ret += datetime.timedelta(days=jumpdays) + return ret + + def __radd__(self, other): + return self.__add__(other) + + def __rsub__(self, other): + return self.__neg__().__radd__(other) + + def __sub__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented # In case the other object defines __rsub__ + return self.__class__(years=self.years - other.years, + months=self.months - other.months, + days=self.days - other.days, + hours=self.hours - other.hours, + minutes=self.minutes - other.minutes, + seconds=self.seconds - other.seconds, + microseconds=self.microseconds - other.microseconds, + leapdays=self.leapdays or other.leapdays, + year=(self.year if self.year is not None + else other.year), + month=(self.month if self.month is not None else + other.month), + day=(self.day if self.day is not None else + other.day), + weekday=(self.weekday if self.weekday is not None else + other.weekday), + hour=(self.hour if self.hour is not None else + other.hour), + minute=(self.minute if self.minute is not None else + other.minute), + second=(self.second if self.second is not None else + other.second), + microsecond=(self.microsecond if self.microsecond + is not None else + other.microsecond)) + + def __abs__(self): + return self.__class__(years=abs(self.years), + months=abs(self.months), + days=abs(self.days), + hours=abs(self.hours), + minutes=abs(self.minutes), + seconds=abs(self.seconds), + microseconds=abs(self.microseconds), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __neg__(self): + return self.__class__(years=-self.years, + months=-self.months, + days=-self.days, + hours=-self.hours, + minutes=-self.minutes, + seconds=-self.seconds, + microseconds=-self.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __bool__(self): + return not (not self.years and + not self.months and + not self.days and + not self.hours and + not self.minutes and + not self.seconds and + not self.microseconds and + not self.leapdays and + self.year is None and + self.month is None and + self.day is None and + self.weekday is None and + self.hour is None and + self.minute is None and + self.second is None and + self.microsecond is None) + # Compatibility with Python 2.x + __nonzero__ = __bool__ + + def __mul__(self, other): + try: + f = float(other) + except TypeError: + return NotImplemented + + return self.__class__(years=int(self.years * f), + months=int(self.months * f), + days=int(self.days * f), + hours=int(self.hours * f), + minutes=int(self.minutes * f), + seconds=int(self.seconds * f), + microseconds=int(self.microseconds * f), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + __rmul__ = __mul__ + + def __eq__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented + if self.weekday or other.weekday: + if not self.weekday or not other.weekday: + return False + if self.weekday.weekday != other.weekday.weekday: + return False + n1, n2 = self.weekday.n, other.weekday.n + if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): + return False + return (self.years == other.years and + self.months == other.months and + self.days == other.days and + self.hours == other.hours and + self.minutes == other.minutes and + self.seconds == other.seconds and + self.microseconds == other.microseconds and + self.leapdays == other.leapdays and + self.year == other.year and + self.month == other.month and + self.day == other.day and + self.hour == other.hour and + self.minute == other.minute and + self.second == other.second and + self.microsecond == other.microsecond) + + def __hash__(self): + return hash(( + self.weekday, + self.years, + self.months, + self.days, + self.hours, + self.minutes, + self.seconds, + self.microseconds, + self.leapdays, + self.year, + self.month, + self.day, + self.hour, + self.minute, + self.second, + self.microsecond, + )) + + def __ne__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + try: + reciprocal = 1 / float(other) + except TypeError: + return NotImplemented + + return self.__mul__(reciprocal) + + __truediv__ = __div__ + + def __repr__(self): + l = [] + for attr in ["years", "months", "days", "leapdays", + "hours", "minutes", "seconds", "microseconds"]: + value = getattr(self, attr) + if value: + l.append("{attr}={value:+g}".format(attr=attr, value=value)) + for attr in ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + l.append("{attr}={value}".format(attr=attr, value=repr(value))) + return "{classname}({attrs})".format(classname=self.__class__.__name__, + attrs=", ".join(l)) + + +def _sign(x): + return int(copysign(1, x)) + +# vim:ts=4:sw=4:et diff --git a/.venv/Lib/site-packages/dateutil/rrule.py b/.venv/Lib/site-packages/dateutil/rrule.py new file mode 100644 index 00000000..571a0d2b --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/rrule.py @@ -0,0 +1,1737 @@ +# -*- coding: utf-8 -*- +""" +The rrule module offers a small, complete, and very fast, implementation of +the recurrence rules documented in the +`iCalendar RFC `_, +including support for caching of results. +""" +import calendar +import datetime +import heapq +import itertools +import re +import sys +from functools import wraps +# For warning about deprecation of until and count +from warnings import warn + +from six import advance_iterator, integer_types + +from six.moves import _thread, range + +from ._common import weekday as weekdaybase + +try: + from math import gcd +except ImportError: + from fractions import gcd + +__all__ = ["rrule", "rruleset", "rrulestr", + "YEARLY", "MONTHLY", "WEEKLY", "DAILY", + "HOURLY", "MINUTELY", "SECONDLY", + "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + +# Every mask is 7 days longer to handle cross-year weekly periods. +M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + + [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) +M365MASK = list(M366MASK) +M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) +MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +MDAY365MASK = list(MDAY366MASK) +M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) +NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +NMDAY365MASK = list(NMDAY366MASK) +M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) +M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) +WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 +del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] +MDAY365MASK = tuple(MDAY365MASK) +M365MASK = tuple(M365MASK) + +FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY'] + +(YEARLY, + MONTHLY, + WEEKLY, + DAILY, + HOURLY, + MINUTELY, + SECONDLY) = list(range(7)) + +# Imported on demand. +easter = None +parser = None + + +class weekday(weekdaybase): + """ + This version of weekday does not allow n = 0. + """ + def __init__(self, wkday, n=None): + if n == 0: + raise ValueError("Can't create weekday with n==0") + + super(weekday, self).__init__(wkday, n) + + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + + +def _invalidates_cache(f): + """ + Decorator for rruleset methods which may invalidate the + cached length. + """ + @wraps(f) + def inner_func(self, *args, **kwargs): + rv = f(self, *args, **kwargs) + self._invalidate_cache() + return rv + + return inner_func + + +class rrulebase(object): + def __init__(self, cache=False): + if cache: + self._cache = [] + self._cache_lock = _thread.allocate_lock() + self._invalidate_cache() + else: + self._cache = None + self._cache_complete = False + self._len = None + + def __iter__(self): + if self._cache_complete: + return iter(self._cache) + elif self._cache is None: + return self._iter() + else: + return self._iter_cached() + + def _invalidate_cache(self): + if self._cache is not None: + self._cache = [] + self._cache_complete = False + self._cache_gen = self._iter() + + if self._cache_lock.locked(): + self._cache_lock.release() + + self._len = None + + def _iter_cached(self): + i = 0 + gen = self._cache_gen + cache = self._cache + acquire = self._cache_lock.acquire + release = self._cache_lock.release + while gen: + if i == len(cache): + acquire() + if self._cache_complete: + break + try: + for j in range(10): + cache.append(advance_iterator(gen)) + except StopIteration: + self._cache_gen = gen = None + self._cache_complete = True + break + release() + yield cache[i] + i += 1 + while i < self._len: + yield cache[i] + i += 1 + + def __getitem__(self, item): + if self._cache_complete: + return self._cache[item] + elif isinstance(item, slice): + if item.step and item.step < 0: + return list(iter(self))[item] + else: + return list(itertools.islice(self, + item.start or 0, + item.stop or sys.maxsize, + item.step or 1)) + elif item >= 0: + gen = iter(self) + try: + for i in range(item+1): + res = advance_iterator(gen) + except StopIteration: + raise IndexError + return res + else: + return list(iter(self))[item] + + def __contains__(self, item): + if self._cache_complete: + return item in self._cache + else: + for i in self: + if i == item: + return True + elif i > item: + return False + return False + + # __len__() introduces a large performance penalty. + def count(self): + """ Returns the number of recurrences in this set. It will have go + through the whole recurrence, if this hasn't been done before. """ + if self._len is None: + for x in self: + pass + return self._len + + def before(self, dt, inc=False): + """ Returns the last recurrence before the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + last = None + if inc: + for i in gen: + if i > dt: + break + last = i + else: + for i in gen: + if i >= dt: + break + last = i + return last + + def after(self, dt, inc=False): + """ Returns the first recurrence after the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + if inc: + for i in gen: + if i >= dt: + return i + else: + for i in gen: + if i > dt: + return i + return None + + def xafter(self, dt, count=None, inc=False): + """ + Generator which yields up to `count` recurrences after the given + datetime instance, equivalent to `after`. + + :param dt: + The datetime at which to start generating recurrences. + + :param count: + The maximum number of recurrences to generate. If `None` (default), + dates are generated until the recurrence rule is exhausted. + + :param inc: + If `dt` is an instance of the rule and `inc` is `True`, it is + included in the output. + + :yields: Yields a sequence of `datetime` objects. + """ + + if self._cache_complete: + gen = self._cache + else: + gen = self + + # Select the comparison function + if inc: + comp = lambda dc, dtc: dc >= dtc + else: + comp = lambda dc, dtc: dc > dtc + + # Generate dates + n = 0 + for d in gen: + if comp(d, dt): + if count is not None: + n += 1 + if n > count: + break + + yield d + + def between(self, after, before, inc=False, count=1): + """ Returns all the occurrences of the rrule between after and before. + The inc keyword defines what happens if after and/or before are + themselves occurrences. With inc=True, they will be included in the + list, if they are found in the recurrence set. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + started = False + l = [] + if inc: + for i in gen: + if i > before: + break + elif not started: + if i >= after: + started = True + l.append(i) + else: + l.append(i) + else: + for i in gen: + if i >= before: + break + elif not started: + if i > after: + started = True + l.append(i) + else: + l.append(i) + return l + + +class rrule(rrulebase): + """ + That's the base of the rrule operation. It accepts all the keywords + defined in the RFC as its constructor parameters (except byday, + which was renamed to byweekday) and more. The constructor prototype is:: + + rrule(freq) + + Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, + or SECONDLY. + + .. note:: + Per RFC section 3.3.10, recurrence instances falling on invalid dates + and times are ignored rather than coerced: + + Recurrence rules may generate recurrence instances with an invalid + date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM + on a day where the local time is moved forward by an hour at 1:00 + AM). Such recurrence instances MUST be ignored and MUST NOT be + counted as part of the recurrence set. + + This can lead to possibly surprising behavior when, for example, the + start date occurs at the end of the month: + + >>> from dateutil.rrule import rrule, MONTHLY + >>> from datetime import datetime + >>> start_date = datetime(2014, 12, 31) + >>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date)) + ... # doctest: +NORMALIZE_WHITESPACE + [datetime.datetime(2014, 12, 31, 0, 0), + datetime.datetime(2015, 1, 31, 0, 0), + datetime.datetime(2015, 3, 31, 0, 0), + datetime.datetime(2015, 5, 31, 0, 0)] + + Additionally, it supports the following keyword arguments: + + :param dtstart: + The recurrence start. Besides being the base for the recurrence, + missing parameters in the final recurrence instances will also be + extracted from this date. If not given, datetime.now() will be used + instead. + :param interval: + The interval between each freq iteration. For example, when using + YEARLY, an interval of 2 means once every two years, but with HOURLY, + it means once every two hours. The default interval is 1. + :param wkst: + The week start day. Must be one of the MO, TU, WE constants, or an + integer, specifying the first day of the week. This will affect + recurrences based on weekly periods. The default week start is got + from calendar.firstweekday(), and may be modified by + calendar.setfirstweekday(). + :param count: + If given, this determines how many occurrences will be generated. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param until: + If given, this must be a datetime instance specifying the upper-bound + limit of the recurrence. The last recurrence in the rule is the greatest + datetime that is less than or equal to the value specified in the + ``until`` parameter. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param bysetpos: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each given integer will specify an occurrence + number, corresponding to the nth occurrence of the rule inside the + frequency period. For example, a bysetpos of -1 if combined with a + MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will + result in the last work day of every month. + :param bymonth: + If given, it must be either an integer, or a sequence of integers, + meaning the months to apply the recurrence to. + :param bymonthday: + If given, it must be either an integer, or a sequence of integers, + meaning the month days to apply the recurrence to. + :param byyearday: + If given, it must be either an integer, or a sequence of integers, + meaning the year days to apply the recurrence to. + :param byeaster: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each integer will define an offset from the + Easter Sunday. Passing the offset 0 to byeaster will yield the Easter + Sunday itself. This is an extension to the RFC specification. + :param byweekno: + If given, it must be either an integer, or a sequence of integers, + meaning the week numbers to apply the recurrence to. Week numbers + have the meaning described in ISO8601, that is, the first week of + the year is that containing at least four days of the new year. + :param byweekday: + If given, it must be either an integer (0 == MO), a sequence of + integers, one of the weekday constants (MO, TU, etc), or a sequence + of these constants. When given, these variables will define the + weekdays where the recurrence will be applied. It's also possible to + use an argument n for the weekday instances, which will mean the nth + occurrence of this weekday in the period. For example, with MONTHLY, + or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the + first friday of the month where the recurrence happens. Notice that in + the RFC documentation, this is specified as BYDAY, but was renamed to + avoid the ambiguity of that keyword. + :param byhour: + If given, it must be either an integer, or a sequence of integers, + meaning the hours to apply the recurrence to. + :param byminute: + If given, it must be either an integer, or a sequence of integers, + meaning the minutes to apply the recurrence to. + :param bysecond: + If given, it must be either an integer, or a sequence of integers, + meaning the seconds to apply the recurrence to. + :param cache: + If given, it must be a boolean value specifying to enable or disable + caching of results. If you will use the same rrule instance multiple + times, enabling caching will improve the performance considerably. + """ + def __init__(self, freq, dtstart=None, + interval=1, wkst=None, count=None, until=None, bysetpos=None, + bymonth=None, bymonthday=None, byyearday=None, byeaster=None, + byweekno=None, byweekday=None, + byhour=None, byminute=None, bysecond=None, + cache=False): + super(rrule, self).__init__(cache) + global easter + if not dtstart: + if until and until.tzinfo: + dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0) + else: + dtstart = datetime.datetime.now().replace(microsecond=0) + elif not isinstance(dtstart, datetime.datetime): + dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) + else: + dtstart = dtstart.replace(microsecond=0) + self._dtstart = dtstart + self._tzinfo = dtstart.tzinfo + self._freq = freq + self._interval = interval + self._count = count + + # Cache the original byxxx rules, if they are provided, as the _byxxx + # attributes do not necessarily map to the inputs, and this can be + # a problem in generating the strings. Only store things if they've + # been supplied (the string retrieval will just use .get()) + self._original_rule = {} + + if until and not isinstance(until, datetime.datetime): + until = datetime.datetime.fromordinal(until.toordinal()) + self._until = until + + if self._dtstart and self._until: + if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None): + # According to RFC5545 Section 3.3.10: + # https://tools.ietf.org/html/rfc5545#section-3.3.10 + # + # > If the "DTSTART" property is specified as a date with UTC + # > time or a date with local time and time zone reference, + # > then the UNTIL rule part MUST be specified as a date with + # > UTC time. + raise ValueError( + 'RRULE UNTIL values must be specified in UTC when DTSTART ' + 'is timezone-aware' + ) + + if count is not None and until: + warn("Using both 'count' and 'until' is inconsistent with RFC 5545" + " and has been deprecated in dateutil. Future versions will " + "raise an error.", DeprecationWarning) + + if wkst is None: + self._wkst = calendar.firstweekday() + elif isinstance(wkst, integer_types): + self._wkst = wkst + else: + self._wkst = wkst.weekday + + if bysetpos is None: + self._bysetpos = None + elif isinstance(bysetpos, integer_types): + if bysetpos == 0 or not (-366 <= bysetpos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + self._bysetpos = (bysetpos,) + else: + self._bysetpos = tuple(bysetpos) + for pos in self._bysetpos: + if pos == 0 or not (-366 <= pos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + + if self._bysetpos: + self._original_rule['bysetpos'] = self._bysetpos + + if (byweekno is None and byyearday is None and bymonthday is None and + byweekday is None and byeaster is None): + if freq == YEARLY: + if bymonth is None: + bymonth = dtstart.month + self._original_rule['bymonth'] = None + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == MONTHLY: + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == WEEKLY: + byweekday = dtstart.weekday() + self._original_rule['byweekday'] = None + + # bymonth + if bymonth is None: + self._bymonth = None + else: + if isinstance(bymonth, integer_types): + bymonth = (bymonth,) + + self._bymonth = tuple(sorted(set(bymonth))) + + if 'bymonth' not in self._original_rule: + self._original_rule['bymonth'] = self._bymonth + + # byyearday + if byyearday is None: + self._byyearday = None + else: + if isinstance(byyearday, integer_types): + byyearday = (byyearday,) + + self._byyearday = tuple(sorted(set(byyearday))) + self._original_rule['byyearday'] = self._byyearday + + # byeaster + if byeaster is not None: + if not easter: + from dateutil import easter + if isinstance(byeaster, integer_types): + self._byeaster = (byeaster,) + else: + self._byeaster = tuple(sorted(byeaster)) + + self._original_rule['byeaster'] = self._byeaster + else: + self._byeaster = None + + # bymonthday + if bymonthday is None: + self._bymonthday = () + self._bynmonthday = () + else: + if isinstance(bymonthday, integer_types): + bymonthday = (bymonthday,) + + bymonthday = set(bymonthday) # Ensure it's unique + + self._bymonthday = tuple(sorted(x for x in bymonthday if x > 0)) + self._bynmonthday = tuple(sorted(x for x in bymonthday if x < 0)) + + # Storing positive numbers first, then negative numbers + if 'bymonthday' not in self._original_rule: + self._original_rule['bymonthday'] = tuple( + itertools.chain(self._bymonthday, self._bynmonthday)) + + # byweekno + if byweekno is None: + self._byweekno = None + else: + if isinstance(byweekno, integer_types): + byweekno = (byweekno,) + + self._byweekno = tuple(sorted(set(byweekno))) + + self._original_rule['byweekno'] = self._byweekno + + # byweekday / bynweekday + if byweekday is None: + self._byweekday = None + self._bynweekday = None + else: + # If it's one of the valid non-sequence types, convert to a + # single-element sequence before the iterator that builds the + # byweekday set. + if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"): + byweekday = (byweekday,) + + self._byweekday = set() + self._bynweekday = set() + for wday in byweekday: + if isinstance(wday, integer_types): + self._byweekday.add(wday) + elif not wday.n or freq > MONTHLY: + self._byweekday.add(wday.weekday) + else: + self._bynweekday.add((wday.weekday, wday.n)) + + if not self._byweekday: + self._byweekday = None + elif not self._bynweekday: + self._bynweekday = None + + if self._byweekday is not None: + self._byweekday = tuple(sorted(self._byweekday)) + orig_byweekday = [weekday(x) for x in self._byweekday] + else: + orig_byweekday = () + + if self._bynweekday is not None: + self._bynweekday = tuple(sorted(self._bynweekday)) + orig_bynweekday = [weekday(*x) for x in self._bynweekday] + else: + orig_bynweekday = () + + if 'byweekday' not in self._original_rule: + self._original_rule['byweekday'] = tuple(itertools.chain( + orig_byweekday, orig_bynweekday)) + + # byhour + if byhour is None: + if freq < HOURLY: + self._byhour = {dtstart.hour} + else: + self._byhour = None + else: + if isinstance(byhour, integer_types): + byhour = (byhour,) + + if freq == HOURLY: + self._byhour = self.__construct_byset(start=dtstart.hour, + byxxx=byhour, + base=24) + else: + self._byhour = set(byhour) + + self._byhour = tuple(sorted(self._byhour)) + self._original_rule['byhour'] = self._byhour + + # byminute + if byminute is None: + if freq < MINUTELY: + self._byminute = {dtstart.minute} + else: + self._byminute = None + else: + if isinstance(byminute, integer_types): + byminute = (byminute,) + + if freq == MINUTELY: + self._byminute = self.__construct_byset(start=dtstart.minute, + byxxx=byminute, + base=60) + else: + self._byminute = set(byminute) + + self._byminute = tuple(sorted(self._byminute)) + self._original_rule['byminute'] = self._byminute + + # bysecond + if bysecond is None: + if freq < SECONDLY: + self._bysecond = ((dtstart.second,)) + else: + self._bysecond = None + else: + if isinstance(bysecond, integer_types): + bysecond = (bysecond,) + + self._bysecond = set(bysecond) + + if freq == SECONDLY: + self._bysecond = self.__construct_byset(start=dtstart.second, + byxxx=bysecond, + base=60) + else: + self._bysecond = set(bysecond) + + self._bysecond = tuple(sorted(self._bysecond)) + self._original_rule['bysecond'] = self._bysecond + + if self._freq >= HOURLY: + self._timeset = None + else: + self._timeset = [] + for hour in self._byhour: + for minute in self._byminute: + for second in self._bysecond: + self._timeset.append( + datetime.time(hour, minute, second, + tzinfo=self._tzinfo)) + self._timeset.sort() + self._timeset = tuple(self._timeset) + + def __str__(self): + """ + Output a string that would generate this RRULE if passed to rrulestr. + This is mostly compatible with RFC5545, except for the + dateutil-specific extension BYEASTER. + """ + + output = [] + h, m, s = [None] * 3 + if self._dtstart: + output.append(self._dtstart.strftime('DTSTART:%Y%m%dT%H%M%S')) + h, m, s = self._dtstart.timetuple()[3:6] + + parts = ['FREQ=' + FREQNAMES[self._freq]] + if self._interval != 1: + parts.append('INTERVAL=' + str(self._interval)) + + if self._wkst: + parts.append('WKST=' + repr(weekday(self._wkst))[0:2]) + + if self._count is not None: + parts.append('COUNT=' + str(self._count)) + + if self._until: + parts.append(self._until.strftime('UNTIL=%Y%m%dT%H%M%S')) + + if self._original_rule.get('byweekday') is not None: + # The str() method on weekday objects doesn't generate + # RFC5545-compliant strings, so we should modify that. + original_rule = dict(self._original_rule) + wday_strings = [] + for wday in original_rule['byweekday']: + if wday.n: + wday_strings.append('{n:+d}{wday}'.format( + n=wday.n, + wday=repr(wday)[0:2])) + else: + wday_strings.append(repr(wday)) + + original_rule['byweekday'] = wday_strings + else: + original_rule = self._original_rule + + partfmt = '{name}={vals}' + for name, key in [('BYSETPOS', 'bysetpos'), + ('BYMONTH', 'bymonth'), + ('BYMONTHDAY', 'bymonthday'), + ('BYYEARDAY', 'byyearday'), + ('BYWEEKNO', 'byweekno'), + ('BYDAY', 'byweekday'), + ('BYHOUR', 'byhour'), + ('BYMINUTE', 'byminute'), + ('BYSECOND', 'bysecond'), + ('BYEASTER', 'byeaster')]: + value = original_rule.get(key) + if value: + parts.append(partfmt.format(name=name, vals=(','.join(str(v) + for v in value)))) + + output.append('RRULE:' + ';'.join(parts)) + return '\n'.join(output) + + def replace(self, **kwargs): + """Return new rrule with same attributes except for those attributes given new + values by whichever keyword arguments are specified.""" + new_kwargs = {"interval": self._interval, + "count": self._count, + "dtstart": self._dtstart, + "freq": self._freq, + "until": self._until, + "wkst": self._wkst, + "cache": False if self._cache is None else True } + new_kwargs.update(self._original_rule) + new_kwargs.update(kwargs) + return rrule(**new_kwargs) + + def _iter(self): + year, month, day, hour, minute, second, weekday, yearday, _ = \ + self._dtstart.timetuple() + + # Some local variables to speed things up a bit + freq = self._freq + interval = self._interval + wkst = self._wkst + until = self._until + bymonth = self._bymonth + byweekno = self._byweekno + byyearday = self._byyearday + byweekday = self._byweekday + byeaster = self._byeaster + bymonthday = self._bymonthday + bynmonthday = self._bynmonthday + bysetpos = self._bysetpos + byhour = self._byhour + byminute = self._byminute + bysecond = self._bysecond + + ii = _iterinfo(self) + ii.rebuild(year, month) + + getdayset = {YEARLY: ii.ydayset, + MONTHLY: ii.mdayset, + WEEKLY: ii.wdayset, + DAILY: ii.ddayset, + HOURLY: ii.ddayset, + MINUTELY: ii.ddayset, + SECONDLY: ii.ddayset}[freq] + + if freq < HOURLY: + timeset = self._timeset + else: + gettimeset = {HOURLY: ii.htimeset, + MINUTELY: ii.mtimeset, + SECONDLY: ii.stimeset}[freq] + if ((freq >= HOURLY and + self._byhour and hour not in self._byhour) or + (freq >= MINUTELY and + self._byminute and minute not in self._byminute) or + (freq >= SECONDLY and + self._bysecond and second not in self._bysecond)): + timeset = () + else: + timeset = gettimeset(hour, minute, second) + + total = 0 + count = self._count + while True: + # Get dayset with the right frequency + dayset, start, end = getdayset(year, month, day) + + # Do the "hard" work ;-) + filtered = False + for i in dayset[start:end]: + if ((bymonth and ii.mmask[i] not in bymonth) or + (byweekno and not ii.wnomask[i]) or + (byweekday and ii.wdaymask[i] not in byweekday) or + (ii.nwdaymask and not ii.nwdaymask[i]) or + (byeaster and not ii.eastermask[i]) or + ((bymonthday or bynmonthday) and + ii.mdaymask[i] not in bymonthday and + ii.nmdaymask[i] not in bynmonthday) or + (byyearday and + ((i < ii.yearlen and i+1 not in byyearday and + -ii.yearlen+i not in byyearday) or + (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and + -ii.nextyearlen+i-ii.yearlen not in byyearday)))): + dayset[i] = None + filtered = True + + # Output results + if bysetpos and timeset: + poslist = [] + for pos in bysetpos: + if pos < 0: + daypos, timepos = divmod(pos, len(timeset)) + else: + daypos, timepos = divmod(pos-1, len(timeset)) + try: + i = [x for x in dayset[start:end] + if x is not None][daypos] + time = timeset[timepos] + except IndexError: + pass + else: + date = datetime.date.fromordinal(ii.yearordinal+i) + res = datetime.datetime.combine(date, time) + if res not in poslist: + poslist.append(res) + poslist.sort() + for res in poslist: + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + total += 1 + yield res + else: + for i in dayset[start:end]: + if i is not None: + date = datetime.date.fromordinal(ii.yearordinal + i) + for time in timeset: + res = datetime.datetime.combine(date, time) + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + + total += 1 + yield res + + # Handle frequency and interval + fixday = False + if freq == YEARLY: + year += interval + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == MONTHLY: + month += interval + if month > 12: + div, mod = divmod(month, 12) + month = mod + year += div + if month == 0: + month = 12 + year -= 1 + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == WEEKLY: + if wkst > weekday: + day += -(weekday+1+(6-wkst))+self._interval*7 + else: + day += -(weekday-wkst)+self._interval*7 + weekday = wkst + fixday = True + elif freq == DAILY: + day += interval + fixday = True + elif freq == HOURLY: + if filtered: + # Jump to one iteration before next day + hour += ((23-hour)//interval)*interval + + if byhour: + ndays, hour = self.__mod_distance(value=hour, + byxxx=self._byhour, + base=24) + else: + ndays, hour = divmod(hour+interval, 24) + + if ndays: + day += ndays + fixday = True + + timeset = gettimeset(hour, minute, second) + elif freq == MINUTELY: + if filtered: + # Jump to one iteration before next day + minute += ((1439-(hour*60+minute))//interval)*interval + + valid = False + rep_rate = (24*60) + for j in range(rep_rate // gcd(interval, rep_rate)): + if byminute: + nhours, minute = \ + self.__mod_distance(value=minute, + byxxx=self._byminute, + base=60) + else: + nhours, minute = divmod(minute+interval, 60) + + div, hour = divmod(hour+nhours, 24) + if div: + day += div + fixday = True + filtered = False + + if not byhour or hour in byhour: + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval and ' + + 'byhour resulting in empty rule.') + + timeset = gettimeset(hour, minute, second) + elif freq == SECONDLY: + if filtered: + # Jump to one iteration before next day + second += (((86399 - (hour * 3600 + minute * 60 + second)) + // interval) * interval) + + rep_rate = (24 * 3600) + valid = False + for j in range(0, rep_rate // gcd(interval, rep_rate)): + if bysecond: + nminutes, second = \ + self.__mod_distance(value=second, + byxxx=self._bysecond, + base=60) + else: + nminutes, second = divmod(second+interval, 60) + + div, minute = divmod(minute+nminutes, 60) + if div: + hour += div + div, hour = divmod(hour, 24) + if div: + day += div + fixday = True + + if ((not byhour or hour in byhour) and + (not byminute or minute in byminute) and + (not bysecond or second in bysecond)): + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval, ' + + 'byhour and byminute resulting in empty' + + ' rule.') + + timeset = gettimeset(hour, minute, second) + + if fixday and day > 28: + daysinmonth = calendar.monthrange(year, month)[1] + if day > daysinmonth: + while day > daysinmonth: + day -= daysinmonth + month += 1 + if month == 13: + month = 1 + year += 1 + if year > datetime.MAXYEAR: + self._len = total + return + daysinmonth = calendar.monthrange(year, month)[1] + ii.rebuild(year, month) + + def __construct_byset(self, start, byxxx, base): + """ + If a `BYXXX` sequence is passed to the constructor at the same level as + `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some + specifications which cannot be reached given some starting conditions. + + This occurs whenever the interval is not coprime with the base of a + given unit and the difference between the starting position and the + ending position is not coprime with the greatest common denominator + between the interval and the base. For example, with a FREQ of hourly + starting at 17:00 and an interval of 4, the only valid values for + BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not + coprime. + + :param start: + Specifies the starting position. + :param byxxx: + An iterable containing the list of allowed values. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + This does not preserve the type of the iterable, returning a set, since + the values should be unique and the order is irrelevant, this will + speed up later lookups. + + In the event of an empty set, raises a :exception:`ValueError`, as this + results in an empty rrule. + """ + + cset = set() + + # Support a single byxxx value. + if isinstance(byxxx, integer_types): + byxxx = (byxxx, ) + + for num in byxxx: + i_gcd = gcd(self._interval, base) + # Use divmod rather than % because we need to wrap negative nums. + if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: + cset.add(num) + + if len(cset) == 0: + raise ValueError("Invalid rrule byxxx generates an empty set.") + + return cset + + def __mod_distance(self, value, byxxx, base): + """ + Calculates the next value in a sequence where the `FREQ` parameter is + specified along with a `BYXXX` parameter at the same "level" + (e.g. `HOURLY` specified with `BYHOUR`). + + :param value: + The old value of the component. + :param byxxx: + The `BYXXX` set, which should have been generated by + `rrule._construct_byset`, or something else which checks that a + valid rule is present. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + If a valid value is not found after `base` iterations (the maximum + number before the sequence would start to repeat), this raises a + :exception:`ValueError`, as no valid values were found. + + This returns a tuple of `divmod(n*interval, base)`, where `n` is the + smallest number of `interval` repetitions until the next specified + value in `byxxx` is found. + """ + accumulator = 0 + for ii in range(1, base + 1): + # Using divmod() over % to account for negative intervals + div, value = divmod(value + self._interval, base) + accumulator += div + if value in byxxx: + return (accumulator, value) + + +class _iterinfo(object): + __slots__ = ["rrule", "lastyear", "lastmonth", + "yearlen", "nextyearlen", "yearordinal", "yearweekday", + "mmask", "mrange", "mdaymask", "nmdaymask", + "wdaymask", "wnomask", "nwdaymask", "eastermask"] + + def __init__(self, rrule): + for attr in self.__slots__: + setattr(self, attr, None) + self.rrule = rrule + + def rebuild(self, year, month): + # Every mask is 7 days longer to handle cross-year weekly periods. + rr = self.rrule + if year != self.lastyear: + self.yearlen = 365 + calendar.isleap(year) + self.nextyearlen = 365 + calendar.isleap(year + 1) + firstyday = datetime.date(year, 1, 1) + self.yearordinal = firstyday.toordinal() + self.yearweekday = firstyday.weekday() + + wday = datetime.date(year, 1, 1).weekday() + if self.yearlen == 365: + self.mmask = M365MASK + self.mdaymask = MDAY365MASK + self.nmdaymask = NMDAY365MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M365RANGE + else: + self.mmask = M366MASK + self.mdaymask = MDAY366MASK + self.nmdaymask = NMDAY366MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M366RANGE + + if not rr._byweekno: + self.wnomask = None + else: + self.wnomask = [0]*(self.yearlen+7) + # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) + no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 + if no1wkst >= 4: + no1wkst = 0 + # Number of days in the year, plus the days we got + # from last year. + wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 + else: + # Number of days in the year, minus the days we + # left in last year. + wyearlen = self.yearlen-no1wkst + div, mod = divmod(wyearlen, 7) + numweeks = div+mod//4 + for n in rr._byweekno: + if n < 0: + n += numweeks+1 + if not (0 < n <= numweeks): + continue + if n > 1: + i = no1wkst+(n-1)*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + else: + i = no1wkst + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if 1 in rr._byweekno: + # Check week number 1 of next year as well + # TODO: Check -numweeks for next year. + i = no1wkst+numweeks*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + if i < self.yearlen: + # If week starts in next year, we + # don't care about it. + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if no1wkst: + # Check last week number of last year as + # well. If no1wkst is 0, either the year + # started on week start, or week number 1 + # got days from last year, so there are no + # days from last year's last week number in + # this year. + if -1 not in rr._byweekno: + lyearweekday = datetime.date(year-1, 1, 1).weekday() + lno1wkst = (7-lyearweekday+rr._wkst) % 7 + lyearlen = 365+calendar.isleap(year-1) + if lno1wkst >= 4: + lno1wkst = 0 + lnumweeks = 52+(lyearlen + + (lyearweekday-rr._wkst) % 7) % 7//4 + else: + lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 + else: + lnumweeks = -1 + if lnumweeks in rr._byweekno: + for i in range(no1wkst): + self.wnomask[i] = 1 + + if (rr._bynweekday and (month != self.lastmonth or + year != self.lastyear)): + ranges = [] + if rr._freq == YEARLY: + if rr._bymonth: + for month in rr._bymonth: + ranges.append(self.mrange[month-1:month+1]) + else: + ranges = [(0, self.yearlen)] + elif rr._freq == MONTHLY: + ranges = [self.mrange[month-1:month+1]] + if ranges: + # Weekly frequency won't get here, so we may not + # care about cross-year weekly periods. + self.nwdaymask = [0]*self.yearlen + for first, last in ranges: + last -= 1 + for wday, n in rr._bynweekday: + if n < 0: + i = last+(n+1)*7 + i -= (self.wdaymask[i]-wday) % 7 + else: + i = first+(n-1)*7 + i += (7-self.wdaymask[i]+wday) % 7 + if first <= i <= last: + self.nwdaymask[i] = 1 + + if rr._byeaster: + self.eastermask = [0]*(self.yearlen+7) + eyday = easter.easter(year).toordinal()-self.yearordinal + for offset in rr._byeaster: + self.eastermask[eyday+offset] = 1 + + self.lastyear = year + self.lastmonth = month + + def ydayset(self, year, month, day): + return list(range(self.yearlen)), 0, self.yearlen + + def mdayset(self, year, month, day): + dset = [None]*self.yearlen + start, end = self.mrange[month-1:month+1] + for i in range(start, end): + dset[i] = i + return dset, start, end + + def wdayset(self, year, month, day): + # We need to handle cross-year weeks here. + dset = [None]*(self.yearlen+7) + i = datetime.date(year, month, day).toordinal()-self.yearordinal + start = i + for j in range(7): + dset[i] = i + i += 1 + # if (not (0 <= i < self.yearlen) or + # self.wdaymask[i] == self.rrule._wkst): + # This will cross the year boundary, if necessary. + if self.wdaymask[i] == self.rrule._wkst: + break + return dset, start, i + + def ddayset(self, year, month, day): + dset = [None] * self.yearlen + i = datetime.date(year, month, day).toordinal() - self.yearordinal + dset[i] = i + return dset, i, i + 1 + + def htimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for minute in rr._byminute: + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, + tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def mtimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def stimeset(self, hour, minute, second): + return (datetime.time(hour, minute, second, + tzinfo=self.rrule._tzinfo),) + + +class rruleset(rrulebase): + """ The rruleset type allows more complex recurrence setups, mixing + multiple rules, dates, exclusion rules, and exclusion dates. The type + constructor takes the following keyword arguments: + + :param cache: If True, caching of results will be enabled, improving + performance of multiple queries considerably. """ + + class _genitem(object): + def __init__(self, genlist, gen): + try: + self.dt = advance_iterator(gen) + genlist.append(self) + except StopIteration: + pass + self.genlist = genlist + self.gen = gen + + def __next__(self): + try: + self.dt = advance_iterator(self.gen) + except StopIteration: + if self.genlist[0] is self: + heapq.heappop(self.genlist) + else: + self.genlist.remove(self) + heapq.heapify(self.genlist) + + next = __next__ + + def __lt__(self, other): + return self.dt < other.dt + + def __gt__(self, other): + return self.dt > other.dt + + def __eq__(self, other): + return self.dt == other.dt + + def __ne__(self, other): + return self.dt != other.dt + + def __init__(self, cache=False): + super(rruleset, self).__init__(cache) + self._rrule = [] + self._rdate = [] + self._exrule = [] + self._exdate = [] + + @_invalidates_cache + def rrule(self, rrule): + """ Include the given :py:class:`rrule` instance in the recurrence set + generation. """ + self._rrule.append(rrule) + + @_invalidates_cache + def rdate(self, rdate): + """ Include the given :py:class:`datetime` instance in the recurrence + set generation. """ + self._rdate.append(rdate) + + @_invalidates_cache + def exrule(self, exrule): + """ Include the given rrule instance in the recurrence set exclusion + list. Dates which are part of the given recurrence rules will not + be generated, even if some inclusive rrule or rdate matches them. + """ + self._exrule.append(exrule) + + @_invalidates_cache + def exdate(self, exdate): + """ Include the given datetime instance in the recurrence set + exclusion list. Dates included that way will not be generated, + even if some inclusive rrule or rdate matches them. """ + self._exdate.append(exdate) + + def _iter(self): + rlist = [] + self._rdate.sort() + self._genitem(rlist, iter(self._rdate)) + for gen in [iter(x) for x in self._rrule]: + self._genitem(rlist, gen) + exlist = [] + self._exdate.sort() + self._genitem(exlist, iter(self._exdate)) + for gen in [iter(x) for x in self._exrule]: + self._genitem(exlist, gen) + lastdt = None + total = 0 + heapq.heapify(rlist) + heapq.heapify(exlist) + while rlist: + ritem = rlist[0] + if not lastdt or lastdt != ritem.dt: + while exlist and exlist[0] < ritem: + exitem = exlist[0] + advance_iterator(exitem) + if exlist and exlist[0] is exitem: + heapq.heapreplace(exlist, exitem) + if not exlist or ritem != exlist[0]: + total += 1 + yield ritem.dt + lastdt = ritem.dt + advance_iterator(ritem) + if rlist and rlist[0] is ritem: + heapq.heapreplace(rlist, ritem) + self._len = total + + + + +class _rrulestr(object): + """ Parses a string representation of a recurrence rule or set of + recurrence rules. + + :param s: + Required, a string defining one or more recurrence rules. + + :param dtstart: + If given, used as the default recurrence start if not specified in the + rule string. + + :param cache: + If set ``True`` caching of results will be enabled, improving + performance of multiple queries considerably. + + :param unfold: + If set ``True`` indicates that a rule string is split over more + than one line and should be joined before processing. + + :param forceset: + If set ``True`` forces a :class:`dateutil.rrule.rruleset` to + be returned. + + :param compatible: + If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime.datetime` object is returned. + + :param tzids: + If given, a callable or mapping used to retrieve a + :class:`datetime.tzinfo` from a string representation. + Defaults to :func:`dateutil.tz.gettz`. + + :param tzinfos: + Additional time zone names / aliases which may be present in a string + representation. See :func:`dateutil.parser.parse` for more + information. + + :return: + Returns a :class:`dateutil.rrule.rruleset` or + :class:`dateutil.rrule.rrule` + """ + + _freq_map = {"YEARLY": YEARLY, + "MONTHLY": MONTHLY, + "WEEKLY": WEEKLY, + "DAILY": DAILY, + "HOURLY": HOURLY, + "MINUTELY": MINUTELY, + "SECONDLY": SECONDLY} + + _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, + "FR": 4, "SA": 5, "SU": 6} + + def _handle_int(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = int(value) + + def _handle_int_list(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = [int(x) for x in value.split(',')] + + _handle_INTERVAL = _handle_int + _handle_COUNT = _handle_int + _handle_BYSETPOS = _handle_int_list + _handle_BYMONTH = _handle_int_list + _handle_BYMONTHDAY = _handle_int_list + _handle_BYYEARDAY = _handle_int_list + _handle_BYEASTER = _handle_int_list + _handle_BYWEEKNO = _handle_int_list + _handle_BYHOUR = _handle_int_list + _handle_BYMINUTE = _handle_int_list + _handle_BYSECOND = _handle_int_list + + def _handle_FREQ(self, rrkwargs, name, value, **kwargs): + rrkwargs["freq"] = self._freq_map[value] + + def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): + global parser + if not parser: + from dateutil import parser + try: + rrkwargs["until"] = parser.parse(value, + ignoretz=kwargs.get("ignoretz"), + tzinfos=kwargs.get("tzinfos")) + except ValueError: + raise ValueError("invalid until date") + + def _handle_WKST(self, rrkwargs, name, value, **kwargs): + rrkwargs["wkst"] = self._weekday_map[value] + + def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwargs): + """ + Two ways to specify this: +1MO or MO(+1) + """ + l = [] + for wday in value.split(','): + if '(' in wday: + # If it's of the form TH(+1), etc. + splt = wday.split('(') + w = splt[0] + n = int(splt[1][:-1]) + elif len(wday): + # If it's of the form +1MO + for i in range(len(wday)): + if wday[i] not in '+-0123456789': + break + n = wday[:i] or None + w = wday[i:] + if n: + n = int(n) + else: + raise ValueError("Invalid (empty) BYDAY specification.") + + l.append(weekdays[self._weekday_map[w]](n)) + rrkwargs["byweekday"] = l + + _handle_BYDAY = _handle_BYWEEKDAY + + def _parse_rfc_rrule(self, line, + dtstart=None, + cache=False, + ignoretz=False, + tzinfos=None): + if line.find(':') != -1: + name, value = line.split(':') + if name != "RRULE": + raise ValueError("unknown parameter name") + else: + value = line + rrkwargs = {} + for pair in value.split(';'): + name, value = pair.split('=') + name = name.upper() + value = value.upper() + try: + getattr(self, "_handle_"+name)(rrkwargs, name, value, + ignoretz=ignoretz, + tzinfos=tzinfos) + except AttributeError: + raise ValueError("unknown parameter '%s'" % name) + except (KeyError, ValueError): + raise ValueError("invalid '%s': %s" % (name, value)) + return rrule(dtstart=dtstart, cache=cache, **rrkwargs) + + def _parse_date_value(self, date_value, parms, rule_tzids, + ignoretz, tzids, tzinfos): + global parser + if not parser: + from dateutil import parser + + datevals = [] + value_found = False + TZID = None + + for parm in parms: + if parm.startswith("TZID="): + try: + tzkey = rule_tzids[parm.split('TZID=')[-1]] + except KeyError: + continue + if tzids is None: + from . import tz + tzlookup = tz.gettz + elif callable(tzids): + tzlookup = tzids + else: + tzlookup = getattr(tzids, 'get', None) + if tzlookup is None: + msg = ('tzids must be a callable, mapping, or None, ' + 'not %s' % tzids) + raise ValueError(msg) + + TZID = tzlookup(tzkey) + continue + + # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found + # only once. + if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: + raise ValueError("unsupported parm: " + parm) + else: + if value_found: + msg = ("Duplicate value parameter found in: " + parm) + raise ValueError(msg) + value_found = True + + for datestr in date_value.split(','): + date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) + if TZID is not None: + if date.tzinfo is None: + date = date.replace(tzinfo=TZID) + else: + raise ValueError('DTSTART/EXDATE specifies multiple timezone') + datevals.append(date) + + return datevals + + def _parse_rfc(self, s, + dtstart=None, + cache=False, + unfold=False, + forceset=False, + compatible=False, + ignoretz=False, + tzids=None, + tzinfos=None): + global parser + if compatible: + forceset = True + unfold = True + + TZID_NAMES = dict(map( + lambda x: (x.upper(), x), + re.findall('TZID=(?P[^:]+):', s) + )) + s = s.upper() + if not s.strip(): + raise ValueError("empty string") + if unfold: + lines = s.splitlines() + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + else: + lines = s.split() + if (not forceset and len(lines) == 1 and (s.find(':') == -1 or + s.startswith('RRULE:'))): + return self._parse_rfc_rrule(lines[0], cache=cache, + dtstart=dtstart, ignoretz=ignoretz, + tzinfos=tzinfos) + else: + rrulevals = [] + rdatevals = [] + exrulevals = [] + exdatevals = [] + for line in lines: + if not line: + continue + if line.find(':') == -1: + name = "RRULE" + value = line + else: + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0] + parms = parms[1:] + if name == "RRULE": + for parm in parms: + raise ValueError("unsupported RRULE parm: "+parm) + rrulevals.append(value) + elif name == "RDATE": + for parm in parms: + if parm != "VALUE=DATE-TIME": + raise ValueError("unsupported RDATE parm: "+parm) + rdatevals.append(value) + elif name == "EXRULE": + for parm in parms: + raise ValueError("unsupported EXRULE parm: "+parm) + exrulevals.append(value) + elif name == "EXDATE": + exdatevals.extend( + self._parse_date_value(value, parms, + TZID_NAMES, ignoretz, + tzids, tzinfos) + ) + elif name == "DTSTART": + dtvals = self._parse_date_value(value, parms, TZID_NAMES, + ignoretz, tzids, tzinfos) + if len(dtvals) != 1: + raise ValueError("Multiple DTSTART values specified:" + + value) + dtstart = dtvals[0] + else: + raise ValueError("unsupported property: "+name) + if (forceset or len(rrulevals) > 1 or rdatevals + or exrulevals or exdatevals): + if not parser and (rdatevals or exdatevals): + from dateutil import parser + rset = rruleset(cache=cache) + for value in rrulevals: + rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in rdatevals: + for datestr in value.split(','): + rset.rdate(parser.parse(datestr, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exrulevals: + rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exdatevals: + rset.exdate(value) + if compatible and dtstart: + rset.rdate(dtstart) + return rset + else: + return self._parse_rfc_rrule(rrulevals[0], + dtstart=dtstart, + cache=cache, + ignoretz=ignoretz, + tzinfos=tzinfos) + + def __call__(self, s, **kwargs): + return self._parse_rfc(s, **kwargs) + + +rrulestr = _rrulestr() + +# vim:ts=4:sw=4:et diff --git a/.venv/Lib/site-packages/dateutil/tz/__init__.py b/.venv/Lib/site-packages/dateutil/tz/__init__.py new file mode 100644 index 00000000..af1352c4 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/tz/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +from .tz import * +from .tz import __doc__ + +__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", + "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz", + "enfold", "datetime_ambiguous", "datetime_exists", + "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"] + + +class DeprecatedTzFormatWarning(Warning): + """Warning raised when time zones are parsed from deprecated formats.""" diff --git a/.venv/Lib/site-packages/dateutil/tz/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/tz/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3006ffefd2031d079ba87548b8c4ebec9ab5f1a2 GIT binary patch literal 681 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 Ozqh#m*BpH_j{Y0O_D7xo literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/tz/__pycache__/_factories.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/tz/__pycache__/_factories.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa1ee6bff14c321b7231bdd8a88e2477c7243814 GIT binary patch literal 4567 zcmdT|O>7&-6`tKCsijDYj2Y`Ul4%KMMc4YbY*$fb88V!r4HOg#QiM>k*pN$^(u!1P zR<+w0p*vSyQI|kO@&<`Jw@KWkwLFk4IZ>I9w!o-dH|pl2ZWwLV+*RII zKI(x{Z{4V8LyY*oMsX3rbQ{T4Ew1T?IuAY1TQsgwEq*x}Goag|7+0yL#$(pr78NU< z(jYW`3RludREU$Pm?a4zE^NzDiMK>(IkM!25Opq)h-7+|w>KA(sU=-A(y5qGClXcU zhhJ$5$VUPyDMOShgHgFUA%?>q%#aV;2+0UZk`X@^eg?|iAp636#9_AAZ=)#56f@LR zOf#KqeNCgZ1tgdta7z%~9p3h#MT3n;) zWi4hb#?!II;cHsz+TxqZ_ZC^w(1zC3*owNOvBkJ*XzNB&A2BvZl!O{H(ln{D;k6Cw z1yP&F>rXdqAHxk(tPjXHTcp_4o0V?2J&}F4^}V^A9Jzn?K%RPdE-z1&fP);;9BKxC zrT2iK<}zd%T8(9^!?3M(ScjnX2NmXejW?IFKqwwG;-Kj5)PuxUXH3;~P^U)*4*E(3SA+p0+zPw`LAJC!h58e?0v#nCqR%_s(YLZqFC}$L_p; z>-__{mmUM=hzpIFQdc!aF3VG(<$xVQfG=pkekU%W4o%gkl^rbSdz9t{79c7i|V>w-~ku zQ2^@!vPHi12k+dxb#rgwz(0QP>?8m9{c}10_<=mm)dsOij{_fVN78`=J$|29O66|S zjiX3{@MCC^ZBhagOjtZP(_HbLFw>~`xCrWZY)BB}0XX^+1%^XTWPx8-qwp#KqGcJzz!rJZeX`I!nd_d+cb^9!^grnx{Kb#6 z(qp;1*gt^vi7%03B-cHX?;guaANsj-#L#E$g7(0E={W?{E~!~GBi4ZMLB)PFm=QAK za@9h%kQy{5#G6vefn3-EaCFsp?A9_uV?)VEaboXs(~)s(oq54pgwlqR!F{T}Qk%q6 z*fQ-JWRqszG)V+Z2#CfFWf=pkp}>v~TVnH78EG2U7#PL8H0OFy0Wp}xP;V$Jmm$Po zYrb;1tAQE1apBjZEs?*D;BjD|5^m>MAOmEKFyXo=kayv}*4Pc{U2%inx|g*L8z~6#X_#QA|>%w3c2o zC0$F=2zFbb3;BOF;^Y`=Ixz8=t~3W5Q(DnBxB!OU1&CU~R4X4g3kNGFo&;|86%Ysq z&+(naFO!cwgT-LSUVEWyDAzTV?;1HcHhOFB3mn=R&O)Po_u}1)gb zx0JsVr~7;{94Uk^`jdrE2lL?{WakRrzMQvjkLA1rWfutqcP0wKQ@P-& zygz(DScuH#BD0VDv&BHL5a`bZ`U`>6xxnd%&V#_|$ANRtJRtdL8wqq~{m=Zh_H%}A z{>Pb1gL9+OXQR%!sh0VDXJf9w*ArJ8J%KIEv{v3mT~Q?HJPg^k$v;G=bG+0Rbaq;d zIDIH_*w9@<;5m{w9FRH$o;sZHZh%*-LH{rF1|5LgMcnihR5T34>^yXvBiRA-NA0rk z{H;$7p_fe7@&Y}L`=D#r3*yP;rMZDW+pBu6CWZ?jjZFgij}k*qf1zhI*E5>$8P7_8 zkuB>t&kVm8(C~Gb4tq3~WkiXF(iGDhc(B_npKwgCz7=YVUWn<{H$aWIg6a4IZzxT( z#bHcuvZ{jV`2OJqkhuw$jlj)uyNc;eRyNBt{|%h+kR=jbhoKfWSwKKd^J=pzTCfDmF#o zFPfroAh_$j>)rd|J#RiRgeW{x0pWtLH|Oj9pTTesz_3sH%;%izXn}tOuF&tGdKxhI zbsR%-9)5M0J5g>6*qDpc5w9uZ2QmJ~z*8=VBGVH~>pFZ$!>hIOEOmoDhF80XP7W#J1 mmI+klc1f7nd9_TSDtmi`&YjINfvP;+3GMIylR(AO#=imIs+ms! literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/tz/__pycache__/tz.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/tz/__pycache__/tz.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2503a74d8423b8af2ca22514843e1ccdb3885912 GIT binary patch literal 65880 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/tz/__pycache__/win.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/tz/__pycache__/win.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db705fb94e5de625404dac3eb9667fd6a96631bd GIT binary patch literal 17232 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 H$oank cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + + +class _TzStrFactory(_TzFactory): + def __init__(cls, *args, **kwargs): + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + cls.__cache_lock = _thread.allocate_lock() + + def __call__(cls, s, posix_offset=False): + key = (s, posix_offset) + instance = cls.__instances.get(key, None) + + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(s, posix_offset)) + + # This lock may not be necessary in Python 3. See GH issue #901 + with cls.__cache_lock: + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + diff --git a/.venv/Lib/site-packages/dateutil/tz/tz.py b/.venv/Lib/site-packages/dateutil/tz/tz.py new file mode 100644 index 00000000..61759144 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/tz/tz.py @@ -0,0 +1,1849 @@ +# -*- coding: utf-8 -*- +""" +This module offers timezone implementations subclassing the abstract +:py:class:`datetime.tzinfo` type. There are classes to handle tzfile format +files (usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, +etc), TZ environment string (in all known formats), given ranges (with help +from relative deltas), local machine timezone, fixed offset timezone, and UTC +timezone. +""" +import datetime +import struct +import time +import sys +import os +import bisect +import weakref +from collections import OrderedDict + +import six +from six import string_types +from six.moves import _thread +from ._common import tzname_in_python2, _tzinfo +from ._common import tzrangebase, enfold +from ._common import _validate_fromutc_inputs + +from ._factories import _TzSingleton, _TzOffsetFactory +from ._factories import _TzStrFactory +try: + from .win import tzwin, tzwinlocal +except ImportError: + tzwin = tzwinlocal = None + +# For warning about rounding tzinfo +from warnings import warn + +ZERO = datetime.timedelta(0) +EPOCH = datetime.datetime(1970, 1, 1, 0, 0) +EPOCHORDINAL = EPOCH.toordinal() + + +@six.add_metaclass(_TzSingleton) +class tzutc(datetime.tzinfo): + """ + This is a tzinfo object that represents the UTC time zone. + + **Examples:** + + .. doctest:: + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now() + datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) + + >>> datetime.now(tzutc()) + datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) + + >>> datetime.now(tzutc()).tzname() + 'UTC' + + .. versionchanged:: 2.7.0 + ``tzutc()`` is now a singleton, so the result of ``tzutc()`` will + always return the same object. + + .. doctest:: + + >>> from dateutil.tz import tzutc, UTC + >>> tzutc() is tzutc() + True + >>> tzutc() is UTC + True + """ + def utcoffset(self, dt): + return ZERO + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return "UTC" + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Fast track version of fromutc() returns the original ``dt`` object for + any valid :py:class:`datetime.datetime` object. + """ + return dt + + def __eq__(self, other): + if not isinstance(other, (tzutc, tzoffset)): + return NotImplemented + + return (isinstance(other, tzutc) or + (isinstance(other, tzoffset) and other._offset == ZERO)) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +#: Convenience constant providing a :class:`tzutc()` instance +#: +#: .. versionadded:: 2.7.0 +UTC = tzutc() + + +@six.add_metaclass(_TzOffsetFactory) +class tzoffset(datetime.tzinfo): + """ + A simple class for representing a fixed offset from UTC. + + :param name: + The timezone name, to be returned when ``tzname()`` is called. + :param offset: + The time zone offset in seconds, or (since version 2.6.0, represented + as a :py:class:`datetime.timedelta` object). + """ + def __init__(self, name, offset): + self._name = name + + try: + # Allow a timedelta + offset = offset.total_seconds() + except (TypeError, AttributeError): + pass + + self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._name + + @_validate_fromutc_inputs + def fromutc(self, dt): + return dt + self._offset + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + def __eq__(self, other): + if not isinstance(other, tzoffset): + return NotImplemented + + return self._offset == other._offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s, %s)" % (self.__class__.__name__, + repr(self._name), + int(self._offset.total_seconds())) + + __reduce__ = object.__reduce__ + + +class tzlocal(_tzinfo): + """ + A :class:`tzinfo` subclass built around the ``time`` timezone functions. + """ + def __init__(self): + super(tzlocal, self).__init__() + + self._std_offset = datetime.timedelta(seconds=-time.timezone) + if time.daylight: + self._dst_offset = datetime.timedelta(seconds=-time.altzone) + else: + self._dst_offset = self._std_offset + + self._dst_saved = self._dst_offset - self._std_offset + self._hasdst = bool(self._dst_saved) + self._tznames = tuple(time.tzname) + + def utcoffset(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset - self._std_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._tznames[self._isdst(dt)] + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + naive_dst = self._naive_is_dst(dt) + return (not naive_dst and + (naive_dst != self._naive_is_dst(dt - self._dst_saved))) + + def _naive_is_dst(self, dt): + timestamp = _datetime_to_timestamp(dt) + return time.localtime(timestamp + time.timezone).tm_isdst + + def _isdst(self, dt, fold_naive=True): + # We can't use mktime here. It is unstable when deciding if + # the hour near to a change is DST or not. + # + # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, + # dt.minute, dt.second, dt.weekday(), 0, -1)) + # return time.localtime(timestamp).tm_isdst + # + # The code above yields the following result: + # + # >>> import tz, datetime + # >>> t = tz.tzlocal() + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # + # Here is a more stable implementation: + # + if not self._hasdst: + return False + + # Check for ambiguous times: + dstval = self._naive_is_dst(dt) + fold = getattr(dt, 'fold', None) + + if self.is_ambiguous(dt): + if fold is not None: + return not self._fold(dt) + else: + return True + + return dstval + + def __eq__(self, other): + if isinstance(other, tzlocal): + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset) + elif isinstance(other, tzutc): + return (not self._hasdst and + self._tznames[0] in {'UTC', 'GMT'} and + self._std_offset == ZERO) + elif isinstance(other, tzoffset): + return (not self._hasdst and + self._tznames[0] == other._name and + self._std_offset == other._offset) + else: + return NotImplemented + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +class _ttinfo(object): + __slots__ = ["offset", "delta", "isdst", "abbr", + "isstd", "isgmt", "dstoffset"] + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def __repr__(self): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + + def __eq__(self, other): + if not isinstance(other, _ttinfo): + return NotImplemented + + return (self.offset == other.offset and + self.delta == other.delta and + self.isdst == other.isdst and + self.abbr == other.abbr and + self.isstd == other.isstd and + self.isgmt == other.isgmt and + self.dstoffset == other.dstoffset) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __getstate__(self): + state = {} + for name in self.__slots__: + state[name] = getattr(self, name, None) + return state + + def __setstate__(self, state): + for name in self.__slots__: + if name in state: + setattr(self, name, state[name]) + + +class _tzfile(object): + """ + Lightweight class for holding the relevant transition and time zone + information read from binary tzfiles. + """ + attrs = ['trans_list', 'trans_list_utc', 'trans_idx', 'ttinfo_list', + 'ttinfo_std', 'ttinfo_dst', 'ttinfo_before', 'ttinfo_first'] + + def __init__(self, **kwargs): + for attr in self.attrs: + setattr(self, attr, kwargs.get(attr, None)) + + +class tzfile(_tzinfo): + """ + This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)`` + format timezone files to extract current and historical zone information. + + :param fileobj: + This can be an opened file stream or a file name that the time zone + information can be read from. + + :param filename: + This is an optional parameter specifying the source of the time zone + information in the event that ``fileobj`` is a file object. If omitted + and ``fileobj`` is a file stream, this parameter will be set either to + ``fileobj``'s ``name`` attribute or to ``repr(fileobj)``. + + See `Sources for Time Zone and Daylight Saving Time Data + `_ for more information. + Time zone files can be compiled from the `IANA Time Zone database files + `_ with the `zic time zone compiler + `_ + + .. note:: + + Only construct a ``tzfile`` directly if you have a specific timezone + file on disk that you want to read into a Python ``tzinfo`` object. + If you want to get a ``tzfile`` representing a specific IANA zone, + (e.g. ``'America/New_York'``), you should call + :func:`dateutil.tz.gettz` with the zone identifier. + + + **Examples:** + + Using the US Eastern time zone as an example, we can see that a ``tzfile`` + provides time zone information for the standard Daylight Saving offsets: + + .. testsetup:: tzfile + + from dateutil.tz import gettz + from datetime import datetime + + .. doctest:: tzfile + + >>> NYC = gettz('America/New_York') + >>> NYC + tzfile('/usr/share/zoneinfo/America/New_York') + + >>> print(datetime(2016, 1, 3, tzinfo=NYC)) # EST + 2016-01-03 00:00:00-05:00 + + >>> print(datetime(2016, 7, 7, tzinfo=NYC)) # EDT + 2016-07-07 00:00:00-04:00 + + + The ``tzfile`` structure contains a fully history of the time zone, + so historical dates will also have the right offsets. For example, before + the adoption of the UTC standards, New York used local solar mean time: + + .. doctest:: tzfile + + >>> print(datetime(1901, 4, 12, tzinfo=NYC)) # LMT + 1901-04-12 00:00:00-04:56 + + And during World War II, New York was on "Eastern War Time", which was a + state of permanent daylight saving time: + + .. doctest:: tzfile + + >>> print(datetime(1944, 2, 7, tzinfo=NYC)) # EWT + 1944-02-07 00:00:00-04:00 + + """ + + def __init__(self, fileobj, filename=None): + super(tzfile, self).__init__() + + file_opened_here = False + if isinstance(fileobj, string_types): + self._filename = fileobj + fileobj = open(fileobj, 'rb') + file_opened_here = True + elif filename is not None: + self._filename = filename + elif hasattr(fileobj, "name"): + self._filename = fileobj.name + else: + self._filename = repr(fileobj) + + if fileobj is not None: + if not file_opened_here: + fileobj = _nullcontext(fileobj) + + with fileobj as file_stream: + tzobj = self._read_tzfile(file_stream) + + self._set_tzdata(tzobj) + + def _set_tzdata(self, tzobj): + """ Set the time zone data of this object from a _tzfile object """ + # Copy the relevant attributes over as private attributes + for attr in _tzfile.attrs: + setattr(self, '_' + attr, getattr(tzobj, attr)) + + def _read_tzfile(self, fileobj): + out = _tzfile() + + # From tzfile(5): + # + # The time zone information files used by tzset(3) + # begin with the magic characters "TZif" to identify + # them as time zone information files, followed by + # sixteen bytes reserved for future use, followed by + # six four-byte values of type long, written in a + # ``standard'' byte order (the high-order byte + # of the value is written first). + if fileobj.read(4).decode() != "TZif": + raise ValueError("magic not found") + + fileobj.read(16) + + ( + # The number of UTC/local indicators stored in the file. + ttisgmtcnt, + + # The number of standard/wall indicators stored in the file. + ttisstdcnt, + + # The number of leap seconds for which data is + # stored in the file. + leapcnt, + + # The number of "transition times" for which data + # is stored in the file. + timecnt, + + # The number of "local time types" for which data + # is stored in the file (must not be zero). + typecnt, + + # The number of characters of "time zone + # abbreviation strings" stored in the file. + charcnt, + + ) = struct.unpack(">6l", fileobj.read(24)) + + # The above header is followed by tzh_timecnt four-byte + # values of type long, sorted in ascending order. + # These values are written in ``standard'' byte order. + # Each is used as a transition time (as returned by + # time(2)) at which the rules for computing local time + # change. + + if timecnt: + out.trans_list_utc = list(struct.unpack(">%dl" % timecnt, + fileobj.read(timecnt*4))) + else: + out.trans_list_utc = [] + + # Next come tzh_timecnt one-byte values of type unsigned + # char; each one tells which of the different types of + # ``local time'' types described in the file is associated + # with the same-indexed transition time. These values + # serve as indices into an array of ttinfo structures that + # appears next in the file. + + if timecnt: + out.trans_idx = struct.unpack(">%dB" % timecnt, + fileobj.read(timecnt)) + else: + out.trans_idx = [] + + # Each ttinfo structure is written as a four-byte value + # for tt_gmtoff of type long, in a standard byte + # order, followed by a one-byte value for tt_isdst + # and a one-byte value for tt_abbrind. In each + # structure, tt_gmtoff gives the number of + # seconds to be added to UTC, tt_isdst tells whether + # tm_isdst should be set by localtime(3), and + # tt_abbrind serves as an index into the array of + # time zone abbreviation characters that follow the + # ttinfo structure(s) in the file. + + ttinfo = [] + + for i in range(typecnt): + ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) + + abbr = fileobj.read(charcnt).decode() + + # Then there are tzh_leapcnt pairs of four-byte + # values, written in standard byte order; the + # first value of each pair gives the time (as + # returned by time(2)) at which a leap second + # occurs; the second gives the total number of + # leap seconds to be applied after the given time. + # The pairs of values are sorted in ascending order + # by time. + + # Not used, for now (but seek for correct file position) + if leapcnt: + fileobj.seek(leapcnt * 8, os.SEEK_CUR) + + # Then there are tzh_ttisstdcnt standard/wall + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as standard + # time or wall clock time, and are used when + # a time zone file is used in handling POSIX-style + # time zone environment variables. + + if ttisstdcnt: + isstd = struct.unpack(">%db" % ttisstdcnt, + fileobj.read(ttisstdcnt)) + + # Finally, there are tzh_ttisgmtcnt UTC/local + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as UTC or + # local time, and are used when a time zone file + # is used in handling POSIX-style time zone envi- + # ronment variables. + + if ttisgmtcnt: + isgmt = struct.unpack(">%db" % ttisgmtcnt, + fileobj.read(ttisgmtcnt)) + + # Build ttinfo list + out.ttinfo_list = [] + for i in range(typecnt): + gmtoff, isdst, abbrind = ttinfo[i] + gmtoff = _get_supported_offset(gmtoff) + tti = _ttinfo() + tti.offset = gmtoff + tti.dstoffset = datetime.timedelta(0) + tti.delta = datetime.timedelta(seconds=gmtoff) + tti.isdst = isdst + tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] + tti.isstd = (ttisstdcnt > i and isstd[i] != 0) + tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) + out.ttinfo_list.append(tti) + + # Replace ttinfo indexes for ttinfo objects. + out.trans_idx = [out.ttinfo_list[idx] for idx in out.trans_idx] + + # Set standard, dst, and before ttinfos. before will be + # used when a given time is before any transitions, + # and will be set to the first non-dst ttinfo, or to + # the first dst, if all of them are dst. + out.ttinfo_std = None + out.ttinfo_dst = None + out.ttinfo_before = None + if out.ttinfo_list: + if not out.trans_list_utc: + out.ttinfo_std = out.ttinfo_first = out.ttinfo_list[0] + else: + for i in range(timecnt-1, -1, -1): + tti = out.trans_idx[i] + if not out.ttinfo_std and not tti.isdst: + out.ttinfo_std = tti + elif not out.ttinfo_dst and tti.isdst: + out.ttinfo_dst = tti + + if out.ttinfo_std and out.ttinfo_dst: + break + else: + if out.ttinfo_dst and not out.ttinfo_std: + out.ttinfo_std = out.ttinfo_dst + + for tti in out.ttinfo_list: + if not tti.isdst: + out.ttinfo_before = tti + break + else: + out.ttinfo_before = out.ttinfo_list[0] + + # Now fix transition times to become relative to wall time. + # + # I'm not sure about this. In my tests, the tz source file + # is setup to wall time, and in the binary file isstd and + # isgmt are off, so it should be in wall time. OTOH, it's + # always in gmt time. Let me know if you have comments + # about this. + lastdst = None + lastoffset = None + lastdstoffset = None + lastbaseoffset = None + out.trans_list = [] + + for i, tti in enumerate(out.trans_idx): + offset = tti.offset + dstoffset = 0 + + if lastdst is not None: + if tti.isdst: + if not lastdst: + dstoffset = offset - lastoffset + + if not dstoffset and lastdstoffset: + dstoffset = lastdstoffset + + tti.dstoffset = datetime.timedelta(seconds=dstoffset) + lastdstoffset = dstoffset + + # If a time zone changes its base offset during a DST transition, + # then you need to adjust by the previous base offset to get the + # transition time in local time. Otherwise you use the current + # base offset. Ideally, I would have some mathematical proof of + # why this is true, but I haven't really thought about it enough. + baseoffset = offset - dstoffset + adjustment = baseoffset + if (lastbaseoffset is not None and baseoffset != lastbaseoffset + and tti.isdst != lastdst): + # The base DST has changed + adjustment = lastbaseoffset + + lastdst = tti.isdst + lastoffset = offset + lastbaseoffset = baseoffset + + out.trans_list.append(out.trans_list_utc[i] + adjustment) + + out.trans_idx = tuple(out.trans_idx) + out.trans_list = tuple(out.trans_list) + out.trans_list_utc = tuple(out.trans_list_utc) + + return out + + def _find_last_transition(self, dt, in_utc=False): + # If there's no list, there are no transitions to find + if not self._trans_list: + return None + + timestamp = _datetime_to_timestamp(dt) + + # Find where the timestamp fits in the transition list - if the + # timestamp is a transition time, it's part of the "after" period. + trans_list = self._trans_list_utc if in_utc else self._trans_list + idx = bisect.bisect_right(trans_list, timestamp) + + # We want to know when the previous transition was, so subtract off 1 + return idx - 1 + + def _get_ttinfo(self, idx): + # For no list or after the last transition, default to _ttinfo_std + if idx is None or (idx + 1) >= len(self._trans_list): + return self._ttinfo_std + + # If there is a list and the time is before it, return _ttinfo_before + if idx < 0: + return self._ttinfo_before + + return self._trans_idx[idx] + + def _find_ttinfo(self, dt): + idx = self._resolve_ambiguous_time(dt) + + return self._get_ttinfo(idx) + + def fromutc(self, dt): + """ + The ``tzfile`` implementation of :py:func:`datetime.tzinfo.fromutc`. + + :param dt: + A :py:class:`datetime.datetime` object. + + :raises TypeError: + Raised if ``dt`` is not a :py:class:`datetime.datetime` object. + + :raises ValueError: + Raised if this is called with a ``dt`` which does not have this + ``tzinfo`` attached. + + :return: + Returns a :py:class:`datetime.datetime` object representing the + wall time in ``self``'s time zone. + """ + # These isinstance checks are in datetime.tzinfo, so we'll preserve + # them, even if we don't care about duck typing. + if not isinstance(dt, datetime.datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # First treat UTC as wall time and get the transition we're in. + idx = self._find_last_transition(dt, in_utc=True) + tti = self._get_ttinfo(idx) + + dt_out = dt + datetime.timedelta(seconds=tti.offset) + + fold = self.is_ambiguous(dt_out, idx=idx) + + return enfold(dt_out, fold=int(fold)) + + def is_ambiguous(self, dt, idx=None): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if idx is None: + idx = self._find_last_transition(dt) + + # Calculate the difference in offsets from current to previous + timestamp = _datetime_to_timestamp(dt) + tti = self._get_ttinfo(idx) + + if idx is None or idx <= 0: + return False + + od = self._get_ttinfo(idx - 1).offset - tti.offset + tt = self._trans_list[idx] # Transition time + + return timestamp < tt + od + + def _resolve_ambiguous_time(self, dt): + idx = self._find_last_transition(dt) + + # If we have no transitions, return the index + _fold = self._fold(dt) + if idx is None or idx == 0: + return idx + + # If it's ambiguous and we're in a fold, shift to a different index. + idx_offset = int(not _fold and self.is_ambiguous(dt, idx)) + + return idx - idx_offset + + def utcoffset(self, dt): + if dt is None: + return None + + if not self._ttinfo_std: + return ZERO + + return self._find_ttinfo(dt).delta + + def dst(self, dt): + if dt is None: + return None + + if not self._ttinfo_dst: + return ZERO + + tti = self._find_ttinfo(dt) + + if not tti.isdst: + return ZERO + + # The documentation says that utcoffset()-dst() must + # be constant for every dt. + return tti.dstoffset + + @tzname_in_python2 + def tzname(self, dt): + if not self._ttinfo_std or dt is None: + return None + return self._find_ttinfo(dt).abbr + + def __eq__(self, other): + if not isinstance(other, tzfile): + return NotImplemented + return (self._trans_list == other._trans_list and + self._trans_idx == other._trans_idx and + self._ttinfo_list == other._ttinfo_list) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) + + def __reduce__(self): + return self.__reduce_ex__(None) + + def __reduce_ex__(self, protocol): + return (self.__class__, (None, self._filename), self.__dict__) + + +class tzrange(tzrangebase): + """ + The ``tzrange`` object is a time zone specified by a set of offsets and + abbreviations, equivalent to the way the ``TZ`` variable can be specified + in POSIX-like systems, but using Python delta objects to specify DST + start, end and offsets. + + :param stdabbr: + The abbreviation for standard time (e.g. ``'EST'``). + + :param stdoffset: + An integer or :class:`datetime.timedelta` object or equivalent + specifying the base offset from UTC. + + If unspecified, +00:00 is used. + + :param dstabbr: + The abbreviation for DST / "Summer" time (e.g. ``'EDT'``). + + If specified, with no other DST information, DST is assumed to occur + and the default behavior or ``dstoffset``, ``start`` and ``end`` is + used. If unspecified and no other DST information is specified, it + is assumed that this zone has no DST. + + If this is unspecified and other DST information is *is* specified, + DST occurs in the zone but the time zone abbreviation is left + unchanged. + + :param dstoffset: + A an integer or :class:`datetime.timedelta` object or equivalent + specifying the UTC offset during DST. If unspecified and any other DST + information is specified, it is assumed to be the STD offset +1 hour. + + :param start: + A :class:`relativedelta.relativedelta` object or equivalent specifying + the time and time of year that daylight savings time starts. To + specify, for example, that DST starts at 2AM on the 2nd Sunday in + March, pass: + + ``relativedelta(hours=2, month=3, day=1, weekday=SU(+2))`` + + If unspecified and any other DST information is specified, the default + value is 2 AM on the first Sunday in April. + + :param end: + A :class:`relativedelta.relativedelta` object or equivalent + representing the time and time of year that daylight savings time + ends, with the same specification method as in ``start``. One note is + that this should point to the first time in the *standard* zone, so if + a transition occurs at 2AM in the DST zone and the clocks are set back + 1 hour to 1AM, set the ``hours`` parameter to +1. + + + **Examples:** + + .. testsetup:: tzrange + + from dateutil.tz import tzrange, tzstr + + .. doctest:: tzrange + + >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") + True + + >>> from dateutil.relativedelta import * + >>> range1 = tzrange("EST", -18000, "EDT") + >>> range2 = tzrange("EST", -18000, "EDT", -14400, + ... relativedelta(hours=+2, month=4, day=1, + ... weekday=SU(+1)), + ... relativedelta(hours=+1, month=10, day=31, + ... weekday=SU(-1))) + >>> tzstr('EST5EDT') == range1 == range2 + True + + """ + def __init__(self, stdabbr, stdoffset=None, + dstabbr=None, dstoffset=None, + start=None, end=None): + + global relativedelta + from dateutil import relativedelta + + self._std_abbr = stdabbr + self._dst_abbr = dstabbr + + try: + stdoffset = stdoffset.total_seconds() + except (TypeError, AttributeError): + pass + + try: + dstoffset = dstoffset.total_seconds() + except (TypeError, AttributeError): + pass + + if stdoffset is not None: + self._std_offset = datetime.timedelta(seconds=stdoffset) + else: + self._std_offset = ZERO + + if dstoffset is not None: + self._dst_offset = datetime.timedelta(seconds=dstoffset) + elif dstabbr and stdoffset is not None: + self._dst_offset = self._std_offset + datetime.timedelta(hours=+1) + else: + self._dst_offset = ZERO + + if dstabbr and start is None: + self._start_delta = relativedelta.relativedelta( + hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) + else: + self._start_delta = start + + if dstabbr and end is None: + self._end_delta = relativedelta.relativedelta( + hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) + else: + self._end_delta = end + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = bool(self._start_delta) + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + if not self.hasdst: + return None + + base_year = datetime.datetime(year, 1, 1) + + start = base_year + self._start_delta + end = base_year + self._end_delta + + return (start, end) + + def __eq__(self, other): + if not isinstance(other, tzrange): + return NotImplemented + + return (self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr and + self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._start_delta == other._start_delta and + self._end_delta == other._end_delta) + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +@six.add_metaclass(_TzStrFactory) +class tzstr(tzrange): + """ + ``tzstr`` objects are time zone objects specified by a time-zone string as + it would be passed to a ``TZ`` variable on POSIX-style systems (see + the `GNU C Library: TZ Variable`_ for more details). + + There is one notable exception, which is that POSIX-style time zones use an + inverted offset format, so normally ``GMT+3`` would be parsed as an offset + 3 hours *behind* GMT. The ``tzstr`` time zone object will parse this as an + offset 3 hours *ahead* of GMT. If you would like to maintain the POSIX + behavior, pass a ``True`` value to ``posix_offset``. + + The :class:`tzrange` object provides the same functionality, but is + specified using :class:`relativedelta.relativedelta` objects. rather than + strings. + + :param s: + A time zone string in ``TZ`` variable format. This can be a + :class:`bytes` (2.x: :class:`str`), :class:`str` (2.x: + :class:`unicode`) or a stream emitting unicode characters + (e.g. :class:`StringIO`). + + :param posix_offset: + Optional. If set to ``True``, interpret strings such as ``GMT+3`` or + ``UTC+3`` as being 3 hours *behind* UTC rather than ahead, per the + POSIX standard. + + .. caution:: + + Prior to version 2.7.0, this function also supported time zones + in the format: + + * ``EST5EDT,4,0,6,7200,10,0,26,7200,3600`` + * ``EST5EDT,4,1,0,7200,10,-1,0,7200,3600`` + + This format is non-standard and has been deprecated; this function + will raise a :class:`DeprecatedTZFormatWarning` until + support is removed in a future version. + + .. _`GNU C Library: TZ Variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + """ + def __init__(self, s, posix_offset=False): + global parser + from dateutil.parser import _parser as parser + + self._s = s + + res = parser._parsetz(s) + if res is None or res.any_unused_tokens: + raise ValueError("unknown string format") + + # Here we break the compatibility with the TZ variable handling. + # GMT-3 actually *means* the timezone -3. + if res.stdabbr in ("GMT", "UTC") and not posix_offset: + res.stdoffset *= -1 + + # We must initialize it first, since _delta() needs + # _std_offset and _dst_offset set. Use False in start/end + # to avoid building it two times. + tzrange.__init__(self, res.stdabbr, res.stdoffset, + res.dstabbr, res.dstoffset, + start=False, end=False) + + if not res.dstabbr: + self._start_delta = None + self._end_delta = None + else: + self._start_delta = self._delta(res.start) + if self._start_delta: + self._end_delta = self._delta(res.end, isend=1) + + self.hasdst = bool(self._start_delta) + + def _delta(self, x, isend=0): + from dateutil import relativedelta + kwargs = {} + if x.month is not None: + kwargs["month"] = x.month + if x.weekday is not None: + kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) + if x.week > 0: + kwargs["day"] = 1 + else: + kwargs["day"] = 31 + elif x.day: + kwargs["day"] = x.day + elif x.yday is not None: + kwargs["yearday"] = x.yday + elif x.jyday is not None: + kwargs["nlyearday"] = x.jyday + if not kwargs: + # Default is to start on first sunday of april, and end + # on last sunday of october. + if not isend: + kwargs["month"] = 4 + kwargs["day"] = 1 + kwargs["weekday"] = relativedelta.SU(+1) + else: + kwargs["month"] = 10 + kwargs["day"] = 31 + kwargs["weekday"] = relativedelta.SU(-1) + if x.time is not None: + kwargs["seconds"] = x.time + else: + # Default is 2AM. + kwargs["seconds"] = 7200 + if isend: + # Convert to standard time, to follow the documented way + # of working with the extra hour. See the documentation + # of the tzinfo class. + delta = self._dst_offset - self._std_offset + kwargs["seconds"] -= delta.seconds + delta.days * 86400 + return relativedelta.relativedelta(**kwargs) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +class _tzicalvtzcomp(object): + def __init__(self, tzoffsetfrom, tzoffsetto, isdst, + tzname=None, rrule=None): + self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) + self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) + self.tzoffsetdiff = self.tzoffsetto - self.tzoffsetfrom + self.isdst = isdst + self.tzname = tzname + self.rrule = rrule + + +class _tzicalvtz(_tzinfo): + def __init__(self, tzid, comps=[]): + super(_tzicalvtz, self).__init__() + + self._tzid = tzid + self._comps = comps + self._cachedate = [] + self._cachecomp = [] + self._cache_lock = _thread.allocate_lock() + + def _find_comp(self, dt): + if len(self._comps) == 1: + return self._comps[0] + + dt = dt.replace(tzinfo=None) + + try: + with self._cache_lock: + return self._cachecomp[self._cachedate.index( + (dt, self._fold(dt)))] + except ValueError: + pass + + lastcompdt = None + lastcomp = None + + for comp in self._comps: + compdt = self._find_compdt(comp, dt) + + if compdt and (not lastcompdt or lastcompdt < compdt): + lastcompdt = compdt + lastcomp = comp + + if not lastcomp: + # RFC says nothing about what to do when a given + # time is before the first onset date. We'll look for the + # first standard component, or the first component, if + # none is found. + for comp in self._comps: + if not comp.isdst: + lastcomp = comp + break + else: + lastcomp = comp[0] + + with self._cache_lock: + self._cachedate.insert(0, (dt, self._fold(dt))) + self._cachecomp.insert(0, lastcomp) + + if len(self._cachedate) > 10: + self._cachedate.pop() + self._cachecomp.pop() + + return lastcomp + + def _find_compdt(self, comp, dt): + if comp.tzoffsetdiff < ZERO and self._fold(dt): + dt -= comp.tzoffsetdiff + + compdt = comp.rrule.before(dt, inc=True) + + return compdt + + def utcoffset(self, dt): + if dt is None: + return None + + return self._find_comp(dt).tzoffsetto + + def dst(self, dt): + comp = self._find_comp(dt) + if comp.isdst: + return comp.tzoffsetdiff + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._find_comp(dt).tzname + + def __repr__(self): + return "" % repr(self._tzid) + + __reduce__ = object.__reduce__ + + +class tzical(object): + """ + This object is designed to parse an iCalendar-style ``VTIMEZONE`` structure + as set out in `RFC 5545`_ Section 4.6.5 into one or more `tzinfo` objects. + + :param `fileobj`: + A file or stream in iCalendar format, which should be UTF-8 encoded + with CRLF endings. + + .. _`RFC 5545`: https://tools.ietf.org/html/rfc5545 + """ + def __init__(self, fileobj): + global rrule + from dateutil import rrule + + if isinstance(fileobj, string_types): + self._s = fileobj + # ical should be encoded in UTF-8 with CRLF + fileobj = open(fileobj, 'r') + else: + self._s = getattr(fileobj, 'name', repr(fileobj)) + fileobj = _nullcontext(fileobj) + + self._vtz = {} + + with fileobj as fobj: + self._parse_rfc(fobj.read()) + + def keys(self): + """ + Retrieves the available time zones as a list. + """ + return list(self._vtz.keys()) + + def get(self, tzid=None): + """ + Retrieve a :py:class:`datetime.tzinfo` object by its ``tzid``. + + :param tzid: + If there is exactly one time zone available, omitting ``tzid`` + or passing :py:const:`None` value returns it. Otherwise a valid + key (which can be retrieved from :func:`keys`) is required. + + :raises ValueError: + Raised if ``tzid`` is not specified but there are either more + or fewer than 1 zone defined. + + :returns: + Returns either a :py:class:`datetime.tzinfo` object representing + the relevant time zone or :py:const:`None` if the ``tzid`` was + not found. + """ + if tzid is None: + if len(self._vtz) == 0: + raise ValueError("no timezones defined") + elif len(self._vtz) > 1: + raise ValueError("more than one timezone available") + tzid = next(iter(self._vtz)) + + return self._vtz.get(tzid) + + def _parse_offset(self, s): + s = s.strip() + if not s: + raise ValueError("empty offset") + if s[0] in ('+', '-'): + signal = (-1, +1)[s[0] == '+'] + s = s[1:] + else: + signal = +1 + if len(s) == 4: + return (int(s[:2]) * 3600 + int(s[2:]) * 60) * signal + elif len(s) == 6: + return (int(s[:2]) * 3600 + int(s[2:4]) * 60 + int(s[4:])) * signal + else: + raise ValueError("invalid offset: " + s) + + def _parse_rfc(self, s): + lines = s.splitlines() + if not lines: + raise ValueError("empty string") + + # Unfold + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + + tzid = None + comps = [] + invtz = False + comptype = None + for line in lines: + if not line: + continue + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0].upper() + parms = parms[1:] + if invtz: + if name == "BEGIN": + if value in ("STANDARD", "DAYLIGHT"): + # Process component + pass + else: + raise ValueError("unknown component: "+value) + comptype = value + founddtstart = False + tzoffsetfrom = None + tzoffsetto = None + rrulelines = [] + tzname = None + elif name == "END": + if value == "VTIMEZONE": + if comptype: + raise ValueError("component not closed: "+comptype) + if not tzid: + raise ValueError("mandatory TZID not found") + if not comps: + raise ValueError( + "at least one component is needed") + # Process vtimezone + self._vtz[tzid] = _tzicalvtz(tzid, comps) + invtz = False + elif value == comptype: + if not founddtstart: + raise ValueError("mandatory DTSTART not found") + if tzoffsetfrom is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + if tzoffsetto is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + # Process component + rr = None + if rrulelines: + rr = rrule.rrulestr("\n".join(rrulelines), + compatible=True, + ignoretz=True, + cache=True) + comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, + (comptype == "DAYLIGHT"), + tzname, rr) + comps.append(comp) + comptype = None + else: + raise ValueError("invalid component end: "+value) + elif comptype: + if name == "DTSTART": + # DTSTART in VTIMEZONE takes a subset of valid RRULE + # values under RFC 5545. + for parm in parms: + if parm != 'VALUE=DATE-TIME': + msg = ('Unsupported DTSTART param in ' + + 'VTIMEZONE: ' + parm) + raise ValueError(msg) + rrulelines.append(line) + founddtstart = True + elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): + rrulelines.append(line) + elif name == "TZOFFSETFROM": + if parms: + raise ValueError( + "unsupported %s parm: %s " % (name, parms[0])) + tzoffsetfrom = self._parse_offset(value) + elif name == "TZOFFSETTO": + if parms: + raise ValueError( + "unsupported TZOFFSETTO parm: "+parms[0]) + tzoffsetto = self._parse_offset(value) + elif name == "TZNAME": + if parms: + raise ValueError( + "unsupported TZNAME parm: "+parms[0]) + tzname = value + elif name == "COMMENT": + pass + else: + raise ValueError("unsupported property: "+name) + else: + if name == "TZID": + if parms: + raise ValueError( + "unsupported TZID parm: "+parms[0]) + tzid = value + elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): + pass + else: + raise ValueError("unsupported property: "+name) + elif name == "BEGIN" and value == "VTIMEZONE": + tzid = None + comps = [] + invtz = True + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +if sys.platform != "win32": + TZFILES = ["/etc/localtime", "localtime"] + TZPATHS = ["/usr/share/zoneinfo", + "/usr/lib/zoneinfo", + "/usr/share/lib/zoneinfo", + "/etc/zoneinfo"] +else: + TZFILES = [] + TZPATHS = [] + + +def __get_gettz(): + tzlocal_classes = (tzlocal,) + if tzwinlocal is not None: + tzlocal_classes += (tzwinlocal,) + + class GettzFunc(object): + """ + Retrieve a time zone object from a string representation + + This function is intended to retrieve the :py:class:`tzinfo` subclass + that best represents the time zone that would be used if a POSIX + `TZ variable`_ were set to the same value. + + If no argument or an empty string is passed to ``gettz``, local time + is returned: + + .. code-block:: python3 + + >>> gettz() + tzfile('/etc/localtime') + + This function is also the preferred way to map IANA tz database keys + to :class:`tzfile` objects: + + .. code-block:: python3 + + >>> gettz('Pacific/Kiritimati') + tzfile('/usr/share/zoneinfo/Pacific/Kiritimati') + + On Windows, the standard is extended to include the Windows-specific + zone names provided by the operating system: + + .. code-block:: python3 + + >>> gettz('Egypt Standard Time') + tzwin('Egypt Standard Time') + + Passing a GNU ``TZ`` style string time zone specification returns a + :class:`tzstr` object: + + .. code-block:: python3 + + >>> gettz('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + tzstr('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + + :param name: + A time zone name (IANA, or, on Windows, Windows keys), location of + a ``tzfile(5)`` zoneinfo file or ``TZ`` variable style time zone + specifier. An empty string, no argument or ``None`` is interpreted + as local time. + + :return: + Returns an instance of one of ``dateutil``'s :py:class:`tzinfo` + subclasses. + + .. versionchanged:: 2.7.0 + + After version 2.7.0, any two calls to ``gettz`` using the same + input strings will return the same object: + + .. code-block:: python3 + + >>> tz.gettz('America/Chicago') is tz.gettz('America/Chicago') + True + + In addition to improving performance, this ensures that + `"same zone" semantics`_ are used for datetimes in the same zone. + + + .. _`TZ variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + + .. _`"same zone" semantics`: + https://blog.ganssle.io/articles/2018/02/aware-datetime-arithmetic.html + """ + def __init__(self): + + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache_size = 8 + self.__strong_cache = OrderedDict() + self._cache_lock = _thread.allocate_lock() + + def __call__(self, name=None): + with self._cache_lock: + rv = self.__instances.get(name, None) + + if rv is None: + rv = self.nocache(name=name) + if not (name is None + or isinstance(rv, tzlocal_classes) + or rv is None): + # tzlocal is slightly more complicated than the other + # time zone providers because it depends on environment + # at construction time, so don't cache that. + # + # We also cannot store weak references to None, so we + # will also not store that. + self.__instances[name] = rv + else: + # No need for strong caching, return immediately + return rv + + self.__strong_cache[name] = self.__strong_cache.pop(name, rv) + + if len(self.__strong_cache) > self.__strong_cache_size: + self.__strong_cache.popitem(last=False) + + return rv + + def set_cache_size(self, size): + with self._cache_lock: + self.__strong_cache_size = size + while len(self.__strong_cache) > size: + self.__strong_cache.popitem(last=False) + + def cache_clear(self): + with self._cache_lock: + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache.clear() + + @staticmethod + def nocache(name=None): + """A non-cached version of gettz""" + tz = None + if not name: + try: + name = os.environ["TZ"] + except KeyError: + pass + if name is None or name in ("", ":"): + for filepath in TZFILES: + if not os.path.isabs(filepath): + filename = filepath + for path in TZPATHS: + filepath = os.path.join(path, filename) + if os.path.isfile(filepath): + break + else: + continue + if os.path.isfile(filepath): + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = tzlocal() + else: + try: + if name.startswith(":"): + name = name[1:] + except TypeError as e: + if isinstance(name, bytes): + new_msg = "gettz argument should be str, not bytes" + six.raise_from(TypeError(new_msg), e) + else: + raise + if os.path.isabs(name): + if os.path.isfile(name): + tz = tzfile(name) + else: + tz = None + else: + for path in TZPATHS: + filepath = os.path.join(path, name) + if not os.path.isfile(filepath): + filepath = filepath.replace(' ', '_') + if not os.path.isfile(filepath): + continue + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = None + if tzwin is not None: + try: + tz = tzwin(name) + except (WindowsError, UnicodeEncodeError): + # UnicodeEncodeError is for Python 2.7 compat + tz = None + + if not tz: + from dateutil.zoneinfo import get_zonefile_instance + tz = get_zonefile_instance().get(name) + + if not tz: + for c in name: + # name is not a tzstr unless it has at least + # one offset. For short values of "name", an + # explicit for loop seems to be the fastest way + # To determine if a string contains a digit + if c in "0123456789": + try: + tz = tzstr(name) + except ValueError: + pass + break + else: + if name in ("GMT", "UTC"): + tz = UTC + elif name in time.tzname: + tz = tzlocal() + return tz + + return GettzFunc() + + +gettz = __get_gettz() +del __get_gettz + + +def datetime_exists(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + would fall in a gap. + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" exists in + ``tz``. + + .. versionadded:: 2.7.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + tz = dt.tzinfo + + dt = dt.replace(tzinfo=None) + + # This is essentially a test of whether or not the datetime can survive + # a round trip to UTC. + dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz) + dt_rt = dt_rt.replace(tzinfo=None) + + return dt == dt_rt + + +def datetime_ambiguous(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + is ambiguous (i.e if there are two times differentiated only by their DST + status). + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" is ambiguous in + ``tz``. + + .. versionadded:: 2.6.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + + tz = dt.tzinfo + + # If a time zone defines its own "is_ambiguous" function, we'll use that. + is_ambiguous_fn = getattr(tz, 'is_ambiguous', None) + if is_ambiguous_fn is not None: + try: + return tz.is_ambiguous(dt) + except Exception: + pass + + # If it doesn't come out and tell us it's ambiguous, we'll just check if + # the fold attribute has any effect on this particular date and time. + dt = dt.replace(tzinfo=tz) + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dst = wall_0.dst() == wall_1.dst() + + return not (same_offset and same_dst) + + +def resolve_imaginary(dt): + """ + Given a datetime that may be imaginary, return an existing datetime. + + This function assumes that an imaginary datetime represents what the + wall time would be in a zone had the offset transition not occurred, so + it will always fall forward by the transition's change in offset. + + .. doctest:: + + >>> from dateutil import tz + >>> from datetime import datetime + >>> NYC = tz.gettz('America/New_York') + >>> print(tz.resolve_imaginary(datetime(2017, 3, 12, 2, 30, tzinfo=NYC))) + 2017-03-12 03:30:00-04:00 + + >>> KIR = tz.gettz('Pacific/Kiritimati') + >>> print(tz.resolve_imaginary(datetime(1995, 1, 1, 12, 30, tzinfo=KIR))) + 1995-01-02 12:30:00+14:00 + + As a note, :func:`datetime.astimezone` is guaranteed to produce a valid, + existing datetime, so a round-trip to and from UTC is sufficient to get + an extant datetime, however, this generally "falls back" to an earlier time + rather than falling forward to the STD side (though no guarantees are made + about this behavior). + + :param dt: + A :class:`datetime.datetime` which may or may not exist. + + :return: + Returns an existing :class:`datetime.datetime`. If ``dt`` was not + imaginary, the datetime returned is guaranteed to be the same object + passed to the function. + + .. versionadded:: 2.7.0 + """ + if dt.tzinfo is not None and not datetime_exists(dt): + + curr_offset = (dt + datetime.timedelta(hours=24)).utcoffset() + old_offset = (dt - datetime.timedelta(hours=24)).utcoffset() + + dt += curr_offset - old_offset + + return dt + + +def _datetime_to_timestamp(dt): + """ + Convert a :class:`datetime.datetime` object to an epoch timestamp in + seconds since January 1, 1970, ignoring the time zone. + """ + return (dt.replace(tzinfo=None) - EPOCH).total_seconds() + + +if sys.version_info >= (3, 6): + def _get_supported_offset(second_offset): + return second_offset +else: + def _get_supported_offset(second_offset): + # For python pre-3.6, round to full-minutes if that's not the case. + # Python's datetime doesn't accept sub-minute timezones. Check + # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 + # for some information. + old_offset = second_offset + calculated_offset = 60 * ((second_offset + 30) // 60) + return calculated_offset + + +try: + # Python 3.7 feature + from contextlib import nullcontext as _nullcontext +except ImportError: + class _nullcontext(object): + """ + Class for wrapping contexts so that they are passed through in a + with statement. + """ + def __init__(self, context): + self.context = context + + def __enter__(self): + return self.context + + def __exit__(*args, **kwargs): + pass + +# vim:ts=4:sw=4:et diff --git a/.venv/Lib/site-packages/dateutil/tz/win.py b/.venv/Lib/site-packages/dateutil/tz/win.py new file mode 100644 index 00000000..cde07ba7 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/tz/win.py @@ -0,0 +1,370 @@ +# -*- coding: utf-8 -*- +""" +This module provides an interface to the native time zone data on Windows, +including :py:class:`datetime.tzinfo` implementations. + +Attempting to import this module on a non-Windows platform will raise an +:py:obj:`ImportError`. +""" +# This code was originally contributed by Jeffrey Harris. +import datetime +import struct + +from six.moves import winreg +from six import text_type + +try: + import ctypes + from ctypes import wintypes +except ValueError: + # ValueError is raised on non-Windows systems for some horrible reason. + raise ImportError("Running tzwin on non-Windows system") + +from ._common import tzrangebase + +__all__ = ["tzwin", "tzwinlocal", "tzres"] + +ONEWEEK = datetime.timedelta(7) + +TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" +TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" +TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" + + +def _settzkeyname(): + handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + winreg.OpenKey(handle, TZKEYNAMENT).Close() + TZKEYNAME = TZKEYNAMENT + except WindowsError: + TZKEYNAME = TZKEYNAME9X + handle.Close() + return TZKEYNAME + + +TZKEYNAME = _settzkeyname() + + +class tzres(object): + """ + Class for accessing ``tzres.dll``, which contains timezone name related + resources. + + .. versionadded:: 2.5.0 + """ + p_wchar = ctypes.POINTER(wintypes.WCHAR) # Pointer to a wide char + + def __init__(self, tzres_loc='tzres.dll'): + # Load the user32 DLL so we can load strings from tzres + user32 = ctypes.WinDLL('user32') + + # Specify the LoadStringW function + user32.LoadStringW.argtypes = (wintypes.HINSTANCE, + wintypes.UINT, + wintypes.LPWSTR, + ctypes.c_int) + + self.LoadStringW = user32.LoadStringW + self._tzres = ctypes.WinDLL(tzres_loc) + self.tzres_loc = tzres_loc + + def load_name(self, offset): + """ + Load a timezone name from a DLL offset (integer). + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.load_name(112)) + 'Eastern Standard Time' + + :param offset: + A positive integer value referring to a string from the tzres dll. + + .. note:: + + Offsets found in the registry are generally of the form + ``@tzres.dll,-114``. The offset in this case is 114, not -114. + + """ + resource = self.p_wchar() + lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR) + nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0) + return resource[:nchar] + + def name_from_string(self, tzname_str): + """ + Parse strings as returned from the Windows registry into the time zone + name as defined in the registry. + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.name_from_string('@tzres.dll,-251')) + 'Dateline Daylight Time' + >>> print(tzr.name_from_string('Eastern Standard Time')) + 'Eastern Standard Time' + + :param tzname_str: + A timezone name string as returned from a Windows registry key. + + :return: + Returns the localized timezone string from tzres.dll if the string + is of the form `@tzres.dll,-offset`, else returns the input string. + """ + if not tzname_str.startswith('@'): + return tzname_str + + name_splt = tzname_str.split(',-') + try: + offset = int(name_splt[1]) + except: + raise ValueError("Malformed timezone string.") + + return self.load_name(offset) + + +class tzwinbase(tzrangebase): + """tzinfo class based on win32's timezones available in the registry.""" + def __init__(self): + raise NotImplementedError('tzwinbase is an abstract base class') + + def __eq__(self, other): + # Compare on all relevant dimensions, including name. + if not isinstance(other, tzwinbase): + return NotImplemented + + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._stddayofweek == other._stddayofweek and + self._dstdayofweek == other._dstdayofweek and + self._stdweeknumber == other._stdweeknumber and + self._dstweeknumber == other._dstweeknumber and + self._stdhour == other._stdhour and + self._dsthour == other._dsthour and + self._stdminute == other._stdminute and + self._dstminute == other._dstminute and + self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr) + + @staticmethod + def list(): + """Return a list of all time zones known to the system.""" + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZKEYNAME) as tzkey: + result = [winreg.EnumKey(tzkey, i) + for i in range(winreg.QueryInfoKey(tzkey)[0])] + return result + + def display(self): + """ + Return the display name of the time zone. + """ + return self._display + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + + if not self.hasdst: + return None + + dston = picknthweekday(year, self._dstmonth, self._dstdayofweek, + self._dsthour, self._dstminute, + self._dstweeknumber) + + dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek, + self._stdhour, self._stdminute, + self._stdweeknumber) + + # Ambiguous dates default to the STD side + dstoff -= self._dst_base_offset + + return dston, dstoff + + def _get_hasdst(self): + return self._dstmonth != 0 + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +class tzwin(tzwinbase): + """ + Time zone object created from the zone info in the Windows registry + + These are similar to :py:class:`dateutil.tz.tzrange` objects in that + the time zone data is provided in the format of a single offset rule + for either 0 or 2 time zone transitions per year. + + :param: name + The name of a Windows time zone key, e.g. "Eastern Standard Time". + The full list of keys can be retrieved with :func:`tzwin.list`. + """ + + def __init__(self, name): + self._name = name + + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + keydict = valuestodict(tzkey) + + self._std_abbr = keydict["Std"] + self._dst_abbr = keydict["Dlt"] + + self._display = keydict["Display"] + + # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm + tup = struct.unpack("=3l16h", keydict["TZI"]) + stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 + dstoffset = stdoffset-tup[2] # + DaylightBias * -1 + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx + (self._stdmonth, + self._stddayofweek, # Sunday = 0 + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[4:9] + + (self._dstmonth, + self._dstdayofweek, # Sunday = 0 + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[12:17] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwin(%s)" % repr(self._name) + + def __reduce__(self): + return (self.__class__, (self._name,)) + + +class tzwinlocal(tzwinbase): + """ + Class representing the local time zone information in the Windows registry + + While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` + module) to retrieve time zone information, ``tzwinlocal`` retrieves the + rules directly from the Windows registry and creates an object like + :class:`dateutil.tz.tzwin`. + + Because Windows does not have an equivalent of :func:`time.tzset`, on + Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the + time zone settings *at the time that the process was started*, meaning + changes to the machine's time zone settings during the run of a program + on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. + Because ``tzwinlocal`` reads the registry directly, it is unaffected by + this issue. + """ + def __init__(self): + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: + keydict = valuestodict(tzlocalkey) + + self._std_abbr = keydict["StandardName"] + self._dst_abbr = keydict["DaylightName"] + + try: + tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME, + sn=self._std_abbr) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + _keydict = valuestodict(tzkey) + self._display = _keydict["Display"] + except OSError: + self._display = None + + stdoffset = -keydict["Bias"]-keydict["StandardBias"] + dstoffset = stdoffset-keydict["DaylightBias"] + + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # For reasons unclear, in this particular key, the day of week has been + # moved to the END of the SYSTEMTIME structure. + tup = struct.unpack("=8h", keydict["StandardStart"]) + + (self._stdmonth, + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[1:5] + + self._stddayofweek = tup[7] + + tup = struct.unpack("=8h", keydict["DaylightStart"]) + + (self._dstmonth, + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[1:5] + + self._dstdayofweek = tup[7] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwinlocal()" + + def __str__(self): + # str will return the standard name, not the daylight name. + return "tzwinlocal(%s)" % repr(self._std_abbr) + + def __reduce__(self): + return (self.__class__, ()) + + +def picknthweekday(year, month, dayofweek, hour, minute, whichweek): + """ dayofweek == 0 means Sunday, whichweek 5 means last instance """ + first = datetime.datetime(year, month, 1, hour, minute) + + # This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6), + # Because 7 % 7 = 0 + weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1) + wd = weekdayone + ((whichweek - 1) * ONEWEEK) + if (wd.month != month): + wd -= ONEWEEK + + return wd + + +def valuestodict(key): + """Convert a registry key's values to a dictionary.""" + dout = {} + size = winreg.QueryInfoKey(key)[1] + tz_res = None + + for i in range(size): + key_name, value, dtype = winreg.EnumValue(key, i) + if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN: + # If it's a DWORD (32-bit integer), it's stored as unsigned - convert + # that to a proper signed integer + if value & (1 << 31): + value = value - (1 << 32) + elif dtype == winreg.REG_SZ: + # If it's a reference to the tzres DLL, load the actual string + if value.startswith('@tzres'): + tz_res = tz_res or tzres() + value = tz_res.name_from_string(value) + + value = value.rstrip('\x00') # Remove trailing nulls + + dout[key_name] = value + + return dout diff --git a/.venv/Lib/site-packages/dateutil/tzwin.py b/.venv/Lib/site-packages/dateutil/tzwin.py new file mode 100644 index 00000000..cebc673e --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/tzwin.py @@ -0,0 +1,2 @@ +# tzwin has moved to dateutil.tz.win +from .tz.win import * diff --git a/.venv/Lib/site-packages/dateutil/utils.py b/.venv/Lib/site-packages/dateutil/utils.py new file mode 100644 index 00000000..dd2d245a --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/utils.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +This module offers general convenience and utility functions for dealing with +datetimes. + +.. versionadded:: 2.7.0 +""" +from __future__ import unicode_literals + +from datetime import datetime, time + + +def today(tzinfo=None): + """ + Returns a :py:class:`datetime` representing the current day at midnight + + :param tzinfo: + The time zone to attach (also used to determine the current day). + + :return: + A :py:class:`datetime.datetime` object representing the current day + at midnight. + """ + + dt = datetime.now(tzinfo) + return datetime.combine(dt.date(), time(0, tzinfo=tzinfo)) + + +def default_tzinfo(dt, tzinfo): + """ + Sets the ``tzinfo`` parameter on naive datetimes only + + This is useful for example when you are provided a datetime that may have + either an implicit or explicit time zone, such as when parsing a time zone + string. + + .. doctest:: + + >>> from dateutil.tz import tzoffset + >>> from dateutil.parser import parse + >>> from dateutil.utils import default_tzinfo + >>> dflt_tz = tzoffset("EST", -18000) + >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz)) + 2014-01-01 12:30:00+00:00 + >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz)) + 2014-01-01 12:30:00-05:00 + + :param dt: + The datetime on which to replace the time zone + + :param tzinfo: + The :py:class:`datetime.tzinfo` subclass instance to assign to + ``dt`` if (and only if) it is naive. + + :return: + Returns an aware :py:class:`datetime.datetime`. + """ + if dt.tzinfo is not None: + return dt + else: + return dt.replace(tzinfo=tzinfo) + + +def within_delta(dt1, dt2, delta): + """ + Useful for comparing two datetimes that may have a negligible difference + to be considered equal. + """ + delta = abs(delta) + difference = dt1 - dt2 + return -delta <= difference <= delta diff --git a/.venv/Lib/site-packages/dateutil/zoneinfo/__init__.py b/.venv/Lib/site-packages/dateutil/zoneinfo/__init__.py new file mode 100644 index 00000000..34f11ad6 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/zoneinfo/__init__.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +import warnings +import json + +from tarfile import TarFile +from pkgutil import get_data +from io import BytesIO + +from dateutil.tz import tzfile as _tzfile + +__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"] + +ZONEFILENAME = "dateutil-zoneinfo.tar.gz" +METADATA_FN = 'METADATA' + + +class tzfile(_tzfile): + def __reduce__(self): + return (gettz, (self._filename,)) + + +def getzoneinfofile_stream(): + try: + return BytesIO(get_data(__name__, ZONEFILENAME)) + except IOError as e: # TODO switch to FileNotFoundError? + warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) + return None + + +class ZoneInfoFile(object): + def __init__(self, zonefile_stream=None): + if zonefile_stream is not None: + with TarFile.open(fileobj=zonefile_stream) as tf: + self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name) + for zf in tf.getmembers() + if zf.isfile() and zf.name != METADATA_FN} + # deal with links: They'll point to their parent object. Less + # waste of memory + links = {zl.name: self.zones[zl.linkname] + for zl in tf.getmembers() if + zl.islnk() or zl.issym()} + self.zones.update(links) + try: + metadata_json = tf.extractfile(tf.getmember(METADATA_FN)) + metadata_str = metadata_json.read().decode('UTF-8') + self.metadata = json.loads(metadata_str) + except KeyError: + # no metadata in tar file + self.metadata = None + else: + self.zones = {} + self.metadata = None + + def get(self, name, default=None): + """ + Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method + for retrieving zones from the zone dictionary. + + :param name: + The name of the zone to retrieve. (Generally IANA zone names) + + :param default: + The value to return in the event of a missing key. + + .. versionadded:: 2.6.0 + + """ + return self.zones.get(name, default) + + +# The current API has gettz as a module function, although in fact it taps into +# a stateful class. So as a workaround for now, without changing the API, we +# will create a new "global" class instance the first time a user requests a +# timezone. Ugly, but adheres to the api. +# +# TODO: Remove after deprecation period. +_CLASS_ZONE_INSTANCE = [] + + +def get_zonefile_instance(new_instance=False): + """ + This is a convenience function which provides a :class:`ZoneInfoFile` + instance using the data provided by the ``dateutil`` package. By default, it + caches a single instance of the ZoneInfoFile object and returns that. + + :param new_instance: + If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and + used as the cached instance for the next call. Otherwise, new instances + are created only as necessary. + + :return: + Returns a :class:`ZoneInfoFile` object. + + .. versionadded:: 2.6 + """ + if new_instance: + zif = None + else: + zif = getattr(get_zonefile_instance, '_cached_instance', None) + + if zif is None: + zif = ZoneInfoFile(getzoneinfofile_stream()) + + get_zonefile_instance._cached_instance = zif + + return zif + + +def gettz(name): + """ + This retrieves a time zone from the local zoneinfo tarball that is packaged + with dateutil. + + :param name: + An IANA-style time zone name, as found in the zoneinfo file. + + :return: + Returns a :class:`dateutil.tz.tzfile` time zone object. + + .. warning:: + It is generally inadvisable to use this function, and it is only + provided for API compatibility with earlier versions. This is *not* + equivalent to ``dateutil.tz.gettz()``, which selects an appropriate + time zone based on the inputs, favoring system zoneinfo. This is ONLY + for accessing the dateutil-specific zoneinfo (which may be out of + date compared to the system zoneinfo). + + .. deprecated:: 2.6 + If you need to use a specific zoneinfofile over the system zoneinfo, + instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call + :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead. + + Use :func:`get_zonefile_instance` to retrieve an instance of the + dateutil-provided zoneinfo. + """ + warnings.warn("zoneinfo.gettz() will be removed in future versions, " + "to use the dateutil-provided zoneinfo files, instantiate a " + "ZoneInfoFile object and use ZoneInfoFile.zones.get() " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].zones.get(name) + + +def gettz_db_metadata(): + """ Get the zonefile metadata + + See `zonefile_metadata`_ + + :returns: + A dictionary with the database metadata + + .. deprecated:: 2.6 + See deprecation warning in :func:`zoneinfo.gettz`. To get metadata, + query the attribute ``zoneinfo.ZoneInfoFile.metadata``. + """ + warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future " + "versions, to use the dateutil-provided zoneinfo files, " + "ZoneInfoFile object and query the 'metadata' attribute " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].metadata diff --git a/.venv/Lib/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bafede4b4d0e0600562152ce386fee6bff17caf9 GIT binary patch literal 7404 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 U9%j#z(H+bwX8o|A2|Jqq4aM=G(EtDd literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/.venv/Lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..1461f8c862df8c3eae75e0ea376788b5b2602269 GIT binary patch literal 156400 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/dateutil/zoneinfo/rebuild.py b/.venv/Lib/site-packages/dateutil/zoneinfo/rebuild.py new file mode 100644 index 00000000..684c6586 --- /dev/null +++ b/.venv/Lib/site-packages/dateutil/zoneinfo/rebuild.py @@ -0,0 +1,75 @@ +import logging +import os +import tempfile +import shutil +import json +from subprocess import check_call, check_output +from tarfile import TarFile + +from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME + + +def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): + """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* + + filename is the timezone tarball from ``ftp.iana.org/tz``. + + """ + tmpdir = tempfile.mkdtemp() + zonedir = os.path.join(tmpdir, "zoneinfo") + moduledir = os.path.dirname(__file__) + try: + with TarFile.open(filename) as tf: + for name in zonegroups: + tf.extract(name, tmpdir) + filepaths = [os.path.join(tmpdir, n) for n in zonegroups] + + _run_zic(zonedir, filepaths) + + # write metadata file + with open(os.path.join(zonedir, METADATA_FN), 'w') as f: + json.dump(metadata, f, indent=4, sort_keys=True) + target = os.path.join(moduledir, ZONEFILENAME) + with TarFile.open(target, "w:%s" % format) as tf: + for entry in os.listdir(zonedir): + entrypath = os.path.join(zonedir, entry) + tf.add(entrypath, entry) + finally: + shutil.rmtree(tmpdir) + + +def _run_zic(zonedir, filepaths): + """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. + + Recent versions of ``zic`` default to ``-b slim``, while older versions + don't even have the ``-b`` option (but default to "fat" binaries). The + current version of dateutil does not support Version 2+ TZif files, which + causes problems when used in conjunction with "slim" binaries, so this + function is used to ensure that we always get a "fat" binary. + """ + + try: + help_text = check_output(["zic", "--help"]) + except OSError as e: + _print_on_nosuchfile(e) + raise + + if b"-b " in help_text: + bloat_args = ["-b", "fat"] + else: + bloat_args = [] + + check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) + + +def _print_on_nosuchfile(e): + """Print helpful troubleshooting message + + e is an exception raised by subprocess.check_call() + + """ + if e.errno == 2: + logging.error( + "Could not find zic. Perhaps you need to install " + "libc-bin or some other package that provides it, " + "or it's not in your PATH?") diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/INSTALLER b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/LICENSE b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/LICENSE new file mode 100644 index 00000000..756d048c --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/LICENSE @@ -0,0 +1,201 @@ + 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 [2020] [Paul Davis ] + + 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/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/METADATA b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/METADATA new file mode 100644 index 00000000..70c12664 --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/METADATA @@ -0,0 +1,154 @@ +Metadata-Version: 2.1 +Name: ghp-import +Version: 2.1.0 +Summary: Copy your docs directly to the gh-pages branch. +Home-page: https://github.com/c-w/ghp-import +Author: Paul Joseph Davis +Author-email: paul.joseph.davis@gmail.com +License: Apache Software License +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Intended Audience :: Developers +Classifier: Natural Language :: English +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: python-dateutil (>=2.8.1) +Provides-Extra: dev +Requires-Dist: twine ; extra == 'dev' +Requires-Dist: markdown ; extra == 'dev' +Requires-Dist: flake8 ; extra == 'dev' +Requires-Dist: wheel ; extra == 'dev' + +GitHub Pages Import +=================== + +[![CI status](https://github.com/davisp/ghp-import/workflows/CI/badge.svg)](https://github.com/davisp/ghp-import/actions?query=workflow%3Aci) +[![CircleCI](https://circleci.com/gh/c-w/ghp-import/tree/master.svg?style=svg)](https://circleci.com/gh/c-w/ghp-import/tree/master) +[![TravisCI](https://travis-ci.org/c-w/ghp-import.svg?branch=master)](https://travis-ci.org/c-w/ghp-import) + +[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) +[![Version](https://img.shields.io/pypi/v/ghp-import.svg)](https://pypi.org/project/ghp-import/) + +As part of [gunicorn][gunicorn], [Benoit Chesneau][benoit] and [Paul Davis][davisp] +were looking at how to host documentation. There's the obvious method of +using [GitHub's post-receive hook][github-post] to trigger doc builds and rsync +to a webserver, but we ended up wanting to try out github's hosting to make the +whole interface a bit more robust. + +[GitHub Pages][gh-pages] is a pretty awesome service that GitHub provides for +hosting project documentation. The only thing is that it requires a +`gh-pages` branch that is the site's document root. This means that keeping +documentation sources in the branch with code is a bit difficult. And it really +turns into a head scratcher for things like [Sphinx][sphinx] that want to +access documentation sources and code sources at the same time. + +Then we stumbled across an interesting looking package called +[github-tools][github-tools] that looked almost like what we wanted. It was a tad +complicated and more involved than we wanted but it gave us an idea. Why not +just write a script that can copy a directory to the `gh-pages` branch of the +repository. This saves us from even having to think about the branch and +everything becomes magical. + +This is what `ghp-import` was written for. + +[gunicorn]: http://www.gunicorn.com/ "Gunicorn" +[benoit]: http://github.com/benoitc "Benoît Chesneau" +[davisp]: http://github.com/davisp "Paul J. Davis" +[github-post]: https://help.github.com/articles/post-receive-hooks "GitHub Post-Receive Hook" +[gh-pages]: http://pages.github.com/ "GitHub Pages" +[sphinx]: http://sphinx.pocoo.org/ "Sphinx Documentation" +[github-tools]: http://dinoboff.github.com/github-tools/ "github-tools" + + +Big Fat Warning +--------------- + +This will **DESTROY** your `gh-pages` branch. If you love it, you'll want to +take backups before playing with this. This script assumes that `gh-pages` is +100% derivative. You should never edit files in your `gh-pages` branch by hand +if you're using this script because you will lose your work. + +When used with a prefix, only files below the set prefix will be destroyed, limiting the +above warning to just that directory and everything below it. + +Usage +----- + +``` +Usage: ghp-import [OPTIONS] DIRECTORY + +Options: + -n, --no-jekyll Include a .nojekyll file in the branch. + -c CNAME, --cname=CNAME + Write a CNAME file with the given CNAME. + -m MESG, --message=MESG + The commit message to use on the target branch. + -p, --push Push the branch to origin/{branch} after committing. + -x PREFIX, --prefix=PREFIX + The prefix to add to each file that gets pushed to the + remote. Only files below this prefix will be cleared + out. [none] + -f, --force Force the push to the repository. + -o, --no-history Force new commit without parent history. + -r REMOTE, --remote=REMOTE + The name of the remote to push to. [origin] + -b BRANCH, --branch=BRANCH + Name of the branch to write to. [gh-pages] + -s, --shell Use the shell when invoking Git. [False] + -l, --follow-links Follow symlinks when adding files. [False] + -h, --help show this help message and exit +``` + +Its pretty simple. Inside your repository just run `ghp-import $DOCS_DIR` +where `$DOCS_DIR` is the path to the **built** documentation. This will write a +commit to your `gh-pages` branch with the current documents in it. + +If you specify `-p` it will also attempt to push the `gh-pages` branch to +GitHub. By default it'll just run `git push origin gh-pages`. You can specify +a different remote using the `-r` flag. + +The `-o` option will discard any previous history and ensure that only a +single commit is always pushed to the `gh-pages` branch. This is useful to +avoid bloating the repository size and is **highly recommended**. + +You can specify a different branch with `-b`. This is useful for user and +organization page, which are served from the `master` branch. + +Some Windows users report needing to pass Git commands through the shell which can be accomplished by passing `-s`. + +The `-l` option will cause the import to follow symlinks for users that have odd configurations that include symlinking outside of their documentation directory. + +Python Usage +------------ + +You can also call ghp_import directly from your Python code as a library. The +library has one public function `ghp_import.ghp_import`, which accepts the +following arguments: + +* `srcdir`: The path to the **built** documentation (required). +* `remote`: The name of the remote to push to. Default: `origin`. +* `branch`: Name of the branch to write to. Default: `gh-pages`. +* `mesg`: The commit message to use on the target branch. Default: `Update documentation`. +* `push`: Push the branch to {remote}/{branch} after committing. Default: `False`. +* `prefix`: The prefix to add to each file that gets pushed to the remote. Default: `None`. +* `force`: Force the push to the repository. Default: `False`. +* `no_history`: Force new commit without parent history. Default: `False`. +* `use_shell`: Default: Use the shell when invoking Git. `False`. +* `followlinks`: Follow symlinks when adding files. Default: `False`. +* `cname`: Write a CNAME file with the given CNAME. Default: `None`. +* `nojekyll`: Include a .nojekyll file in the branch. Default: `False`. + +With Python's current working directory (cwd) inside your repository, do the +following: + +```python +from ghp_import import ghp_import +ghp_import('docs', push=True, cname='example.com') +``` + + diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/RECORD b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/RECORD new file mode 100644 index 00000000..e079e532 --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/RECORD @@ -0,0 +1,10 @@ +../../Scripts/ghp-import.exe,sha256=2m0lwK5ZZQjdPkdms19CqN6kcnub1FSQLDgbKL8gm_Q,108386 +__pycache__/ghp_import.cpython-312.pyc,, +ghp_import-2.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +ghp_import-2.1.0.dist-info/LICENSE,sha256=C8j_tF8m7dHNDeT1BCWuLLRsWMbYrBE5hNQSC-NVr6k,11374 +ghp_import-2.1.0.dist-info/METADATA,sha256=PCrYmDTJ2XjIuUkYM33d1t8Fva95SG2UphvN-t9b6y8,7177 +ghp_import-2.1.0.dist-info/RECORD,, +ghp_import-2.1.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +ghp_import-2.1.0.dist-info/entry_points.txt,sha256=mk55YA2cS0KmQK9APJFk_1ny9zFWFOZDtOBZMO0cu1Y,48 +ghp_import-2.1.0.dist-info/top_level.txt,sha256=QGVcxjaCFAMEV3ZX7ADAlIMIlsiyfplHNQi-JwrTgow,11 +ghp_import.py,sha256=zvDcFrdka_GzgEkD1BjJrBfDHD3sCExSbnJHmBE1igU,9234 diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/WHEEL b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/entry_points.txt b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/entry_points.txt new file mode 100644 index 00000000..6f2959a8 --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +ghp-import = ghp_import:main + diff --git a/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/top_level.txt b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/top_level.txt new file mode 100644 index 00000000..a780cead --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import-2.1.0.dist-info/top_level.txt @@ -0,0 +1 @@ +ghp_import diff --git a/.venv/Lib/site-packages/ghp_import.py b/.venv/Lib/site-packages/ghp_import.py new file mode 100644 index 00000000..328422bd --- /dev/null +++ b/.venv/Lib/site-packages/ghp_import.py @@ -0,0 +1,306 @@ +#! /usr/bin/env python + +import errno +import os +import subprocess as sp +import sys +import time +from dateutil import tz +from datetime import datetime + +try: + from shlex import quote +except ImportError: + from pipes import quote + +__all__ = ['ghp_import'] +__version__ = "2.1.0" + + +class GhpError(Exception): + def __init__(self, message): + self.message = message + + +if sys.version_info[0] == 3: + def enc(text): + if isinstance(text, bytes): + return text + return text.encode() + + def dec(text): + if isinstance(text, bytes): + return text.decode('utf-8') + return text + + def write(pipe, data): + try: + pipe.stdin.write(data) + except IOError as e: + if e.errno != errno.EPIPE: + raise +else: + def enc(text): + if isinstance(text, unicode): # noqa F821 + return text.encode('utf-8') + return text + + def dec(text): + if isinstance(text, unicode): # noqa F821 + return text + return text.decode('utf-8') + + def write(pipe, data): + pipe.stdin.write(data) + + +class Git(object): + def __init__(self, use_shell=False): + self.use_shell = use_shell + + self.cmd = None + self.pipe = None + self.stderr = None + self.stdout = None + + def check_repo(self): + if self.call('rev-parse') != 0: + error = self.stderr + if not error: + error = "Unknown Git error" + error = dec(error) + if error.startswith("fatal: "): + error = error[len("fatal: "):] + raise GhpError(error) + + def try_rebase(self, remote, branch, no_history=False): + rc = self.call('rev-list', '--max-count=1', '%s/%s' % (remote, branch)) + if rc != 0: + return True + rev = dec(self.stdout.strip()) + if no_history: + rc = self.call('update-ref', '-d', 'refs/heads/%s' % branch) + else: + rc = self.call('update-ref', 'refs/heads/%s' % branch, rev) + if rc != 0: + return False + return True + + def get_config(self, key): + self.call('config', key) + return self.stdout.strip() + + def get_prev_commit(self, branch): + rc = self.call('rev-list', '--max-count=1', branch, '--') + if rc != 0: + return None + return dec(self.stdout).strip() + + def open(self, *args, **kwargs): + if self.use_shell: + self.cmd = 'git ' + ' '.join(map(quote, args)) + else: + self.cmd = ['git'] + list(args) + if sys.version_info >= (3, 2, 0): + kwargs['universal_newlines'] = False + for k in 'stdin stdout stderr'.split(): + kwargs.setdefault(k, sp.PIPE) + kwargs['shell'] = self.use_shell + self.pipe = sp.Popen(self.cmd, **kwargs) + return self.pipe + + def call(self, *args, **kwargs): + self.open(*args, **kwargs) + (self.stdout, self.stderr) = self.pipe.communicate() + return self.pipe.wait() + + def check_call(self, *args, **kwargs): + kwargs["shell"] = self.use_shell + sp.check_call(['git'] + list(args), **kwargs) + + +def mk_when(timestamp=None): + if timestamp is None: + timestamp = int(time.time()) + currtz = datetime.now(tz.tzlocal()).strftime('%z') + return "%s %s" % (timestamp, currtz) + + +def start_commit(pipe, git, branch, message, prefix=None): + uname = os.getenv('GIT_COMMITTER_NAME', dec(git.get_config('user.name'))) + email = os.getenv('GIT_COMMITTER_EMAIL', dec(git.get_config('user.email'))) + when = os.getenv('GIT_COMMITTER_DATE', mk_when()) + write(pipe, enc('commit refs/heads/%s\n' % branch)) + write(pipe, enc('committer %s <%s> %s\n' % (uname, email, when))) + write(pipe, enc('data %d\n%s\n' % (len(enc(message)), message))) + head = git.get_prev_commit(branch) + if head: + write(pipe, enc('from %s\n' % head)) + if prefix: + write(pipe, enc('D %s\n' % prefix)) + else: + write(pipe, enc('deleteall\n')) + + +def add_file(pipe, srcpath, tgtpath): + with open(srcpath, "rb") as handle: + if os.access(srcpath, os.X_OK): + write(pipe, enc('M 100755 inline %s\n' % tgtpath)) + else: + write(pipe, enc('M 100644 inline %s\n' % tgtpath)) + data = handle.read() + write(pipe, enc('data %d\n' % len(data))) + write(pipe, enc(data)) + write(pipe, enc('\n')) + + +def add_nojekyll(pipe, prefix=None): + if prefix: + fpath = os.path.join(prefix, '.nojekyll') + else: + fpath = '.nojekyll' + write(pipe, enc('M 100644 inline %s\n' % fpath)) + write(pipe, enc('data 0\n')) + write(pipe, enc('\n')) + + +def add_cname(pipe, cname): + write(pipe, enc('M 100644 inline CNAME\n')) + write(pipe, enc('data %d\n%s\n' % (len(enc(cname)), cname))) + + +def gitpath(fname): + norm = os.path.normpath(fname) + return "/".join(norm.split(os.path.sep)) + + +def run_import(git, srcdir, **opts): + srcdir = dec(srcdir) + pipe = git.open('fast-import', '--date-format=rfc2822', '--quiet', + stdin=sp.PIPE, stdout=None, stderr=None) + start_commit(pipe, git, opts['branch'], opts['mesg'], opts['prefix']) + for path, _, fnames in os.walk(srcdir, followlinks=opts['followlinks']): + for fn in fnames: + fpath = os.path.join(path, fn) + gpath = gitpath(os.path.relpath(fpath, start=srcdir)) + if opts['prefix']: + gpath = os.path.join(opts['prefix'], gpath) + add_file(pipe, fpath, gpath) + if opts['nojekyll']: + add_nojekyll(pipe, opts['prefix']) + if opts['cname'] is not None: + add_cname(pipe, opts['cname']) + write(pipe, enc('\n')) + pipe.stdin.close() + if pipe.wait() != 0: + sys.stdout.write(enc("Failed to process commit.\n")) + + +def options(): + return [ + (('-n', '--no-jekyll'), dict( + dest='nojekyll', + default=False, + action="store_true", + help='Include a .nojekyll file in the branch.', + )), + (('-c', '--cname'), dict( + dest='cname', + default=None, + help='Write a CNAME file with the given CNAME.', + )), + (('-m', '--message'), dict( + dest='mesg', + default='Update documentation', + help='The commit message to use on the target branch.', + )), + (('-p', '--push'), dict( + dest='push', + default=False, + action='store_true', + help='Push the branch to origin/{branch} after committing.', + )), + (('-x', '--prefix'), dict( + dest='prefix', + default=None, + help='The prefix to add to each file that gets pushed to the ' + 'remote. Only files below this prefix will be cleared ' + 'out. [%(default)s]', + )), + (('-f', '--force'), dict( + dest='force', + default=False, action='store_true', + help='Force the push to the repository.', + )), + (('-o', '--no-history'), dict( + dest='no_history', + default=False, + action='store_true', + help='Force new commit without parent history.', + )), + (('-r', '--remote'), dict( + dest='remote', + default='origin', + help='The name of the remote to push to. [%(default)s]', + )), + (('-b', '--branch'), dict( + dest='branch', + default='gh-pages', + help='Name of the branch to write to. [%(default)s]', + )), + (('-s', '--shell'), dict( + dest='use_shell', + default=False, + action='store_true', + help='Use the shell when invoking Git. [%(default)s]', + )), + (('-l', '--follow-links'), dict( + dest='followlinks', + default=False, + action='store_true', + help='Follow symlinks when adding files. [%(default)s]', + )) + ] + + +def ghp_import(srcdir, **kwargs): + if not os.path.isdir(srcdir): + raise GhpError("Not a directory: %s" % srcdir) + + opts = {kwargs["dest"]: kwargs["default"] for _, kwargs in options()} + opts.update(kwargs) + + git = Git(use_shell=opts['use_shell']) + git.check_repo() + + if not git.try_rebase(opts['remote'], opts['branch'], opts['no_history']): + raise GhpError("Failed to rebase %s branch." % opts['branch']) + + run_import(git, srcdir, **opts) + + if opts['push']: + if opts['force'] or opts['no_history']: + git.check_call('push', opts['remote'], opts['branch'], '--force') + else: + git.check_call('push', opts['remote'], opts['branch']) + + +def main(): + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument("--version", action="version", version=__version__) + parser.add_argument("directory") + for args, kwargs in options(): + parser.add_argument(*args, **kwargs) + + args = parser.parse_args().__dict__ + + try: + ghp_import(args.pop("directory"), **args) + except GhpError as e: + parser.error(e.message) + + +if __name__ == '__main__': + main() diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/INSTALLER b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/METADATA b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/METADATA new file mode 100644 index 00000000..265cc32e --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/METADATA @@ -0,0 +1,76 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 3.1.4 +Summary: A very fast and expressive template engine. +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Typing :: Typed +Requires-Dist: MarkupSafe>=2.0 +Requires-Dist: Babel>=2.7 ; extra == "i18n" +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/jinja/ +Provides-Extra: i18n + +# Jinja + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +## In A Nutshell + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} +

+ {% endblock %} + + +## Donate + +The Pallets organization develops and supports Jinja and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/RECORD b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/RECORD new file mode 100644 index 00000000..b1a27b12 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/RECORD @@ -0,0 +1,57 @@ +jinja2-3.1.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2-3.1.4.dist-info/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +jinja2-3.1.4.dist-info/METADATA,sha256=R_brzpPQVBvpGcsm-WbrtgotO7suQ1D0F-qkhTzeEfY,2640 +jinja2-3.1.4.dist-info/RECORD,, +jinja2-3.1.4.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +jinja2-3.1.4.dist-info/entry_points.txt,sha256=OL85gYU1eD8cuPlikifFngXpeBjaxl6rIJ8KkC_3r-I,58 +jinja2/__init__.py,sha256=wIl45IM20KGw-kfr7jJhaBxxX5g4-kihlBYjxopX7Pw,1928 +jinja2/__pycache__/__init__.cpython-312.pyc,, +jinja2/__pycache__/_identifier.cpython-312.pyc,, +jinja2/__pycache__/async_utils.cpython-312.pyc,, +jinja2/__pycache__/bccache.cpython-312.pyc,, +jinja2/__pycache__/compiler.cpython-312.pyc,, +jinja2/__pycache__/constants.cpython-312.pyc,, +jinja2/__pycache__/debug.cpython-312.pyc,, +jinja2/__pycache__/defaults.cpython-312.pyc,, +jinja2/__pycache__/environment.cpython-312.pyc,, +jinja2/__pycache__/exceptions.cpython-312.pyc,, +jinja2/__pycache__/ext.cpython-312.pyc,, +jinja2/__pycache__/filters.cpython-312.pyc,, +jinja2/__pycache__/idtracking.cpython-312.pyc,, +jinja2/__pycache__/lexer.cpython-312.pyc,, +jinja2/__pycache__/loaders.cpython-312.pyc,, +jinja2/__pycache__/meta.cpython-312.pyc,, +jinja2/__pycache__/nativetypes.cpython-312.pyc,, +jinja2/__pycache__/nodes.cpython-312.pyc,, +jinja2/__pycache__/optimizer.cpython-312.pyc,, +jinja2/__pycache__/parser.cpython-312.pyc,, +jinja2/__pycache__/runtime.cpython-312.pyc,, +jinja2/__pycache__/sandbox.cpython-312.pyc,, +jinja2/__pycache__/tests.cpython-312.pyc,, +jinja2/__pycache__/utils.cpython-312.pyc,, +jinja2/__pycache__/visitor.cpython-312.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=JXKWCAXmTx0iZB4-hAsF50vgjxw_RJTjiLOlGGTBso0,2477 +jinja2/bccache.py,sha256=gh0qs9rulnXo0PhX5jTJy2UHzI8wFnQ63o_vw7nhzRg,14061 +jinja2/compiler.py,sha256=dpV-n6_iQUP4uSwlXwGUavJmwjvXdyxKzJ-AonFjPBk,72271 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=iWJ432RadxJNnaMOPrjIDInz50UEgni3_HKuFXi2vuQ,6299 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=xhFkmxO0CESA76Ki5tz4XWq9yzGu-t0p93JCCVBVNps,61538 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=igsBH7c6C0byHaOtMbE-ugpt4GjLGgR-ywskyXtKgq8,31877 +jinja2/filters.py,sha256=bKeqjFjjz88TkHVLSyyMIEB75CzAN6b3Airgx0phJDg,54611 +jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704 +jinja2/lexer.py,sha256=xnWWXhPndHFsoqzpc5VTjheDE9JuKk9MUo9DZkrM8Os,29754 +jinja2/loaders.py,sha256=ru0GIWHo5KiHJi7_MoI_LvGDoBBvP6rd0hiC1ReaTwk,23167 +jinja2/meta.py,sha256=OTDPkaFvU2Hgvx-6akz7154F8BIWaRmvJcBFvwopHww,4397 +jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 +jinja2/nodes.py,sha256=m1Duzcr6qhZI8JQ6VyJgUNinjAf5bQzijSmDnMsvUx8,34579 +jinja2/optimizer.py,sha256=rJnCRlQ7pZsEEmMhsQDgC_pKyDHxP5TPS6zVPGsgcu8,1651 +jinja2/parser.py,sha256=DV1iF1FR2Rsaj_5zl8rmx7j6Bj4S8iLHoYsvJ0bfEis,39890 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=POXT3tKNKJRENx2CymwUsOOXH2JwGPjW702njB5__cQ,33435 +jinja2/sandbox.py,sha256=TJjBNS9qRJ2ZgBMWdAgRBpyDLOHea2kT-2mk4PrjYx0,14616 +jinja2/tests.py,sha256=VLsBhVFnWg-PxSBz1MhRnNWgP1ovXk3neO1FLQMeC9Q,5926 +jinja2/utils.py,sha256=nV7IpWLvRCMyHW1irBAK8CIPAnOFfkb2ukggDBjbBEY,23952 +jinja2/visitor.py,sha256=EcnL1PIwf_4RVCOMxsRNuR8AXHbS1qfAdMOE2ngKJz4,3557 diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/WHEEL b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/WHEEL new file mode 100644 index 00000000..3b5e64b5 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/entry_points.txt b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/entry_points.txt new file mode 100644 index 00000000..abc3eae3 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2-3.1.4.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2=jinja2.ext:babel_extract[i18n] + diff --git a/.venv/Lib/site-packages/jinja2/__init__.py b/.venv/Lib/site-packages/jinja2/__init__.py new file mode 100644 index 00000000..2f0b5b28 --- /dev/null +++ b/.venv/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.4" diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4143f3697d5649ae7aae33192b06eb8293bbd09e GIT binary patch literal 1623 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 BJ%a!M literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/constants.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/constants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..914d05e82eb2cf3a5a65bfa5dd25faa4d2b8efe1 GIT binary patch literal 1526 zcmX|>&#E0o5XR5ZC}H3(BDj^_W?=-E7jYFALSiIA1UV3Tdg`20*PiaV{b%4liTDWF z_#&=!>DCtrWEWict2tK>bE>}SsjmL|tLpy!>T1~W`{%bmkH3Dj+x=}X|NZv&;N3&O zFS}{?)9!Bn_yd1Upm#p-gg#fFoS%4f(Hb3@ zZt80P>f|J~u@t^JiK0h#Gyv{-OJrM;NFfEHQZlimw&-SSO6SqahTYKz=vMt7RM0GS zIHH=dbVt&eE%(`v(oag-W1$urqj$$%gSb=it4`jXZOfG59@HwJFr497q`>TaMt?J_Tz$y975;FTJwR<)-(<5e^&76HN=I98lx;Ycp zR0e=;XU@gkq1OG2OuS2syhvr8VPS`Dt0`K$<;(<23#f!aVL{5RWdKe1 zf>IaTOg!EzXMjZ6&X>BSc&Xc3WKznr6rB-ZDVZuRJ+2BXKq2{dR&T9;&Dg%nIVVat z6s7yS5kOY6y%myGf6`6w%6XCG&@a+J+tezPt3r%e-{4TwM6B9|nuD^6xlAx%vO40a zPT)9BkYk;|h0+Y53ulc!ZFCgdY8N#cxpNuJk-5>7I(39a3D{qNsnX!oxQdwH3wM;W zGR+|uW7Z>|1Lx@i6ds*Yx!&CBi;{Siv+dpkqW$5tvK=dxeI)gWHnUqfRf1hTEj8e! zP`owA-WHDI+T+q2W&7^&{;x;RUcCI~`Ri}LfAz!j*FU~^`SjJB-8;K&-(NqyK2V+; z| X!o2-(zu&)o@X4p2{jqyg9x(DR+;c7| literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7846427ca658f0e0c1306c9ce0e18a63ce60a482 GIT binary patch literal 6536 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 Ly!8dvlQI1tB_%Cb zEJ(xPo4@dJ5g8o=NXGEcJ?KG~{U2T2(IupDoRB7PQo4du;GOQXSIIRpNx~#VB4iL} zUIwJ=co>gh0p3ygjp1QczzLjv8I-0V(t?}EMNdY7e|#}^(YmLf={S$o6><~D+*CP+ zTBDr61{O-?npj;0=&y;ZH4XyBZbKs!P1~!Nmnx#XS}WAVC9zVISE}Md=|h%s=;HFyC34|R z2wPW8k}s@rwAt`IO?5HL+3@a{=b3ioQXZ533E61vDp5 z7HBx@V1Z31TNcvYTx%?-w_0t!xMM#Qf`yD0HRUbRHF7~K*=RM}DpVk^7!6gG4U<~o z4%JkPtHg~mTo03kz3DTKEsN`JbCqvxAnY9)n=1m7M~Xv3TtJk+;X{8EQzbR85S_RZB^f3 zg2@KfRSl|TP`Fr#4Y}g}#xlQ24AY>_GNZ21*=pwRn5t&b0Qk`X-UNBW?<0%WK3Wmw z;$yM6SgJf?iSuwWp;{_DEIWtb zLYVrOzNAgN2jV|-CSCSIN%gf6oJH+WGAgv z7A^BUSNcO5<$}zjD6Yu0YM}(@>XF<(Uo-|bI>ZGDw{DfflDN83D2jB1^S*h0-n<39 z`#m}Z0-fERf2ZE2txeJ}>$ugZ=bsY&X}zp|RyW{C&%s66QZ|TD-&FNY<<4zP)|HNC z8u@njEO@Wk!X1sgOW%Z<`295ggyzI62*R%@`3JgvgmOn{>Lh@MvptlwQzJbTw?`*>C}VRbWsi*aP}_QX*Y|Gh-q=s=E8mfC$$s{y P+rV6FcE3dh7D literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/environment.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/environment.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b378b19dc60b5a6e6c83f0b85cf9411a2a74b0f GIT binary patch literal 76670 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 Cn@ME= literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11a3a392e74071799734d469349e397eedec5fd2 GIT binary patch literal 7685 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/ext.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/ext.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1dd9720df30415c715b372057df9c5c14f061fc GIT binary patch literal 41832 zcmd75dw5$%b|-l8eiPsed{ZDPK0ryNDC$YQEKzUClx#h0({_^(E+~;A0rmwbi8R

c28_t_u{X}{=8v6)LiHr^ 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5eeb9200f51a5f418925788e53871d23ec687c10 GIT binary patch literal 71979 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�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

4>k` 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3638edecd5068940914f9dbc1ddfacd8b705b3b6 GIT binary patch literal 19119 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 b8u+4LaOD1a^$bMX-ON<#uWRh5dJO+Rj-;dx literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec4f1f5fd9a3edd4d27128f102392a2a2be86ab1 GIT binary patch literal 30940 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 M>puweWb^%h0skiKI{*Lx literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/meta.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/meta.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe1399fa75319086666209992bda2ba536d414a0 GIT binary patch literal 5440 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 XUMBD;9^gp(&NWv? literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80a762fc874f2b2fc0e24f4b62bfca731318a52a GIT binary patch literal 58179 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..263529b16e45634fb0e3449949f311e1591e360d GIT binary patch literal 48449 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 JP-3+Ee*q=C%OU^( literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fe81d3a667cd5181b478b00bb448029be48d760 GIT binary patch literal 9020 zcmcgwU2Gi3k)GL|`QaY!_1+H1%i4N~GdTkWl05h+6EhEikcWKL zJ+r&~S*{HPH^6jPcU4zcbyrta_b+Q}qYA#i{Nm$WnJtz)TQzFs)@mGa;35TDmF|o(TgE8CB^>rh2AYz~OW>6Pt;t3JWea`Rt1| zuL6A}U7M+!sRMmAJ77dv{eou1eyGhHENR!E-5}bv9!-@|hrUDT3oZ^6Ir@;t=KyFL zE6~(~<_L=!2MwCxs2Evg9QvX5fyZp7X&3fz3AVWc|3>g{sX%iCG_4hAj)JDG0!OVhcJ zjZ_(37~5BNthC2&(DYZJ=>g3^S(;wR@Gajui}l`;HG{yj!#;2wN-0J^JNOgT7+?)3 z2iYN%L#z?yFgt?sIo5>oIBP~3XDuk7XRRn-U~MQzSUbuStOMmqb`0eyrlUN~I#Hfs zT_|5<-9J$=&so-k)=R7xrir1c?;883^uTo&^>FyHfe6l-vMqa5aa6_~jqtq*<0-g$pq zu?B}ddW|bT3%#$-oLCMFer@HQF%20i)PWEow+o6b%~pcENNdg z%;eShEy#KG>#6yxR?23_mlDYviEGTdx|qr?CQdvrmL|Tm>_iBf1#eytJ_qn`5%7-k zS*(6-ivs(t$7Q5%2!mVr-DKZBF1?Q7;~XkEkSiCq)MEGajJ!UM9L4NO+PHl>nwSL7C51oF0YZgm9kQ_*7M6ificV=UX*Mw zAeNgqVk(QK(RC?dy^ydle14fDfl$b2StO`j$&>fbZFGJVYt3t|Lh@}(sew$`Mh}2> z#V***J;g34_kjo1khQ3Zb0Dg)zMkQZMx#2ucwD#498a>OX|T~zT^NEy5&CW~Ey=b8 zk#?{5eqW3yBKm}h>t>O5RKI(-IPm*LYOrK!i|uAmwCSvA>zkB5wepx9TdZyn_EbF$ZTg=vT{>c?ge9f%5Xg&!z zQEYeCvJ=@P<2Z@CO|M37tXu}(3X%@|7Mb8X%AeYl`j(B}|7d=CU^pKe&TGT_>}wZ> zRN7bC)s^F4Pu(b0lpN2TKA*G20+?6@E>z?uw2N~xvRx;pPKaI5p0|VOdHfcgr+1X! z#TwVx&)$9->(6Wb-YJ5s;1OW=K1!rDJeGP-Sp>B6yCvB*4GT5m|EAKA$#|H_BOWe~M(rToW~Vq|w-~ob1;bzlq&yjaK`4ee5tiau zPXe6QQ@ZX_Hxd)uCaE|X%qjfVAr$W@ZiiBHaBXb;%?EGhW5@E^F==a_M*xYU5G;Ji zm)fm&x9=8Bt?##2g5YntQ)x42h+Pt#ckYqri)fp$kwm-GiI6AqH|1V#3DLZC7X@~2 z@3U=S+PuB@K!0C}n!Ylw%$J~a?p^L{U$Y32{ub}V?rjSyGVBqO_X2mB@SZL7Nn5z` z;7UH$p4ZxU`<;R<(4AK18aXTJM4Y#&%X_OJ zJ-Ww?4?>~@X+iNChb&493q3xL4Q-5XPH#-)wV{0!+O@cs_Eq9?0IkCkj&PZPC+(+Ou7_!}VinpUhIyE~! z|HdS&XR?A4nZ(i(w9p5P6oL-3lkvfQPRtpZ)&-@;WDQRE8PO@4XlR!H!Q=mIK|2UD(ndg$GsTZDm=#t=tK|t=v}e zT=Kn&Dq8Gjj^TC}*C#y)sRU<*yQ(EN(Y~IrMK_*FxV&*t#&>yYFz5u+EbGK(XRk3E z*v#y#Q$2ns$;35f*J{;@5baOOUx!jZ$8S+gK$MPXp~nA<#8$_D9Q`Cx`>ROv$B||? zqSVy?`A=b`rtu3!4K@Dyz+pFt`k6?q-aXo){It3+_`cc~bVB0txAz6j&qVI2BArrK z{!qM$Wp(eUE|~~Y7F~|%E^XmDre|2j(9GMJKEBA80(^BP8Kp1LD7k!b_eGQ_@#1c_IrGVN2#C<*Zm(Yr&59wAPWr zj->2 z4x`h8WOOyF(?5mgFUy?e$&uLgYy)pDO)|=OQh0j5lXE!Sy z3i(2@GFp(YAR8WwF@7IEKO*n%+w5zS1S++!usHasET0A@PuSALd~Ef6UOVbZi+5H> zqsL4qR`OuzguOQ~r@HWL<5bC~07oP4jz;$`C+uBaoRBzBz#+v(Rv>d(egbnlA(7QM zA(0F?RWjr{VK4qTRnnb15#Lcc5#M^8ND{}7Tp)&t)8d4^op1uF>`LIm1t-96qVr}h zk+#j1Kqoq~?3sGe30$+C*fpGA*em%Fbg-4c#S4R>XX<$;khYyj8a{?lD}nPEmS%$| zo$%}|-m2kNBmR55Q)Mqx9ClRjOPc94u7G$@vAB$}Qh1Bg!F0krm$g$F`FaP1?Nr+0 zVZzi-z5RFNvtw_JkG*+i;&mrh@?797bZ6og6*($yqi{k~w`d| zs=rpw|5iEh8>Qh>rS(&#<@ZX*r%Lx{LG7Pje)r{1wE?#(pth`yxeBU{OIuXAQRTaR#0uzA51eMzmQr}XG zT;5V8o3~WL^c4B@NIpGoeE^z?_0cyB5=5uP+@q^&?dE#!L5@W3+B{5@T_o~Qak3#f z*AVgSEmHSN>RvY*RqHnnK5Bf}=qdm=Pi;}UP7_h$x}D)q8F=!BHhtzt-W#2(D2=wW~MW zT7v78Pz-|)5L_?eg9JCov4;pgtb}S-XWT}Dk4T!M1UE^VW`bKJO)J4|5^g8BL&C=h z*5$mN1b2zCf9xi>NA~v;+^2*Ntkt^x1P@4fkl-PLBknN4&q?~@1jnTe&lCKD5~^P9 zcSi_5LGZwP!}o{Xlhi&{Y@ep~85(!zy}S4Cx-U}uY!UwwwMUEXbJRYsgd(d=@3r1< zbuUo+ViEr`wO>)O@@r?;&pkNjzN%8sYv}Ps7!y60iamcE7d@9%CE7qtKS2dqKdEn8 Uk3ER_E!p|STSWU0AraO73dsQsW&i*H literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..deb240e2961067a479bf5d3969d0c3a106307165 GIT binary patch literal 34468 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

7p_f3Lv`#9)Fj@f$DHkZE%P1wQ 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 L`8iOIFB1Ph#23<7 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/__pycache__/visitor.cpython-312.pyc b/.venv/Lib/site-packages/jinja2/__pycache__/visitor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ffc2a5d78168d682266b62f13981b6e9ec1729d GIT binary patch literal 5323 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 literal 0 HcmV?d00001 diff --git a/.venv/Lib/site-packages/jinja2/_identifier.py b/.venv/Lib/site-packages/jinja2/_identifier.py new file mode 100644 index 00000000..928c1503 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/jinja2/async_utils.py b/.venv/Lib/site-packages/jinja2/async_utils.py new file mode 100644 index 00000000..e65219e4 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2/async_utils.py @@ -0,0 +1,84 @@ +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 + +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 t.cast("V", value) + + +async def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + async for item in t.cast("t.AsyncIterable[V]", iterable): + yield item + else: + for item in iterable: + yield item + + +async def auto_to_list( + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> t.List["V"]: + return [x async for x in auto_aiter(value)] diff --git a/.venv/Lib/site-packages/jinja2/bccache.py b/.venv/Lib/site-packages/jinja2/bccache.py new file mode 100644 index 00000000..ada8b099 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/jinja2/compiler.py b/.venv/Lib/site-packages/jinja2/compiler.py new file mode 100644 index 00000000..27407175 --- /dev/null +++ b/.venv/Lib/site-packages/jinja2/compiler.py @@ -0,0 +1,1960 @@ +"""Compiles nodes from the parser into Python code.""" + +import typing as t +from contextlib import contextmanager +from functools import update_wrapper +from io import StringIO +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import _PassArg +from .utils import concat +from .visitor import NodeVisitor + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + + +def optimizeconst(f: F) -> F: + def new_func( + self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any + ) -> t.Any: + # Only optimize if the frame is not volatile + if self.optimizer is not None and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + + if new_node != node: + return self.visit(new_node, frame) + + return f(self, node, frame, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor + + +def generate( + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + + if stream is None: + return generator.stream.getvalue() # type: ignore + + return None + + +def has_safe_repr(value: t.Any) -> bool: + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + + if type(value) in {bool, int, float, complex, range, str, Markup}: + return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: # noqa E721 + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + + return False + + +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame: + """Holds compile time information for us.""" + + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: + self.eval_ctx = eval_ctx + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False + + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False + + def copy(self) -> "Frame": + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated: bool = False) -> "Frame": + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self) -> "Frame": + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements and conditional + expressions. + """ + rv = self.copy() + rv.rootlevel = False + rv.soft_frame = True + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self) -> None: + self.filters: t.Set[str] = set() + self.tests: t.Set[str] = set() + + def visit_Filter(self, node: nodes.Filter) -> None: + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node: nodes.Test) -> None: + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names: t.Iterable[str]) -> None: + self.names = set(names) + self.undeclared: t.Set[str] = set() + + def visit_Name(self, node: nodes.Name) -> None: + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, + ) -> None: + if stream is None: + stream = StringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimizer: t.Optional[Optimizer] = None + + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases: t.Dict[str, str] = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks: t.Dict[str, nodes.Block] = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests: t.Dict[str, str] = {} + self.filters: t.Dict[str, str] = {} + + # the debug information + self.debug_info: t.List[t.Tuple[int, int]] = [] + self._write_debug_info: t.Optional[int] = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack: t.List[t.Set[str]] = [] + + # Tracks parameter definition blocks + self._param_def_block: t.List[t.Set[str]] = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + @property + def optimized(self) -> bool: + return self.optimizer is not None + + # -- Various compilation helpers + + def fail(self, msg: str, lineno: int) -> "te.NoReturn": + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self) -> str: + """Get a new unique identifier.""" + self._last_identifier += 1 + return f"t_{self._last_identifier}" + + def buffer(self, frame: Frame) -> None: + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline(f"{frame.buffer} = []") + + def return_buffer_contents( + self, frame: Frame, force_unescaped: bool = False + ) -> None: + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline(f"return Markup(concat({frame.buffer}))") + self.outdent() + self.writeline("else:") + self.indent() + self.writeline(f"return concat({frame.buffer})") + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline(f"return Markup(concat({frame.buffer}))") + return + self.writeline(f"return concat({frame.buffer})") + + def indent(self) -> None: + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step: int = 1) -> None: + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None: + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline(f"{frame.buffer}.append(", node) + + def end_write(self, frame: Frame) -> None: + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write( + self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None + ) -> None: + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x: str) -> None: + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline( + self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 + ) -> None: + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature( + self, + node: t.Union[nodes.Call, nodes.Filter, nodes.Test], + frame: Frame, + extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + ) -> None: + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = any( + is_python_keyword(t.cast(str, k)) + for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) + ) + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f", {key}={value}") + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write(f"{kwarg.key!r}: ") + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f"{key!r}: {value}, ") + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: + """Find all filter and test names used in the template and + assign them to variables in the compiled namespace. Checking + that the names are registered with the environment is done when + compiling the Filter and Test nodes. If the node is in an If or + CondExpr node, the check is done at runtime instead. + + .. versionchanged:: 3.0 + Filters and tests in If and CondExpr nodes are checked at + runtime instead of compile time. + """ + visitor = DependencyFinderVisitor() + + for node in nodes: + visitor.visit(node) + + for id_map, names, dependency in ( + (self.filters, visitor.filters, "filters"), + ( + self.tests, + visitor.tests, + "tests", + ), + ): + for name in sorted(names): + if name not in id_map: + id_map[name] = self.temporary_identifier() + + # add check during runtime that dependencies used inside of executed + # blocks are defined, as this step may be skipped during compile time + self.writeline("try:") + self.indent() + self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") + self.outdent() + self.writeline("except KeyError:") + self.indent() + self.writeline("@internalcode") + self.writeline(f"def {id_map[name]}(*unused):") + self.indent() + self.writeline( + f'raise TemplateRuntimeError("No {dependency[:-1]}' + f' named {name!r} found.")' + ) + self.outdent() + self.outdent() + + def enter_frame(self, frame: Frame) -> None: + undefs = [] + for target, (action, param) in frame.symbols.loads.items(): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") + elif action == VAR_LOAD_ALIAS: + self.writeline(f"{target} = {param}") + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: + if not with_python_scope: + undefs = [] + for target in frame.symbols.loads: + undefs.append(target) + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: + return async_value if self.environment.is_async else sync_value + + def func(self, name: str) -> str: + return f"{self.choose_async()}def {name}" + + def macro_body( + self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame + ) -> t.Tuple[Frame, MacroRef]: + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline(f"{self.func('macro')}({', '.join(args)}):", node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline(f"if {ref} is missing:") + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + f'{ref} = undefined("parameter {arg.name!r} was not provided",' + f" name={arg.name!r})" + ) + else: + self.writeline(f"{ref} = ") + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + f"Macro(environment, macro, {name!r}, ({arg_tuple})," + f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," + f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" + ) + + def position(self, node: nodes.Node) -> str: + """Return a human readable position for the node.""" + rv = f"line {node.lineno}" + if self.name is not None: + rv = f"{rv} in {self.name!r}" + return rv + + def dump_local_context(self, frame: Frame) -> str: + items_kv = ", ".join( + f"{name!r}: {target}" + for name, target in frame.symbols.dump_stores().items() + ) + return f"{{{items_kv}}}" + + def write_commons(self) -> None: + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + self.writeline("concat = environment.concat") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame: Frame) -> None: + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self) -> None: + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target: str) -> None: + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target: str) -> None: + self._context_reference_stack.append(target) + + def pop_context_reference(self) -> None: + self._context_reference_stack.pop() + + def get_context_ref(self) -> str: + return self._context_reference_stack[-1] + + def get_resolve_func(self) -> str: + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return f"{target}.resolve" + + def derive_context(self, frame: Frame) -> str: + return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" + + def parameter_is_undeclared(self, target: str) -> bool: + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self) -> None: + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame: Frame) -> None: + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if ( + not frame.block_frame + and not frame.loop_frame + and not frame.toplevel + or not vars + ): + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + if frame.loop_frame: + self.writeline(f"_loop_vars[{name!r}] = {ref}") + return + if frame.block_frame: + self.writeline(f"_block_vars[{name!r}] = {ref}") + return + self.writeline(f"context.vars[{name!r}] = {ref}") + else: + if frame.loop_frame: + self.writeline("_loop_vars.update({") + elif frame.block_frame: + self.writeline("_block_vars.update({") + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(vars): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write(f"{name!r}: {ref}") + self.write("})") + if not frame.block_frame and not frame.loop_frame and public_names: + if len(public_names) == 1: + self.writeline(f"context.exported_vars.add({public_names[0]!r})") + else: + names_str = ", ".join(map(repr, public_names)) + self.writeline(f"context.exported_vars.update(({names_str}))") + + # -- Statement Visitors + + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> None: + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import async_exported + from .runtime import exported + + if self.environment.is_async: + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = "" if self.defer_init else ", environment=environment" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail(f"block {block.name!r} defined twice", block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline(f"from {module} import {obj} as {alias}") + else: + self.writeline(f"import {imp} as {alias}") + + # add the load name + self.writeline(f"name = {self.name!r}") + + # generate the root render function. + self.writeline( + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline( + "async for event in parent_template.root_render_func(context):" + ) + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in self.blocks.items(): + self.writeline( + f"{self.func('block_' + name)}(context, missing=missing{envenv}):", + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + block_frame.block_frame = True + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline(f"{ref} = context.super({name!r}, block_{name})") + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.writeline("_block_vars = {}") + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) + self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) + debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) + self.writeline(f"debug_info = {debug_kv_str!r}") + + def visit_Block(self, node: nodes.Block, frame: Frame) -> None: + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if node.required: + self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) + self.indent() + self.writeline( + f'raise TemplateRuntimeError("Required block {node.name!r} not found")', + node, + ) + self.outdent() + + if not self.environment.is_async and frame.buffer is None: + self.writeline( + f"yield from context.blocks[{node.name!r}][0]({context})", node + ) + else: + self.writeline( + f"{self.choose_async()}for event in" + f" context.blocks[{node.name!r}][0]({context}):", + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + + self.outdent(level) + + def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline('raise TemplateRuntimeError("extended multiple times")') + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + self.writeline("for name, parent_block in parent_template.blocks.items():") + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node: nodes.Include, frame: Frame) -> None: + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, str): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline(f"template = environment.{func_name}(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + skip_event_yield = False + if node.with_context: + self.writeline( + f"{self.choose_async()}for event in template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)})):" + ) + elif self.environment.is_async: + self.writeline( + "for event in (await template._get_default_module_async())" + "._body_stream:" + ) + else: + self.writeline("yield from template._get_default_module()._body_stream") + skip_event_yield = True + + if not skip_event_yield: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.ignore_missing: + self.outdent() + + def _import_common( + self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame + ) -> None: + self.write(f"{self.choose_async('await ')}environment.get_template(") + self.visit(node.template, frame) + self.write(f", {self.name!r}).") + + if node.with_context: + f_name = f"make_module{self.choose_async('_async')}" + self.write( + f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})" + ) + else: + self.write(f"_get_default_module{self.choose_async('_async')}(context)") + + def visit_Import(self, node: nodes.Import, frame: Frame) -> None: + """Visit regular imports.""" + self.writeline(f"{frame.symbols.ref(node.target)} = ", node) + if frame.toplevel: + self.write(f"context.vars[{node.target!r}] = ") + + self._import_common(node, frame) + + if frame.toplevel and not node.target.startswith("_"): + self.writeline(f"context.exported_vars.discard({node.target!r})") + + def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: + """Visit named imports.""" + self.newline(node) + self.write("included_template = ") + self._import_common(node, frame) + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + f"{frame.symbols.ref(alias)} =" + f" getattr(included_template, {name!r}, missing)" + ) + self.writeline(f"if {frame.symbols.ref(alias)} is missing:") + self.indent() + message = ( + "the template {included_template.__name__!r}" + f" (imported on {self.position(node)})" + f" does not export the requested name {name!r}" + ) + self.writeline( + f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") + else: + names_kv = ", ".join( + f"{name!r}: {frame.symbols.ref(name)}" for name in var_names + ) + self.writeline(f"context.vars.update({{{names_kv}}})") + if discarded_names: + if len(discarded_names) == 1: + self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") + else: + names_str = ", ".join(map(repr, discarded_names)) + self.writeline( + f"context.exported_vars.difference_update(({names_str}))" + ) + + def visit_For(self, node: nodes.For, frame: Frame) -> None: + loop_frame = frame.inner() + loop_frame.loop_frame = True + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body if the body is a scoped block. + extended_loop = ( + node.recursive + or "loop" + in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) + or any(block.scoped for block in node.find_all(nodes.Block)) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.choose_async("async for ", "for ")) + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.choose_async("auto_aiter(fiter)", "fiter")) + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline(f"{loop_ref} = missing") + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline(f"{iteration_indicator} = 1") + + self.writeline(self.choose_async("async for ", "for "), node) + self.visit(node.target, loop_frame) + if extended_loop: + self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") + else: + self.write(" in ") + + if node.test: + self.write(f"{loop_filter_func}(") + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(", undefined):" if extended_loop else ":") + + self.indent() + self.enter_frame(loop_frame) + + self.writeline("_loop_vars = {}") + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline(f"{iteration_indicator} = 0") + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline(f"if {iteration_indicator}:") + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + self.write(f"{self.choose_async('await ')}loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + # at the end of the iteration, clear any assignments made in the + # loop from the top level + if self._assign_stack: + self._assign_stack[-1].difference_update(loop_frame.symbols.stores) + + def visit_If(self, node: nodes.If, frame: Frame) -> None: + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write(f"context.exported_vars.add({node.name!r})") + self.writeline(f"context.vars[{node.name!r}] = ") + self.write(f"{frame.symbols.ref(node.name)} = ") + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node: nodes.With, frame: Frame) -> None: + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in zip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: + self.newline(node) + self.visit(node.node, frame) + + class _FinalizeInfo(t.NamedTuple): + const: t.Optional[t.Callable[..., str]] + src: t.Optional[str] + + @staticmethod + def _default_finalize(value: t.Any) -> t.Any: + """The default finalize function if the environment isn't + configured with one. Or, if the environment has one, this is + called on that function's output for constants. + """ + return str(value) + + _finalize: t.Optional[_FinalizeInfo] = None + + def _make_finalize(self) -> _FinalizeInfo: + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize: t.Optional[t.Callable[..., t.Any]] + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(env_finalize) # type: ignore + ) + finalize = None + + if pass_arg is None: + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(value)) + + else: + src = f"{src}{pass_arg}, " + + if pass_arg == "environment": + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> str: + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return str(const) + + return finalize.const(const) # type: ignore + + def _output_child_pre( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else str)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("str(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node: nodes.Output, frame: Frame) -> None: + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline(f"{frame.buffer}.append(") + else: + self.writeline(f"{frame.buffer}.extend((") + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: + self.push_assign_tracking() + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write(f"concat({block_frame.buffer})") + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node: nodes.Name, frame: Frame) -> None: + if node.ctx == "store" and ( + frame.toplevel or frame.loop_frame or frame.block_frame + ): + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" + ) + return + + self.write(ref) + + def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: + # NSRefs can only be used to store values; since they use the normal + # `foo.bar` notation they will be parsed as a normal attribute access + # when used anywhere but in a `set` context + ref = frame.symbols.ref(node.name) + self.writeline(f"if not isinstance({ref}, Namespace):") + self.indent() + self.writeline( + "raise TemplateRuntimeError" + '("cannot assign attribute on non-namespace object")' + ) + self.outdent() + self.writeline(f"{ref}[{node.attr!r}]") + + def visit_Const(self, node: nodes.Const, frame: Frame) -> None: + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" + ) + + def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(",)" if idx == 0 else ")") + + def visit_List(self, node: nodes.List, frame: Frame) -> None: + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + visit_Add = _make_binop("+") + visit_Sub = _make_binop("-") + visit_Mul = _make_binop("*") + visit_Div = _make_binop("/") + visit_FloorDiv = _make_binop("//") + visit_Pow = _make_binop("**") + visit_Mod = _make_binop("%") + visit_And = _make_binop("and") + visit_Or = _make_binop("or") + visit_Pos = _make_unop("+") + visit_Neg = _make_unop("-") + visit_Not = _make_unop("not ") + + @optimizeconst + def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: + if frame.eval_ctx.volatile: + func_name = "(markup_join if context.eval_ctx.volatile else str_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "str_join" + self.write(f"{func_name}((") + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: + self.write(f" {operators[node.op]} ") + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(f", {node.attr!r})") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @contextmanager + def _filter_test_common( + self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool + ) -> t.Iterator[None]: + if self.environment.is_async: + self.write("(await auto_await(") + + if is_filter: + self.write(f"{self.filters[node.name]}(") + func = self.environment.filters.get(node.name) + else: + self.write(f"{self.tests[node.name]}(") + func = self.environment.tests.get(node.name) + + # When inside an If or CondExpr frame, allow the filter to be + # undefined at compile time and only raise an error if it's + # actually called at runtime. See pull_dependencies. + if func is None and not frame.soft_frame: + type_name = "filter" if is_filter else "test" + self.fail(f"No {type_name} named {node.name!r}.", node.lineno) + + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(func) # type: ignore + ) + + if pass_arg is not None: + self.write(f"{pass_arg}, ") + + # Back to the visitor function to handle visiting the target of + # the filter or test. + yield + + self.signature(node, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: + with self._filter_test_common(node, frame, True): + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + f"(Markup(concat({frame.buffer}))" + f" if context.eval_ctx.autoescape else concat({frame.buffer}))" + ) + elif frame.eval_ctx.autoescape: + self.write(f"Markup(concat({frame.buffer}))") + else: + self.write(f"concat({frame.buffer})") + + @optimizeconst + def visit_Test(self, node: nodes.Test, frame: Frame) -> None: + with self._filter_test_common(node, frame, False): + self.visit(node.node, frame) + + @optimizeconst + def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: + frame = frame.soft() + + def write_expr2() -> None: + if node.expr2 is not None: + self.visit(node.expr2, frame) + return + + self.write( + f'cond_expr_undefined("the inline if-expression on' + f" {self.position(node)} evaluated to false and no else" + f' section was defined.")' + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call( + self, node: nodes.Call, frame: Frame, forward_caller: bool = False + ) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = {"caller": "caller"} if forward_caller else None + loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} + block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} + if extra_kwargs: + extra_kwargs.update(loop_kwargs, **block_kwargs) + elif loop_kwargs or block_kwargs: + extra_kwargs = dict(loop_kwargs, **block_kwargs) + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write("))") + + def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape( + self, node: nodes.MarkSafeIfAutoescape, frame: Frame + ) -> None: + self.write("(Markup if context.eval_ctx.autoescape else identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute( + self, node: nodes.EnvironmentAttribute, frame: Frame + ) -> None: + self.write("environment." + node.name) + + def visit_ExtensionAttribute( + self, node: nodes.ExtensionAttribute, frame: Frame + ) -> None: + self.write(f"environment.extensions[{node.identifier!r}].{node.name}") + + def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: + self.write(node.name) + + def visit_ContextReference( + self, node: nodes.ContextReference, frame: Frame + ) -> None: + self.write("context") + + def visit_DerivedContextReference( + self, node: nodes.DerivedContextReference, frame: Frame + ) -> None: + self.write(self.derive_context(frame)) + + def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: + self.writeline("continue", node) + + def visit_Break(self, node: nodes.Break, frame: Frame) -> None: + self.writeline("break", node) + + def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: + ctx = self.temporary_identifier() + self.writeline(f"{ctx} = {self.derive_context(frame)}") + self.writeline(f"{ctx}.vars = ") + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier( + self, node: nodes.EvalContextModifier, frame: Frame + ) -> None: + for keyword in node.options: + self.writeline(f"context.eval_ctx.{keyword.key} = ") + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier( + self, node: nodes.ScopedEvalContextModifier, frame: Frame + ) -> None: + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/.venv/Lib/site-packages/jinja2/constants.py b/.venv/Lib/site-packages/jinja2/constants.py new file mode 100644 index 00000000..41a1c23b --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/jinja2/debug.py b/.venv/Lib/site-packages/jinja2/debug.py new file mode 100644 index 00000000..7ed7e929 --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/jinja2/defaults.py b/.venv/Lib/site-packages/jinja2/defaults.py new file mode 100644 index 00000000..638cad3d --- /dev/null +++ b/.venv/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/.venv/Lib/site-packages/jinja2/environment.py b/.venv/Lib/site-packages/jinja2/environment.py new file mode 100644 index 00000000..1d3be0be --- /dev/null +++ b/.venv/Lib/site-packages/jinja2/environment.py @@ -0,0 +1,1675 @@ +"""Classes for managing templates and their runtime and compile time +options. +""" + +import os +import typing +import typing as t +import weakref +from collections import ChainMap +from functools import lru_cache +from functools import partial +from functools import reduce +from types import CodeType + +from markupsafe import Markup + +from . import nodes +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import Lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import _PassArg +from .utils import concat +from .utils import consume +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + +# for direct template usage we have up to ten living environments +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + env = cls(*args) + env.shared = True + return env + + +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Return the cache class for the given size.""" + if size == 0: + return None + + if size < 0: + return {} + + return LRUCache(size) # type: ignore + + +def copy_cache( + cache: t.Optional[t.MutableMapping[t.Any, t.Any]], +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: # noqa E721 + return {} + + return LRUCache(cache.capacity) # type: ignore + + +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated extensions. + """ + result = {} + + for extension in extensions: + if isinstance(extension, str): + extension = t.cast(t.Type["Extension"], import_string(extension)) + + result[extension.identifier] = extension(environment) + + return result + + +def _environment_config_check(environment: "Environment") -> "Environment": + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "'undefined' must be a subclass of 'jinja2.Undefined'." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different." + assert environment.newline_sequence in { + "\r", + "\r\n", + "\n", + }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." + return environment + + +class Environment: + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which + allows using async functions and generators. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to: t.Optional["Environment"] = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class: t.Type["CodeGenerator"] = CodeGenerator + + concat = "".join + + #: the context class that is used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class: t.Type[Context] = Context + + template_class: t.Type["Template"] + + def __init__( + self, + block_start_string: str = BLOCK_START_STRING, + block_end_string: str = BLOCK_END_STRING, + variable_start_string: str = VARIABLE_START_STRING, + variable_end_string: str = VARIABLE_END_STRING, + comment_start_string: str = COMMENT_START_STRING, + comment_end_string: str = COMMENT_END_STRING, + line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, + line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, + trim_blocks: bool = TRIM_BLOCKS, + lstrip_blocks: bool = LSTRIP_BLOCKS, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, + keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), + optimized: bool = True, + undefined: t.Type[Undefined] = Undefined, + finalize: t.Optional[t.Callable[..., t.Any]] = None, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, + loader: t.Optional["BaseLoader"] = None, + cache_size: int = 400, + auto_reload: bool = True, + bytecode_cache: t.Optional["BytecodeCache"] = None, + enable_async: bool = False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined: t.Type[Undefined] = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.is_async = enable_async + _environment_config_check(self) + + def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes: t.Any) -> None: + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in attributes.items(): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string: str = missing, + block_end_string: str = missing, + variable_start_string: str = missing, + variable_end_string: str = missing, + comment_start_string: str = missing, + comment_end_string: str = missing, + line_statement_prefix: t.Optional[str] = missing, + line_comment_prefix: t.Optional[str] = missing, + trim_blocks: bool = missing, + lstrip_blocks: bool = missing, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, + keep_trailing_newline: bool = missing, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, + optimized: bool = missing, + undefined: t.Type[Undefined] = missing, + finalize: t.Optional[t.Callable[..., t.Any]] = missing, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, + loader: t.Optional["BaseLoader"] = missing, + cache_size: int = missing, + auto_reload: bool = missing, + bytecode_cache: t.Optional["BytecodeCache"] = missing, + enable_async: bool = False, + ) -> "Environment": + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + + .. versionchanged:: 3.1.2 + Added the ``newline_sequence``,, ``keep_trailing_newline``, + and ``enable_async`` parameters to match ``__init__``. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"], args["enable_async"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in args.items(): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in self.extensions.items(): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + if enable_async is not missing: + rv.is_async = enable_async + + return _environment_config_check(rv) + + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) + + def iter_extensions(self) -> t.Iterator["Extension"]: + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, str): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj: t.Any, attribute: str) -> t.Any: + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a string. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" + + func = env_map.get(name) # type: ignore + + if func is None: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: + if context is None: + raise TemplateRuntimeError( + f"Attempted to invoke a context {type_name} without context." + ) + + args.insert(0, context) + elif pass_arg is _PassArg.eval_context: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if the filter is running from an + environment in async mode and the filter supports async + execution. It's your responsibility to await this if needed. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) + + @internalcode + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, filename).parse() + + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = str(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + str(source), + ) + + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) # type: ignore + + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + + return stream + + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( # type: ignore + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source: str, filename: str) -> CodeType: + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @typing.overload + def compile( # type: ignore + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[False]" = False, + defer_init: bool = False, + ) -> CodeType: ... + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[True]" = ..., + defer_init: bool = False, + ) -> str: ... + + @internalcode + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: bool = False, + defer_init: bool = False, + ) -> t.Union[str, CodeType]: + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, str): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "