From eab0a374cadae815df8d39a9b62a23c2ab860254 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 27 Jun 2025 11:09:39 +0200 Subject: [PATCH] Entferne .venv aus dem Repository und trage es in .gitignore ein --- .gitignore | 1 + .../typing_extensions.cpython-312.pyc | Bin 162089 -> 0 bytes .../beautifulsoup4-4.13.4.dist-info/INSTALLER | 1 - .../beautifulsoup4-4.13.4.dist-info/METADATA | 123 - .../beautifulsoup4-4.13.4.dist-info/RECORD | 90 - .../beautifulsoup4-4.13.4.dist-info/REQUESTED | 0 .../beautifulsoup4-4.13.4.dist-info/WHEEL | 4 - .../licenses/AUTHORS | 49 - .../licenses/LICENSE | 31 - .venv/Lib/site-packages/bs4/__init__.py | 1170 --- .../bs4/__pycache__/__init__.cpython-312.pyc | Bin 39622 -> 0 bytes .../__pycache__/_deprecation.cpython-312.pyc | Bin 3750 -> 0 bytes .../bs4/__pycache__/_typing.cpython-312.pyc | Bin 3552 -> 0 bytes .../bs4/__pycache__/_warnings.cpython-312.pyc | Bin 5603 -> 0 bytes .../bs4/__pycache__/css.cpython-312.pyc | Bin 14429 -> 0 bytes .../bs4/__pycache__/dammit.cpython-312.pyc | Bin 46441 -> 0 bytes .../bs4/__pycache__/diagnose.cpython-312.pyc | Bin 12622 -> 0 bytes .../bs4/__pycache__/element.cpython-312.pyc | Bin 107895 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 1766 -> 0 bytes .../bs4/__pycache__/filter.cpython-312.pyc | Bin 28583 -> 0 bytes .../bs4/__pycache__/formatter.cpython-312.pyc | Bin 10534 -> 0 bytes .venv/Lib/site-packages/bs4/_deprecation.py | 80 - .venv/Lib/site-packages/bs4/_typing.py | 196 - .venv/Lib/site-packages/bs4/_warnings.py | 98 - .../Lib/site-packages/bs4/builder/__init__.py | 848 -- .../__pycache__/__init__.cpython-312.pyc | Bin 27448 -> 0 bytes .../__pycache__/_html5lib.cpython-312.pyc | Bin 23119 -> 0 bytes .../__pycache__/_htmlparser.cpython-312.pyc | Bin 14625 -> 0 bytes .../builder/__pycache__/_lxml.cpython-312.pyc | Bin 18452 -> 0 bytes .../site-packages/bs4/builder/_html5lib.py | 594 -- .../site-packages/bs4/builder/_htmlparser.py | 474 - .venv/Lib/site-packages/bs4/builder/_lxml.py | 491 - .venv/Lib/site-packages/bs4/css.py | 338 - .venv/Lib/site-packages/bs4/dammit.py | 1408 --- .venv/Lib/site-packages/bs4/diagnose.py | 268 - .venv/Lib/site-packages/bs4/element.py | 2894 ------ .venv/Lib/site-packages/bs4/exceptions.py | 28 - .venv/Lib/site-packages/bs4/filter.py | 759 -- .venv/Lib/site-packages/bs4/formatter.py | 276 - .venv/Lib/site-packages/bs4/py.typed | 0 .venv/Lib/site-packages/bs4/tests/__init__.py | 1318 --- .../__pycache__/__init__.cpython-312.pyc | Bin 68224 -> 0 bytes .../__pycache__/test_builder.cpython-312.pyc | Bin 1566 -> 0 bytes .../test_builder_registry.cpython-312.pyc | Bin 7588 -> 0 bytes .../__pycache__/test_css.cpython-312.pyc | Bin 28813 -> 0 bytes .../__pycache__/test_dammit.cpython-312.pyc | Bin 19774 -> 0 bytes .../__pycache__/test_element.cpython-312.pyc | Bin 6030 -> 0 bytes .../__pycache__/test_filter.cpython-312.pyc | Bin 32562 -> 0 bytes .../test_formatter.cpython-312.pyc | Bin 7785 -> 0 bytes .../__pycache__/test_fuzz.cpython-312.pyc | Bin 7036 -> 0 bytes .../__pycache__/test_html5lib.cpython-312.pyc | Bin 11948 -> 0 bytes .../test_htmlparser.cpython-312.pyc | Bin 7270 -> 0 bytes .../__pycache__/test_lxml.cpython-312.pyc | Bin 8096 -> 0 bytes .../test_navigablestring.cpython-312.pyc | Bin 8524 -> 0 bytes .../test_pageelement.cpython-312.pyc | Bin 22889 -> 0 bytes .../__pycache__/test_soup.cpython-312.pyc | Bin 31355 -> 0 bytes .../__pycache__/test_tag.cpython-312.pyc | Bin 14118 -> 0 bytes .../__pycache__/test_tree.cpython-312.pyc | Bin 93764 -> 0 bytes ...mized-bs4_fuzzer-4670634698080256.testcase | 1 - ...mized-bs4_fuzzer-4818336571064320.testcase | 1 - ...mized-bs4_fuzzer-4999465949331456.testcase | 1 - ...mized-bs4_fuzzer-5000587759190016.testcase | Bin 15347 -> 0 bytes ...mized-bs4_fuzzer-5167584867909632.testcase | Bin 19469 -> 0 bytes ...mized-bs4_fuzzer-5270998950477824.testcase | Bin 12 -> 0 bytes ...mized-bs4_fuzzer-5375146639360000.testcase | 1 - ...mized-bs4_fuzzer-5492400320282624.testcase | Bin 11502 -> 0 bytes ...mized-bs4_fuzzer-5703933063462912.testcase | 2 - ...mized-bs4_fuzzer-5843991618256896.testcase | 1 - ...mized-bs4_fuzzer-5984173902397440.testcase | Bin 51495 -> 0 bytes ...mized-bs4_fuzzer-6124268085182464.testcase | 1 - ...mized-bs4_fuzzer-6241471367348224.testcase | 1 - ...mized-bs4_fuzzer-6306874195312640.testcase | 1 - ...mized-bs4_fuzzer-6450958476902400.testcase | Bin 3546 -> 0 bytes ...mized-bs4_fuzzer-6600557255327744.testcase | Bin 124 -> 0 bytes ...0c8ed8bcd0785b67000fcd5dea1d33f08.testcase | Bin 2607 -> 0 bytes ...a2b26f13537b68d3794b0478a4090ee4a.testcase | Bin 103 -> 0 bytes .../site-packages/bs4/tests/test_builder.py | 28 - .../bs4/tests/test_builder_registry.py | 139 - .venv/Lib/site-packages/bs4/tests/test_css.py | 536 - .../site-packages/bs4/tests/test_dammit.py | 433 - .../site-packages/bs4/tests/test_element.py | 138 - .../site-packages/bs4/tests/test_filter.py | 683 -- .../site-packages/bs4/tests/test_formatter.py | 170 - .../Lib/site-packages/bs4/tests/test_fuzz.py | 181 - .../site-packages/bs4/tests/test_html5lib.py | 264 - .../bs4/tests/test_htmlparser.py | 161 - .../Lib/site-packages/bs4/tests/test_lxml.py | 196 - .../bs4/tests/test_navigablestring.py | 155 - .../bs4/tests/test_pageelement.py | 437 - .../Lib/site-packages/bs4/tests/test_soup.py | 602 -- .venv/Lib/site-packages/bs4/tests/test_tag.py | 241 - .../Lib/site-packages/bs4/tests/test_tree.py | 1456 --- .../certifi-2025.6.15.dist-info/INSTALLER | 1 - .../certifi-2025.6.15.dist-info/METADATA | 77 - .../certifi-2025.6.15.dist-info/RECORD | 14 - .../certifi-2025.6.15.dist-info/WHEEL | 5 - .../licenses/LICENSE | 20 - .../certifi-2025.6.15.dist-info/top_level.txt | 1 - .venv/Lib/site-packages/certifi/__init__.py | 4 - .venv/Lib/site-packages/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-312.pyc | Bin 313 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 628 -> 0 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 2060 -> 0 bytes .venv/Lib/site-packages/certifi/cacert.pem | 4635 --------- .venv/Lib/site-packages/certifi/core.py | 83 - .venv/Lib/site-packages/certifi/py.typed | 0 .../INSTALLER | 1 - .../METADATA | 731 -- .../charset_normalizer-3.4.2.dist-info/RECORD | 35 - .../charset_normalizer-3.4.2.dist-info/WHEEL | 5 - .../entry_points.txt | 2 - .../licenses/LICENSE | 21 - .../top_level.txt | 1 - .../charset_normalizer/__init__.py | 48 - .../charset_normalizer/__main__.py | 6 - .../__pycache__/__init__.cpython-312.pyc | Bin 1779 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 354 -> 0 bytes .../__pycache__/api.cpython-312.pyc | Bin 18140 -> 0 bytes .../__pycache__/cd.cpython-312.pyc | Bin 13241 -> 0 bytes .../__pycache__/constant.cpython-312.pyc | Bin 40809 -> 0 bytes .../__pycache__/legacy.cpython-312.pyc | Bin 2779 -> 0 bytes .../__pycache__/md.cpython-312.pyc | Bin 24335 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 17122 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 13709 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 381 -> 0 bytes .../site-packages/charset_normalizer/api.py | 668 -- .../site-packages/charset_normalizer/cd.py | 395 - .../charset_normalizer/cli/__init__.py | 8 - .../charset_normalizer/cli/__main__.py | 381 - .../cli/__pycache__/__init__.cpython-312.pyc | Bin 342 -> 0 bytes .../cli/__pycache__/__main__.cpython-312.pyc | Bin 14392 -> 0 bytes .../charset_normalizer/constant.py | 2015 ---- .../charset_normalizer/legacy.py | 64 - .../charset_normalizer/md.cp312-win_amd64.pyd | Bin 10752 -> 0 bytes .../site-packages/charset_normalizer/md.py | 635 -- .../md__mypyc.cp312-win_amd64.pyd | Bin 125952 -> 0 bytes .../charset_normalizer/models.py | 360 - .../site-packages/charset_normalizer/py.typed | 0 .../site-packages/charset_normalizer/utils.py | 414 - .../charset_normalizer/version.py | 8 - .../idna-3.10.dist-info/INSTALLER | 1 - .../idna-3.10.dist-info/LICENSE.md | 31 - .../idna-3.10.dist-info/METADATA | 250 - .../site-packages/idna-3.10.dist-info/RECORD | 22 - .../site-packages/idna-3.10.dist-info/WHEEL | 4 - .venv/Lib/site-packages/idna/__init__.py | 45 - .../idna/__pycache__/__init__.cpython-312.pyc | Bin 881 -> 0 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 4971 -> 0 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 885 -> 0 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 16116 -> 0 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 99471 -> 0 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 2628 -> 0 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 212 -> 0 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 158841 -> 0 bytes .venv/Lib/site-packages/idna/codec.py | 122 - .venv/Lib/site-packages/idna/compat.py | 15 - .venv/Lib/site-packages/idna/core.py | 437 - .venv/Lib/site-packages/idna/idnadata.py | 4243 -------- .venv/Lib/site-packages/idna/intranges.py | 57 - .venv/Lib/site-packages/idna/package_data.py | 1 - .venv/Lib/site-packages/idna/py.typed | 0 .venv/Lib/site-packages/idna/uts46data.py | 8681 ----------------- .../pip-25.0.1.dist-info/AUTHORS.txt | 806 -- .../pip-25.0.1.dist-info/INSTALLER | 1 - .../pip-25.0.1.dist-info/LICENSE.txt | 20 - .../pip-25.0.1.dist-info/METADATA | 90 - .../site-packages/pip-25.0.1.dist-info/RECORD | 854 -- .../pip-25.0.1.dist-info/REQUESTED | 0 .../site-packages/pip-25.0.1.dist-info/WHEEL | 5 - .../pip-25.0.1.dist-info/entry_points.txt | 3 - .../pip-25.0.1.dist-info/top_level.txt | 1 - .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 693 -> 0 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 847 -> 0 bytes .../__pip-runner__.cpython-312.pyc | Bin 2211 -> 0 bytes .../site-packages/pip/_internal/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 793 -> 0 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 14777 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 12673 -> 0 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 17637 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 36851 -> 0 bytes .../__pycache__/main.cpython-312.pyc | Bin 676 -> 0 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 5124 -> 0 bytes .../self_outdated_check.cpython-312.pyc | Bin 10409 -> 0 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 13621 -> 0 bytes .../site-packages/pip/_internal/build_env.py | 322 - .../Lib/site-packages/pip/_internal/cache.py | 290 - .../pip/_internal/cli/__init__.py | 4 - .../cli/__pycache__/__init__.cpython-312.pyc | Bin 284 -> 0 bytes .../autocompletion.cpython-312.pyc | Bin 8612 -> 0 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 10514 -> 0 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 30407 -> 0 bytes .../command_context.cpython-312.pyc | Bin 1780 -> 0 bytes .../__pycache__/index_command.cpython-312.pyc | Bin 7187 -> 0 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 2306 -> 0 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 4912 -> 0 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 15046 -> 0 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 3858 -> 0 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 12247 -> 0 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 7839 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 381 -> 0 bytes .../pip/_internal/cli/autocompletion.py | 176 - .../pip/_internal/cli/base_command.py | 240 - .../pip/_internal/cli/cmdoptions.py | 1075 -- .../pip/_internal/cli/command_context.py | 27 - .../pip/_internal/cli/index_command.py | 171 - .../site-packages/pip/_internal/cli/main.py | 80 - .../pip/_internal/cli/main_parser.py | 134 - .../site-packages/pip/_internal/cli/parser.py | 294 - .../pip/_internal/cli/progress_bars.py | 94 - .../pip/_internal/cli/req_command.py | 329 - .../pip/_internal/cli/spinners.py | 159 - .../pip/_internal/cli/status_codes.py | 6 - .../pip/_internal/commands/__init__.py | 132 - .../__pycache__/__init__.cpython-312.pyc | Bin 4008 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 9934 -> 0 bytes .../__pycache__/check.cpython-312.pyc | Bin 2598 -> 0 bytes .../__pycache__/completion.cpython-312.pyc | Bin 5199 -> 0 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 13169 -> 0 bytes .../__pycache__/debug.cpython-312.pyc | Bin 10074 -> 0 bytes .../__pycache__/download.cpython-312.pyc | Bin 7509 -> 0 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 4391 -> 0 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 2974 -> 0 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 1679 -> 0 bytes .../__pycache__/index.cpython-312.pyc | Bin 6677 -> 0 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 3986 -> 0 bytes .../__pycache__/install.cpython-312.pyc | Bin 29098 -> 0 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 15763 -> 0 bytes .../__pycache__/search.cpython-312.pyc | Bin 7524 -> 0 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 10943 -> 0 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 4715 -> 0 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 8871 -> 0 bytes .../pip/_internal/commands/cache.py | 228 - .../pip/_internal/commands/check.py | 67 - .../pip/_internal/commands/completion.py | 130 - .../pip/_internal/commands/configuration.py | 280 - .../pip/_internal/commands/debug.py | 201 - .../pip/_internal/commands/download.py | 146 - .../pip/_internal/commands/freeze.py | 109 - .../pip/_internal/commands/hash.py | 59 - .../pip/_internal/commands/help.py | 41 - .../pip/_internal/commands/index.py | 139 - .../pip/_internal/commands/inspect.py | 92 - .../pip/_internal/commands/install.py | 784 -- .../pip/_internal/commands/list.py | 375 - .../pip/_internal/commands/search.py | 172 - .../pip/_internal/commands/show.py | 224 - .../pip/_internal/commands/uninstall.py | 114 - .../pip/_internal/commands/wheel.py | 182 - .../pip/_internal/configuration.py | 383 - .../pip/_internal/distributions/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 947 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 2899 -> 0 bytes .../__pycache__/installed.cpython-312.pyc | Bin 1706 -> 0 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 8433 -> 0 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 2287 -> 0 bytes .../pip/_internal/distributions/base.py | 53 - .../pip/_internal/distributions/installed.py | 29 - .../pip/_internal/distributions/sdist.py | 158 - .../pip/_internal/distributions/wheel.py | 42 - .../site-packages/pip/_internal/exceptions.py | 809 -- .../pip/_internal/index/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 238 -> 0 bytes .../__pycache__/collector.cpython-312.pyc | Bin 21623 -> 0 bytes .../package_finder.cpython-312.pyc | Bin 41371 -> 0 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 12530 -> 0 bytes .../pip/_internal/index/collector.py | 494 - .../pip/_internal/index/package_finder.py | 1029 -- .../pip/_internal/index/sources.py | 284 - .../pip/_internal/locations/__init__.py | 456 - .../__pycache__/__init__.cpython-312.pyc | Bin 16446 -> 0 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 6797 -> 0 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 8034 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 3787 -> 0 bytes .../pip/_internal/locations/_distutils.py | 172 - .../pip/_internal/locations/_sysconfig.py | 214 - .../pip/_internal/locations/base.py | 81 - .venv/Lib/site-packages/pip/_internal/main.py | 12 - .../pip/_internal/metadata/__init__.py | 128 - .../__pycache__/__init__.cpython-312.pyc | Bin 5873 -> 0 bytes .../__pycache__/_json.cpython-312.pyc | Bin 2973 -> 0 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 35204 -> 0 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 16090 -> 0 bytes .../pip/_internal/metadata/_json.py | 86 - .../pip/_internal/metadata/base.py | 688 -- .../_internal/metadata/importlib/__init__.py | 6 - .../__pycache__/__init__.cpython-312.pyc | Bin 364 -> 0 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 4497 -> 0 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 12885 -> 0 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 11085 -> 0 bytes .../_internal/metadata/importlib/_compat.py | 85 - .../_internal/metadata/importlib/_dists.py | 228 - .../pip/_internal/metadata/importlib/_envs.py | 189 - .../pip/_internal/metadata/pkg_resources.py | 301 - .../pip/_internal/models/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 272 -> 0 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 1610 -> 0 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 10850 -> 0 bytes .../format_control.cpython-312.pyc | Bin 4229 -> 0 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 1700 -> 0 bytes .../installation_report.cpython-312.pyc | Bin 2283 -> 0 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 26989 -> 0 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 1029 -> 0 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 4993 -> 0 bytes .../selection_prefs.cpython-312.pyc | Bin 1857 -> 0 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 4959 -> 0 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 6558 -> 0 bytes .../pip/_internal/models/candidate.py | 25 - .../pip/_internal/models/direct_url.py | 224 - .../pip/_internal/models/format_control.py | 78 - .../pip/_internal/models/index.py | 28 - .../_internal/models/installation_report.py | 56 - .../pip/_internal/models/link.py | 604 -- .../pip/_internal/models/scheme.py | 25 - .../pip/_internal/models/search_scope.py | 127 - .../pip/_internal/models/selection_prefs.py | 53 - .../pip/_internal/models/target_python.py | 121 - .../pip/_internal/models/wheel.py | 118 - .../pip/_internal/network/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 260 -> 0 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 22105 -> 0 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 7052 -> 0 bytes .../__pycache__/download.cpython-312.pyc | Bin 8485 -> 0 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 11613 -> 0 bytes .../__pycache__/session.cpython-312.pyc | Bin 18912 -> 0 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 2261 -> 0 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 2955 -> 0 bytes .../pip/_internal/network/auth.py | 566 -- .../pip/_internal/network/cache.py | 118 - .../pip/_internal/network/download.py | 187 - .../pip/_internal/network/lazy_wheel.py | 210 - .../pip/_internal/network/session.py | 523 - .../pip/_internal/network/utils.py | 98 - .../pip/_internal/network/xmlrpc.py | 62 - .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 203 -> 0 bytes .../__pycache__/check.cpython-312.pyc | Bin 7110 -> 0 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 10254 -> 0 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 25778 -> 0 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 209 -> 0 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 7673 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 1863 -> 0 bytes .../metadata_editable.cpython-312.pyc | Bin 1917 -> 0 bytes .../metadata_legacy.cpython-312.pyc | Bin 3017 -> 0 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 1683 -> 0 bytes .../wheel_editable.cpython-312.pyc | Bin 2022 -> 0 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 3852 -> 0 bytes .../operations/build/build_tracker.py | 138 - .../_internal/operations/build/metadata.py | 39 - .../operations/build/metadata_editable.py | 42 - .../operations/build/metadata_legacy.py | 74 - .../pip/_internal/operations/build/wheel.py | 37 - .../operations/build/wheel_editable.py | 46 - .../operations/build/wheel_legacy.py | 102 - .../pip/_internal/operations/check.py | 181 - .../pip/_internal/operations/freeze.py | 256 - .../_internal/operations/install/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 272 -> 0 bytes .../editable_legacy.cpython-312.pyc | Bin 1804 -> 0 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 34109 -> 0 bytes .../operations/install/editable_legacy.py | 47 - .../pip/_internal/operations/install/wheel.py | 741 -- .../pip/_internal/operations/prepare.py | 732 -- .../site-packages/pip/_internal/pyproject.py | 185 - .../pip/_internal/req/__init__.py | 90 - .../req/__pycache__/__init__.cpython-312.pyc | Bin 3451 -> 0 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 21261 -> 0 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 24244 -> 0 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 38476 -> 0 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 5489 -> 0 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 32100 -> 0 bytes .../pip/_internal/req/constructors.py | 560 -- .../pip/_internal/req/req_file.py | 623 -- .../pip/_internal/req/req_install.py | 934 -- .../pip/_internal/req/req_set.py | 82 - .../pip/_internal/req/req_uninstall.py | 633 -- .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 203 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 1191 -> 0 bytes .../pip/_internal/resolution/base.py | 20 - .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 210 -> 0 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 22585 -> 0 bytes .../_internal/resolution/legacy/resolver.py | 597 -- .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 214 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 8155 -> 0 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 29414 -> 0 bytes .../__pycache__/factory.cpython-312.pyc | Bin 32492 -> 0 bytes .../found_candidates.cpython-312.pyc | Bin 6799 -> 0 bytes .../__pycache__/provider.cpython-312.pyc | Bin 10529 -> 0 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 5046 -> 0 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 15362 -> 0 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 12320 -> 0 bytes .../_internal/resolution/resolvelib/base.py | 139 - .../resolution/resolvelib/candidates.py | 574 -- .../resolution/resolvelib/factory.py | 823 -- .../resolution/resolvelib/found_candidates.py | 174 - .../resolution/resolvelib/provider.py | 258 - .../resolution/resolvelib/reporter.py | 81 - .../resolution/resolvelib/requirements.py | 245 - .../resolution/resolvelib/resolver.py | 317 - .../pip/_internal/self_outdated_check.py | 252 - .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 198 -> 0 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 4533 -> 0 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 1869 -> 0 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 2413 -> 0 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 2910 -> 0 bytes .../compatibility_tags.cpython-312.pyc | Bin 6353 -> 0 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 687 -> 0 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 4194 -> 0 bytes .../direct_url_helpers.cpython-312.pyc | Bin 3539 -> 0 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 3209 -> 0 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 3996 -> 0 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 7332 -> 0 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 1167 -> 0 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 2422 -> 0 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 7606 -> 0 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 13894 -> 0 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 33229 -> 0 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 2663 -> 0 bytes .../utils/__pycache__/retry.cpython-312.pyc | Bin 2111 -> 0 bytes .../setuptools_build.cpython-312.pyc | Bin 4553 -> 0 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 8642 -> 0 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 12027 -> 0 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 13501 -> 0 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 2080 -> 0 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 4469 -> 0 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 5906 -> 0 bytes .../pip/_internal/utils/_jaraco_text.py | 109 - .../site-packages/pip/_internal/utils/_log.py | 38 - .../pip/_internal/utils/appdirs.py | 52 - .../pip/_internal/utils/compat.py | 79 - .../pip/_internal/utils/compatibility_tags.py | 188 - .../pip/_internal/utils/datetime.py | 11 - .../pip/_internal/utils/deprecation.py | 124 - .../pip/_internal/utils/direct_url_helpers.py | 87 - .../pip/_internal/utils/egg_link.py | 80 - .../pip/_internal/utils/entrypoints.py | 84 - .../pip/_internal/utils/filesystem.py | 149 - .../pip/_internal/utils/filetypes.py | 27 - .../pip/_internal/utils/glibc.py | 101 - .../pip/_internal/utils/hashes.py | 147 - .../pip/_internal/utils/logging.py | 354 - .../site-packages/pip/_internal/utils/misc.py | 773 -- .../pip/_internal/utils/packaging.py | 58 - .../pip/_internal/utils/retry.py | 42 - .../pip/_internal/utils/setuptools_build.py | 146 - .../pip/_internal/utils/subprocess.py | 245 - .../pip/_internal/utils/temp_dir.py | 296 - .../pip/_internal/utils/unpacking.py | 337 - .../site-packages/pip/_internal/utils/urls.py | 55 - .../pip/_internal/utils/virtualenv.py | 104 - .../pip/_internal/utils/wheel.py | 134 - .../pip/_internal/vcs/__init__.py | 15 - .../vcs/__pycache__/__init__.cpython-312.pyc | Bin 537 -> 0 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 5058 -> 0 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 19023 -> 0 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 7611 -> 0 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 12530 -> 0 bytes .../versioncontrol.cpython-312.pyc | Bin 29003 -> 0 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 - .../site-packages/pip/_internal/vcs/git.py | 527 - .../pip/_internal/vcs/mercurial.py | 163 - .../pip/_internal/vcs/subversion.py | 324 - .../pip/_internal/vcs/versioncontrol.py | 688 -- .../pip/_internal/wheel_builder.py | 354 - .../Lib/site-packages/pip/_vendor/__init__.py | 116 - .../__pycache__/__init__.cpython-312.pyc | Bin 4556 -> 0 bytes .../typing_extensions.cpython-312.pyc | Bin 139458 -> 0 bytes .../pip/_vendor/cachecontrol/__init__.py | 29 - .../__pycache__/__init__.cpython-312.pyc | Bin 909 -> 0 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 2653 -> 0 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 6471 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 3794 -> 0 bytes .../__pycache__/controller.cpython-312.pyc | Bin 16231 -> 0 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 4354 -> 0 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 6704 -> 0 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 5268 -> 0 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 1681 -> 0 bytes .../pip/_vendor/cachecontrol/_cmd.py | 70 - .../pip/_vendor/cachecontrol/adapter.py | 161 - .../pip/_vendor/cachecontrol/cache.py | 75 - .../_vendor/cachecontrol/caches/__init__.py | 8 - .../__pycache__/__init__.cpython-312.pyc | Bin 442 -> 0 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 7751 -> 0 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 2740 -> 0 bytes .../_vendor/cachecontrol/caches/file_cache.py | 182 - .../cachecontrol/caches/redis_cache.py | 48 - .../pip/_vendor/cachecontrol/controller.py | 500 - .../pip/_vendor/cachecontrol/filewrapper.py | 119 - .../pip/_vendor/cachecontrol/heuristics.py | 157 - .../pip/_vendor/cachecontrol/py.typed | 0 .../pip/_vendor/cachecontrol/serialize.py | 146 - .../pip/_vendor/cachecontrol/wrapper.py | 43 - .../pip/_vendor/certifi/__init__.py | 4 - .../pip/_vendor/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-312.pyc | Bin 325 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 652 -> 0 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 3218 -> 0 bytes .../pip/_vendor/certifi/cacert.pem | 4929 ---------- .../site-packages/pip/_vendor/certifi/core.py | 114 - .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/distlib/__init__.py | 33 - .../__pycache__/__init__.cpython-312.pyc | Bin 1276 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 45533 -> 0 bytes .../__pycache__/database.cpython-312.pyc | Bin 65588 -> 0 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 24323 -> 0 bytes .../__pycache__/locators.cpython-312.pyc | Bin 59868 -> 0 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 15083 -> 0 bytes .../__pycache__/markers.cpython-312.pyc | Bin 7661 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 41567 -> 0 bytes .../__pycache__/resources.cpython-312.pyc | Bin 17319 -> 0 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 19760 -> 0 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 88042 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 30351 -> 0 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 52552 -> 0 bytes .../pip/_vendor/distlib/compat.py | 1137 --- .../pip/_vendor/distlib/database.py | 1329 --- .../pip/_vendor/distlib/index.py | 508 - .../pip/_vendor/distlib/locators.py | 1295 --- .../pip/_vendor/distlib/manifest.py | 384 - .../pip/_vendor/distlib/markers.py | 162 - .../pip/_vendor/distlib/metadata.py | 1031 -- .../pip/_vendor/distlib/resources.py | 358 - .../pip/_vendor/distlib/scripts.py | 447 - .../site-packages/pip/_vendor/distlib/t32.exe | Bin 97792 -> 0 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 182784 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 108032 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1984 ---- .../pip/_vendor/distlib/version.py | 750 -- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 91648 -> 0 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 168448 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 101888 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 1100 --- .../pip/_vendor/distro/__init__.py | 54 - .../pip/_vendor/distro/__main__.py | 4 - .../__pycache__/__init__.cpython-312.pyc | Bin 967 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 299 -> 0 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 53799 -> 0 bytes .../pip/_vendor/distro/distro.py | 1403 --- .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 45 - .../idna/__pycache__/__init__.cpython-312.pyc | Bin 893 -> 0 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 4983 -> 0 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 897 -> 0 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 16128 -> 0 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 99483 -> 0 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 2640 -> 0 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 224 -> 0 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 158853 -> 0 bytes .../site-packages/pip/_vendor/idna/codec.py | 122 - .../site-packages/pip/_vendor/idna/compat.py | 15 - .../site-packages/pip/_vendor/idna/core.py | 437 - .../pip/_vendor/idna/idnadata.py | 4243 -------- .../pip/_vendor/idna/intranges.py | 57 - .../pip/_vendor/idna/package_data.py | 1 - .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 8681 ----------------- .../pip/_vendor/msgpack/__init__.py | 55 - .../__pycache__/__init__.cpython-312.pyc | Bin 1746 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 2032 -> 0 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 8300 -> 0 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 41497 -> 0 bytes .../pip/_vendor/msgpack/exceptions.py | 48 - .../site-packages/pip/_vendor/msgpack/ext.py | 170 - .../pip/_vendor/msgpack/fallback.py | 929 -- .../pip/_vendor/packaging/__init__.py | 15 - .../__pycache__/__init__.cpython-312.pyc | Bin 565 -> 0 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 5030 -> 0 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 9718 -> 0 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 4561 -> 0 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 13992 -> 0 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 3248 -> 0 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 7922 -> 0 bytes .../__pycache__/markers.cpython-312.pyc | Bin 11381 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 27219 -> 0 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 4417 -> 0 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 39049 -> 0 bytes .../__pycache__/tags.cpython-312.pyc | Bin 23012 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 6642 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 20493 -> 0 bytes .../pip/_vendor/packaging/_elffile.py | 110 - .../pip/_vendor/packaging/_manylinux.py | 263 - .../pip/_vendor/packaging/_musllinux.py | 85 - .../pip/_vendor/packaging/_parser.py | 354 - .../pip/_vendor/packaging/_structures.py | 61 - .../pip/_vendor/packaging/_tokenizer.py | 194 - .../_vendor/packaging/licenses/__init__.py | 145 - .../__pycache__/__init__.cpython-312.pyc | Bin 4127 -> 0 bytes .../__pycache__/_spdx.cpython-312.pyc | Bin 47371 -> 0 bytes .../pip/_vendor/packaging/licenses/_spdx.py | 759 -- .../pip/_vendor/packaging/markers.py | 331 - .../pip/_vendor/packaging/metadata.py | 863 -- .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 91 - .../pip/_vendor/packaging/specifiers.py | 1020 -- .../pip/_vendor/packaging/tags.py | 617 -- .../pip/_vendor/packaging/utils.py | 163 - .../pip/_vendor/packaging/version.py | 582 -- .../pip/_vendor/pkg_resources/__init__.py | 3676 ------- .../__pycache__/__init__.cpython-312.pyc | Bin 161268 -> 0 bytes .../pip/_vendor/platformdirs/__init__.py | 631 -- .../pip/_vendor/platformdirs/__main__.py | 55 - .../__pycache__/__init__.cpython-312.pyc | Bin 19854 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 1955 -> 0 bytes .../__pycache__/android.cpython-312.pyc | Bin 10704 -> 0 bytes .../__pycache__/api.cpython-312.pyc | Bin 13311 -> 0 bytes .../__pycache__/macos.cpython-312.pyc | Bin 8831 -> 0 bytes .../__pycache__/unix.cpython-312.pyc | Bin 14697 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 604 -> 0 bytes .../__pycache__/windows.cpython-312.pyc | Bin 13681 -> 0 bytes .../pip/_vendor/platformdirs/android.py | 249 - .../pip/_vendor/platformdirs/api.py | 298 - .../pip/_vendor/platformdirs/macos.py | 144 - .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 269 - .../pip/_vendor/platformdirs/version.py | 16 - .../pip/_vendor/platformdirs/windows.py | 272 - .../pip/_vendor/pygments/__init__.py | 82 - .../pip/_vendor/pygments/__main__.py | 17 - .../__pycache__/__init__.cpython-312.pyc | Bin 3496 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 742 -> 0 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 26592 -> 0 bytes .../__pycache__/console.cpython-312.pyc | Bin 2636 -> 0 bytes .../__pycache__/filter.cpython-312.pyc | Bin 3229 -> 0 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 4728 -> 0 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 38369 -> 0 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 1567 -> 0 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 2616 -> 0 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 4085 -> 0 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 4764 -> 0 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 12106 -> 0 bytes .../__pycache__/style.cpython-312.pyc | Bin 6701 -> 0 bytes .../__pycache__/token.cpython-312.pyc | Bin 8197 -> 0 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 32980 -> 0 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 14077 -> 0 bytes .../pip/_vendor/pygments/cmdline.py | 668 -- .../pip/_vendor/pygments/console.py | 70 - .../pip/_vendor/pygments/filter.py | 70 - .../pip/_vendor/pygments/filters/__init__.py | 940 -- .../__pycache__/__init__.cpython-312.pyc | Bin 37919 -> 0 bytes .../pip/_vendor/pygments/formatter.py | 129 - .../_vendor/pygments/formatters/__init__.py | 157 - .../__pycache__/__init__.cpython-312.pyc | Bin 6910 -> 0 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 4223 -> 0 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 4230 -> 0 bytes .../__pycache__/groff.cpython-312.pyc | Bin 7301 -> 0 bytes .../__pycache__/html.cpython-312.pyc | Bin 41034 -> 0 bytes .../__pycache__/img.cpython-312.pyc | Bin 28556 -> 0 bytes .../__pycache__/irc.cpython-312.pyc | Bin 6063 -> 0 bytes .../__pycache__/latex.cpython-312.pyc | Bin 20133 -> 0 bytes .../__pycache__/other.cpython-312.pyc | Bin 6885 -> 0 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 2966 -> 0 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 13781 -> 0 bytes .../__pycache__/svg.cpython-312.pyc | Bin 9147 -> 0 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 5827 -> 0 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 15126 -> 0 bytes .../_vendor/pygments/formatters/_mapping.py | 23 - .../pip/_vendor/pygments/formatters/bbcode.py | 108 - .../pip/_vendor/pygments/formatters/groff.py | 170 - .../pip/_vendor/pygments/formatters/html.py | 987 -- .../pip/_vendor/pygments/formatters/img.py | 685 -- .../pip/_vendor/pygments/formatters/irc.py | 154 - .../pip/_vendor/pygments/formatters/latex.py | 518 - .../pip/_vendor/pygments/formatters/other.py | 160 - .../pygments/formatters/pangomarkup.py | 83 - .../pip/_vendor/pygments/formatters/rtf.py | 349 - .../pip/_vendor/pygments/formatters/svg.py | 185 - .../_vendor/pygments/formatters/terminal.py | 127 - .../pygments/formatters/terminal256.py | 338 - .../pip/_vendor/pygments/lexer.py | 963 -- .../pip/_vendor/pygments/lexers/__init__.py | 362 - .../__pycache__/__init__.cpython-312.pyc | Bin 14629 -> 0 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 68271 -> 0 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 42975 -> 0 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 589 -- .../pip/_vendor/pygments/lexers/python.py | 1198 --- .../pip/_vendor/pygments/modeline.py | 43 - .../pip/_vendor/pygments/plugin.py | 72 - .../pip/_vendor/pygments/regexopt.py | 91 - .../pip/_vendor/pygments/scanner.py | 104 - .../pip/_vendor/pygments/sphinxext.py | 247 - .../pip/_vendor/pygments/style.py | 203 - .../pip/_vendor/pygments/styles/__init__.py | 61 - .../__pycache__/__init__.cpython-312.pyc | Bin 2672 -> 0 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 3656 -> 0 bytes .../pip/_vendor/pygments/styles/_mapping.py | 54 - .../pip/_vendor/pygments/token.py | 214 - .../pip/_vendor/pygments/unistring.py | 153 - .../pip/_vendor/pygments/util.py | 324 - .../pip/_vendor/pyproject_hooks/__init__.py | 31 - .../__pycache__/__init__.cpython-312.pyc | Bin 755 -> 0 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 18054 -> 0 bytes .../pip/_vendor/pyproject_hooks/_impl.py | 410 - .../pyproject_hooks/_in_process/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 1084 -> 0 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 15322 -> 0 bytes .../_in_process/_in_process.py | 389 - .../pip/_vendor/pyproject_hooks/py.typed | 0 .../pip/_vendor/requests/__init__.py | 179 - .../__pycache__/__init__.cpython-312.pyc | Bin 5261 -> 0 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 592 -> 0 bytes .../_internal_utils.cpython-312.pyc | Bin 2032 -> 0 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 28439 -> 0 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 7199 -> 0 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 13929 -> 0 bytes .../__pycache__/certs.cpython-312.pyc | Bin 686 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 1685 -> 0 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 25206 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 7606 -> 0 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 4236 -> 0 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 1059 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 35436 -> 0 bytes .../__pycache__/packages.cpython-312.pyc | Bin 1274 -> 0 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 27854 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 6031 -> 0 bytes .../__pycache__/structures.cpython-312.pyc | Bin 5631 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 36374 -> 0 bytes .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 50 - .../pip/_vendor/requests/adapters.py | 719 -- .../site-packages/pip/_vendor/requests/api.py | 157 - .../pip/_vendor/requests/auth.py | 314 - .../pip/_vendor/requests/certs.py | 17 - .../pip/_vendor/requests/compat.py | 78 - .../pip/_vendor/requests/cookies.py | 561 -- .../pip/_vendor/requests/exceptions.py | 151 - .../pip/_vendor/requests/help.py | 127 - .../pip/_vendor/requests/hooks.py | 33 - .../pip/_vendor/requests/models.py | 1037 -- .../pip/_vendor/requests/packages.py | 25 - .../pip/_vendor/requests/sessions.py | 831 -- .../pip/_vendor/requests/status_codes.py | 128 - .../pip/_vendor/requests/structures.py | 99 - .../pip/_vendor/requests/utils.py | 1096 --- .../pip/_vendor/resolvelib/__init__.py | 26 - .../__pycache__/__init__.cpython-312.pyc | Bin 642 -> 0 bytes .../__pycache__/providers.cpython-312.pyc | Bin 6859 -> 0 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 2662 -> 0 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 25888 -> 0 bytes .../__pycache__/structs.cpython-312.pyc | Bin 10508 -> 0 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 208 -> 0 bytes .../collections_abc.cpython-312.pyc | Bin 428 -> 0 bytes .../resolvelib/compat/collections_abc.py | 6 - .../pip/_vendor/resolvelib/providers.py | 133 - .../pip/_vendor/resolvelib/py.typed | 0 .../pip/_vendor/resolvelib/reporters.py | 43 - .../pip/_vendor/resolvelib/resolvers.py | 547 -- .../pip/_vendor/resolvelib/structs.py | 170 - .../pip/_vendor/rich/__init__.py | 177 - .../pip/_vendor/rich/__main__.py | 273 - .../rich/__pycache__/__init__.cpython-312.pyc | Bin 7023 -> 0 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 10300 -> 0 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 7880 -> 0 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 205984 -> 0 bytes .../_emoji_replace.cpython-312.pyc | Bin 1737 -> 0 bytes .../_export_format.cpython-312.pyc | Bin 2357 -> 0 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 545 -> 0 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 863 -> 0 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 12030 -> 0 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 4155 -> 0 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 1878 -> 0 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 3637 -> 0 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 5168 -> 0 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 729 -> 0 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 6578 -> 0 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 13187 -> 0 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 973 -> 0 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 873 -> 0 bytes .../_win32_console.cpython-312.pyc | Bin 28819 -> 0 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 2498 -> 0 bytes .../_windows_renderer.cpython-312.pyc | Bin 3571 -> 0 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 3334 -> 0 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 1616 -> 0 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 12399 -> 0 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 9089 -> 0 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 4280 -> 0 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 11846 -> 0 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 5568 -> 0 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 26560 -> 0 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 1709 -> 0 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 8592 -> 0 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 114553 -> 0 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 2266 -> 0 bytes .../__pycache__/containers.cpython-312.pyc | Bin 9218 -> 0 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 10949 -> 0 bytes .../default_styles.cpython-312.pyc | Bin 10446 -> 0 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 1496 -> 0 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 4220 -> 0 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 1853 -> 0 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 3579 -> 0 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 3055 -> 0 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 9896 -> 0 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 6043 -> 0 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 5216 -> 0 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 20166 -> 0 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 19016 -> 0 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 4897 -> 0 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 14072 -> 0 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 9575 -> 0 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 6386 -> 0 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 6941 -> 0 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 1819 -> 0 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 5305 -> 0 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 12778 -> 0 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 40619 -> 0 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 75742 -> 0 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 10385 -> 0 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 16013 -> 0 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 1800 -> 0 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 575 -> 0 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 6621 -> 0 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 6576 -> 0 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 3833 -> 0 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 2487 -> 0 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 28545 -> 0 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 6098 -> 0 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 6069 -> 0 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 33484 -> 0 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 2147 -> 0 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 40192 -> 0 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 43891 -> 0 bytes .../terminal_theme.cpython-312.pyc | Bin 3356 -> 0 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 61218 -> 0 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 6335 -> 0 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 322 -> 0 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 32900 -> 0 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 11801 -> 0 bytes .../pip/_vendor/rich/_cell_widths.py | 454 - .../pip/_vendor/rich/_emoji_codes.py | 3610 ------- .../pip/_vendor/rich/_emoji_replace.py | 32 - .../pip/_vendor/rich/_export_format.py | 76 - .../pip/_vendor/rich/_extension.py | 10 - .../site-packages/pip/_vendor/rich/_fileno.py | 24 - .../pip/_vendor/rich/_inspect.py | 268 - .../pip/_vendor/rich/_log_render.py | 94 - .../site-packages/pip/_vendor/rich/_loop.py | 43 - .../pip/_vendor/rich/_null_file.py | 69 - .../pip/_vendor/rich/_palettes.py | 309 - .../site-packages/pip/_vendor/rich/_pick.py | 17 - .../site-packages/pip/_vendor/rich/_ratio.py | 159 - .../pip/_vendor/rich/_spinners.py | 482 - .../site-packages/pip/_vendor/rich/_stack.py | 16 - .../site-packages/pip/_vendor/rich/_timer.py | 19 - .../pip/_vendor/rich/_win32_console.py | 661 -- .../pip/_vendor/rich/_windows.py | 71 - .../pip/_vendor/rich/_windows_renderer.py | 56 - .../site-packages/pip/_vendor/rich/_wrap.py | 93 - .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 - .../site-packages/pip/_vendor/rich/align.py | 312 - .../site-packages/pip/_vendor/rich/ansi.py | 241 - .../Lib/site-packages/pip/_vendor/rich/bar.py | 93 - .../Lib/site-packages/pip/_vendor/rich/box.py | 480 - .../site-packages/pip/_vendor/rich/cells.py | 174 - .../site-packages/pip/_vendor/rich/color.py | 621 -- .../pip/_vendor/rich/color_triplet.py | 38 - .../site-packages/pip/_vendor/rich/columns.py | 187 - .../site-packages/pip/_vendor/rich/console.py | 2661 ----- .../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 | 191 - .../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 | 88 - .../pip/_vendor/rich/highlighter.py | 232 - .../site-packages/pip/_vendor/rich/json.py | 139 - .../site-packages/pip/_vendor/rich/jupyter.py | 101 - .../site-packages/pip/_vendor/rich/layout.py | 442 - .../site-packages/pip/_vendor/rich/live.py | 375 - .../pip/_vendor/rich/live_render.py | 112 - .../site-packages/pip/_vendor/rich/logging.py | 297 - .../site-packages/pip/_vendor/rich/markup.py | 251 - .../site-packages/pip/_vendor/rich/measure.py | 151 - .../site-packages/pip/_vendor/rich/padding.py | 141 - .../site-packages/pip/_vendor/rich/pager.py | 34 - .../site-packages/pip/_vendor/rich/palette.py | 100 - .../site-packages/pip/_vendor/rich/panel.py | 318 - .../site-packages/pip/_vendor/rich/pretty.py | 1016 -- .../pip/_vendor/rich/progress.py | 1715 ---- .../pip/_vendor/rich/progress_bar.py | 223 - .../site-packages/pip/_vendor/rich/prompt.py | 400 - .../pip/_vendor/rich/protocol.py | 42 - .../site-packages/pip/_vendor/rich/py.typed | 0 .../site-packages/pip/_vendor/rich/region.py | 10 - .../site-packages/pip/_vendor/rich/repr.py | 149 - .../site-packages/pip/_vendor/rich/rule.py | 130 - .../site-packages/pip/_vendor/rich/scope.py | 86 - .../site-packages/pip/_vendor/rich/screen.py | 54 - .../site-packages/pip/_vendor/rich/segment.py | 752 -- .../site-packages/pip/_vendor/rich/spinner.py | 138 - .../site-packages/pip/_vendor/rich/status.py | 131 - .../site-packages/pip/_vendor/rich/style.py | 796 -- .../site-packages/pip/_vendor/rich/styled.py | 42 - .../site-packages/pip/_vendor/rich/syntax.py | 966 -- .../site-packages/pip/_vendor/rich/table.py | 1007 -- .../pip/_vendor/rich/terminal_theme.py | 153 - .../site-packages/pip/_vendor/rich/text.py | 1361 --- .../site-packages/pip/_vendor/rich/theme.py | 115 - .../site-packages/pip/_vendor/rich/themes.py | 5 - .../pip/_vendor/rich/traceback.py | 797 -- .../site-packages/pip/_vendor/rich/tree.py | 257 - .../pip/_vendor/tomli/__init__.py | 8 - .../__pycache__/__init__.cpython-312.pyc | Bin 346 -> 0 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 29360 -> 0 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 4047 -> 0 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 374 -> 0 bytes .../pip/_vendor/tomli/_parser.py | 770 -- .../site-packages/pip/_vendor/tomli/_re.py | 112 - .../site-packages/pip/_vendor/tomli/_types.py | 10 - .../site-packages/pip/_vendor/tomli/py.typed | 1 - .../pip/_vendor/truststore/__init__.py | 36 - .../__pycache__/__init__.cpython-312.pyc | Bin 1352 -> 0 bytes .../__pycache__/_api.cpython-312.pyc | Bin 16781 -> 0 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 18995 -> 0 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 2213 -> 0 bytes .../_ssl_constants.cpython-312.pyc | Bin 1107 -> 0 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 15773 -> 0 bytes .../pip/_vendor/truststore/_api.py | 316 - .../pip/_vendor/truststore/_macos.py | 571 -- .../pip/_vendor/truststore/_openssl.py | 66 - .../pip/_vendor/truststore/_ssl_constants.py | 31 - .../pip/_vendor/truststore/_windows.py | 567 -- .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/typing_extensions.py | 3641 ------- .../pip/_vendor/urllib3/__init__.py | 102 - .../__pycache__/__init__.cpython-312.pyc | Bin 3413 -> 0 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 16372 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 226 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 20411 -> 0 bytes .../connectionpool.cpython-312.pyc | Bin 36546 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 13501 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 10410 -> 0 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 4020 -> 0 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 20437 -> 0 bytes .../__pycache__/request.cpython-312.pyc | Bin 7302 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 33951 -> 0 bytes .../pip/_vendor/urllib3/_collections.py | 355 - .../pip/_vendor/urllib3/_version.py | 2 - .../pip/_vendor/urllib3/connection.py | 572 -- .../pip/_vendor/urllib3/connectionpool.py | 1140 --- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 206 -> 0 bytes .../_appengine_environ.cpython-312.pyc | Bin 1856 -> 0 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 11572 -> 0 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 5722 -> 0 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 24456 -> 0 bytes .../securetransport.cpython-312.pyc | Bin 35509 -> 0 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 7519 -> 0 bytes .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 223 -> 0 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 17435 -> 0 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 14771 -> 0 bytes .../contrib/_securetransport/bindings.py | 519 - .../contrib/_securetransport/low_level.py | 397 - .../pip/_vendor/urllib3/contrib/appengine.py | 314 - .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 - .../pip/_vendor/urllib3/contrib/pyopenssl.py | 518 - .../urllib3/contrib/securetransport.py | 920 -- .../pip/_vendor/urllib3/contrib/socks.py | 216 - .../pip/_vendor/urllib3/exceptions.py | 323 - .../pip/_vendor/urllib3/fields.py | 274 - .../pip/_vendor/urllib3/filepost.py | 98 - .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 207 -> 0 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 41263 -> 0 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 217 -> 0 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 1833 -> 0 bytes .../weakref_finalize.cpython-312.pyc | Bin 7344 -> 0 bytes .../urllib3/packages/backports/makefile.py | 51 - .../packages/backports/weakref_finalize.py | 155 - .../pip/_vendor/urllib3/packages/six.py | 1076 -- .../pip/_vendor/urllib3/poolmanager.py | 540 - .../pip/_vendor/urllib3/request.py | 191 - .../pip/_vendor/urllib3/response.py | 879 -- .../pip/_vendor/urllib3/util/__init__.py | 49 - .../util/__pycache__/__init__.cpython-312.pyc | Bin 1154 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 4755 -> 0 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 1560 -> 0 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 1360 -> 0 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 4191 -> 0 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 3000 -> 0 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 21730 -> 0 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 15372 -> 0 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 5059 -> 0 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 10761 -> 0 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 11147 -> 0 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 15793 -> 0 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 4411 -> 0 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 | 622 -- .../pip/_vendor/urllib3/util/ssl_.py | 504 - .../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 | 18 - .venv/Lib/site-packages/pip/py.typed | 4 - .../requests-2.32.4.dist-info/INSTALLER | 1 - .../requests-2.32.4.dist-info/METADATA | 133 - .../requests-2.32.4.dist-info/RECORD | 43 - .../requests-2.32.4.dist-info/REQUESTED | 0 .../requests-2.32.4.dist-info/WHEEL | 5 - .../licenses/LICENSE | 175 - .../requests-2.32.4.dist-info/top_level.txt | 1 - .venv/Lib/site-packages/requests/__init__.py | 184 - .../__pycache__/__init__.cpython-312.pyc | Bin 5416 -> 0 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 580 -> 0 bytes .../_internal_utils.cpython-312.pyc | Bin 2020 -> 0 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 28354 -> 0 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 7187 -> 0 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 13917 -> 0 bytes .../__pycache__/certs.cpython-312.pyc | Bin 662 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 2371 -> 0 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 25194 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 7581 -> 0 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 4323 -> 0 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 1047 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 35447 -> 0 bytes .../__pycache__/packages.cpython-312.pyc | Bin 1114 -> 0 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 27842 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 6019 -> 0 bytes .../__pycache__/structures.cpython-312.pyc | Bin 5619 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 36098 -> 0 bytes .../Lib/site-packages/requests/__version__.py | 14 - .../site-packages/requests/_internal_utils.py | 50 - .venv/Lib/site-packages/requests/adapters.py | 719 -- .venv/Lib/site-packages/requests/api.py | 157 - .venv/Lib/site-packages/requests/auth.py | 314 - .venv/Lib/site-packages/requests/certs.py | 17 - .venv/Lib/site-packages/requests/compat.py | 106 - .venv/Lib/site-packages/requests/cookies.py | 561 -- .../Lib/site-packages/requests/exceptions.py | 151 - .venv/Lib/site-packages/requests/help.py | 134 - .venv/Lib/site-packages/requests/hooks.py | 33 - .venv/Lib/site-packages/requests/models.py | 1039 -- .venv/Lib/site-packages/requests/packages.py | 23 - .venv/Lib/site-packages/requests/sessions.py | 831 -- .../site-packages/requests/status_codes.py | 128 - .../Lib/site-packages/requests/structures.py | 99 - .venv/Lib/site-packages/requests/utils.py | 1086 --- .../soupsieve-2.7.dist-info/INSTALLER | 1 - .../soupsieve-2.7.dist-info/METADATA | 115 - .../soupsieve-2.7.dist-info/RECORD | 20 - .../soupsieve-2.7.dist-info/WHEEL | 4 - .../licenses/LICENSE.md | 21 - .venv/Lib/site-packages/soupsieve/__init__.py | 168 - .venv/Lib/site-packages/soupsieve/__meta__.py | 197 - .../__pycache__/__init__.cpython-312.pyc | Bin 6113 -> 0 bytes .../__pycache__/__meta__.cpython-312.pyc | Bin 8108 -> 0 bytes .../__pycache__/css_match.cpython-312.pyc | Bin 63691 -> 0 bytes .../__pycache__/css_parser.cpython-312.pyc | Bin 50185 -> 0 bytes .../__pycache__/css_types.cpython-312.pyc | Bin 17356 -> 0 bytes .../__pycache__/pretty.cpython-312.pyc | Bin 5050 -> 0 bytes .../__pycache__/util.cpython-312.pyc | Bin 4713 -> 0 bytes .../Lib/site-packages/soupsieve/css_match.py | 1645 ---- .../Lib/site-packages/soupsieve/css_parser.py | 1318 --- .../Lib/site-packages/soupsieve/css_types.py | 407 - .venv/Lib/site-packages/soupsieve/pretty.py | 139 - .venv/Lib/site-packages/soupsieve/py.typed | 0 .venv/Lib/site-packages/soupsieve/util.py | 117 - .../INSTALLER | 1 - .../METADATA | 68 - .../typing_extensions-4.14.0.dist-info/RECORD | 7 - .../typing_extensions-4.14.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 279 - .venv/Lib/site-packages/typing_extensions.py | 4238 -------- .../urllib3-2.5.0.dist-info/INSTALLER | 1 - .../urllib3-2.5.0.dist-info/METADATA | 154 - .../urllib3-2.5.0.dist-info/RECORD | 79 - .../urllib3-2.5.0.dist-info/WHEEL | 4 - .../licenses/LICENSE.txt | 21 - .venv/Lib/site-packages/urllib3/__init__.py | 211 - .../__pycache__/__init__.cpython-312.pyc | Bin 7311 -> 0 bytes .../_base_connection.cpython-312.pyc | Bin 6861 -> 0 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 22462 -> 0 bytes .../_request_methods.cpython-312.pyc | Bin 10603 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 647 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 38395 -> 0 bytes .../connectionpool.cpython-312.pyc | Bin 39731 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 16612 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 12005 -> 0 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 3480 -> 0 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 24361 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 52697 -> 0 bytes .../site-packages/urllib3/_base_connection.py | 165 - .../Lib/site-packages/urllib3/_collections.py | 479 - .../site-packages/urllib3/_request_methods.py | 278 - .venv/Lib/site-packages/urllib3/_version.py | 21 - .venv/Lib/site-packages/urllib3/connection.py | 1093 --- .../site-packages/urllib3/connectionpool.py | 1178 --- .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 194 -> 0 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 28218 -> 0 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 8172 -> 0 bytes .../urllib3/contrib/emscripten/__init__.py | 16 - .../__pycache__/__init__.cpython-312.pyc | Bin 902 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 10238 -> 0 bytes .../__pycache__/fetch.cpython-312.pyc | Bin 28634 -> 0 bytes .../__pycache__/request.cpython-312.pyc | Bin 1422 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 12210 -> 0 bytes .../urllib3/contrib/emscripten/connection.py | 255 - .../emscripten/emscripten_fetch_worker.js | 110 - .../urllib3/contrib/emscripten/fetch.py | 728 -- .../urllib3/contrib/emscripten/request.py | 22 - .../urllib3/contrib/emscripten/response.py | 277 - .../urllib3/contrib/pyopenssl.py | 564 -- .../site-packages/urllib3/contrib/socks.py | 228 - .venv/Lib/site-packages/urllib3/exceptions.py | 335 - .venv/Lib/site-packages/urllib3/fields.py | 341 - .venv/Lib/site-packages/urllib3/filepost.py | 89 - .../site-packages/urllib3/http2/__init__.py | 53 - .../__pycache__/__init__.cpython-312.pyc | Bin 1747 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 16968 -> 0 bytes .../http2/__pycache__/probe.cpython-312.pyc | Bin 3658 -> 0 bytes .../site-packages/urllib3/http2/connection.py | 356 - .../Lib/site-packages/urllib3/http2/probe.py | 87 - .../Lib/site-packages/urllib3/poolmanager.py | 653 -- .venv/Lib/site-packages/urllib3/py.typed | 2 - .venv/Lib/site-packages/urllib3/response.py | 1307 --- .../site-packages/urllib3/util/__init__.py | 42 - .../util/__pycache__/__init__.cpython-312.pyc | Bin 1007 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 4688 -> 0 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 1219 -> 0 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 8319 -> 0 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 2878 -> 0 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 20293 -> 0 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 17157 -> 0 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 5539 -> 0 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 13307 -> 0 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 11691 -> 0 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 16222 -> 0 bytes .../util/__pycache__/util.cpython-312.pyc | Bin 1996 -> 0 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 3442 -> 0 bytes .../site-packages/urllib3/util/connection.py | 137 - .venv/Lib/site-packages/urllib3/util/proxy.py | 43 - .../Lib/site-packages/urllib3/util/request.py | 266 - .../site-packages/urllib3/util/response.py | 101 - .venv/Lib/site-packages/urllib3/util/retry.py | 533 - .venv/Lib/site-packages/urllib3/util/ssl_.py | 524 - .../urllib3/util/ssl_match_hostname.py | 159 - .../urllib3/util/ssltransport.py | 271 - .../Lib/site-packages/urllib3/util/timeout.py | 275 - .venv/Lib/site-packages/urllib3/util/url.py | 469 - .venv/Lib/site-packages/urllib3/util/util.py | 42 - .venv/Lib/site-packages/urllib3/util/wait.py | 124 - .venv/Scripts/Activate.ps1 | 528 - .venv/Scripts/activate | 76 - .venv/Scripts/activate.bat | 34 - .venv/Scripts/deactivate.bat | 22 - .venv/Scripts/normalizer.exe | Bin 108432 -> 0 bytes .venv/Scripts/pip.exe | Bin 108427 -> 0 bytes .venv/Scripts/pip3.12.exe | Bin 108427 -> 0 bytes .venv/Scripts/pip3.exe | Bin 108427 -> 0 bytes .venv/Scripts/python.exe | Bin 274424 -> 0 bytes .venv/Scripts/pythonw.exe | Bin 263400 -> 0 bytes .venv/pyvenv.cfg | 5 - 1172 files changed, 1 insertion(+), 208918 deletions(-) create mode 100644 .gitignore delete mode 100644 .venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/REQUESTED delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/AUTHORS delete mode 100644 .venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/LICENSE delete mode 100644 .venv/Lib/site-packages/bs4/__init__.py delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/_typing.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/_warnings.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/css.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/dammit.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/diagnose.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/element.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/filter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/__pycache__/formatter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/_deprecation.py delete mode 100644 .venv/Lib/site-packages/bs4/_typing.py delete mode 100644 .venv/Lib/site-packages/bs4/_warnings.py delete mode 100644 .venv/Lib/site-packages/bs4/builder/__init__.py delete mode 100644 .venv/Lib/site-packages/bs4/builder/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/builder/__pycache__/_html5lib.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/builder/__pycache__/_htmlparser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/builder/__pycache__/_lxml.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/builder/_html5lib.py delete mode 100644 .venv/Lib/site-packages/bs4/builder/_htmlparser.py delete mode 100644 .venv/Lib/site-packages/bs4/builder/_lxml.py delete mode 100644 .venv/Lib/site-packages/bs4/css.py delete mode 100644 .venv/Lib/site-packages/bs4/dammit.py delete mode 100644 .venv/Lib/site-packages/bs4/diagnose.py delete mode 100644 .venv/Lib/site-packages/bs4/element.py delete mode 100644 .venv/Lib/site-packages/bs4/exceptions.py delete mode 100644 .venv/Lib/site-packages/bs4/filter.py delete mode 100644 .venv/Lib/site-packages/bs4/formatter.py delete mode 100644 .venv/Lib/site-packages/bs4/py.typed delete mode 100644 .venv/Lib/site-packages/bs4/tests/__init__.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_css.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_dammit.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_element.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_filter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_lxml.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_navigablestring.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_pageelement.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_tag.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/__pycache__/test_tree.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_builder.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_builder_registry.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_css.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_dammit.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_element.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_filter.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_formatter.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_fuzz.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_html5lib.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_htmlparser.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_lxml.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_navigablestring.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_pageelement.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_soup.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_tag.py delete mode 100644 .venv/Lib/site-packages/bs4/tests/test_tree.py delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/licenses/LICENSE delete mode 100644 .venv/Lib/site-packages/certifi-2025.6.15.dist-info/top_level.txt delete mode 100644 .venv/Lib/site-packages/certifi/__init__.py delete mode 100644 .venv/Lib/site-packages/certifi/__main__.py delete mode 100644 .venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/certifi/cacert.pem delete mode 100644 .venv/Lib/site-packages/certifi/core.py delete mode 100644 .venv/Lib/site-packages/certifi/py.typed delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/entry_points.txt delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE delete mode 100644 .venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/top_level.txt delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__init__.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__main__.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/api.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/cd.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/cli/__init__.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/cli/__main__.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/charset_normalizer/constant.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/legacy.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd delete mode 100644 .venv/Lib/site-packages/charset_normalizer/md.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/md__mypyc.cp312-win_amd64.pyd delete mode 100644 .venv/Lib/site-packages/charset_normalizer/models.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/py.typed delete mode 100644 .venv/Lib/site-packages/charset_normalizer/utils.py delete mode 100644 .venv/Lib/site-packages/charset_normalizer/version.py delete mode 100644 .venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md delete mode 100644 .venv/Lib/site-packages/idna-3.10.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/idna-3.10.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/idna-3.10.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/idna/__init__.py delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/codec.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/core.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/idnadata.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/intranges.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/package_data.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/__pycache__/uts46data.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/idna/codec.py delete mode 100644 .venv/Lib/site-packages/idna/compat.py delete mode 100644 .venv/Lib/site-packages/idna/core.py delete mode 100644 .venv/Lib/site-packages/idna/idnadata.py delete mode 100644 .venv/Lib/site-packages/idna/intranges.py delete mode 100644 .venv/Lib/site-packages/idna/package_data.py delete mode 100644 .venv/Lib/site-packages/idna/py.typed delete mode 100644 .venv/Lib/site-packages/idna/uts46data.py delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/AUTHORS.txt delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/LICENSE.txt delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/REQUESTED delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/entry_points.txt delete mode 100644 .venv/Lib/site-packages/pip-25.0.1.dist-info/top_level.txt delete mode 100644 .venv/Lib/site-packages/pip/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/__pip-runner__.py delete mode 100644 .venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/build_env.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cache.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/base_command.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/command_context.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/index_command.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/main.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/parser.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/progress_bars.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/req_command.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/spinners.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/cache.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/check.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/completion.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/configuration.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/debug.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/download.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/freeze.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/hash.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/help.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/index.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/inspect.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/install.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/list.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/search.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/show.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/commands/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/configuration.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/base.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/installed.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/sdist.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/distributions/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/exceptions.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/collector.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/package_finder.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/index/sources.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/_distutils.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/locations/base.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/main.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/_json.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/base.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/candidate.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/direct_url.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/format_control.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/index.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/installation_report.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/link.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/scheme.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/search_scope.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/selection_prefs.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/target_python.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/models/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/auth.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/cache.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/download.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/session.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/utils.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/network/xmlrpc.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/check.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/freeze.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/install/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/operations/prepare.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/pyproject.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/constructors.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_file.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_install.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_set.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/base.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/self_outdated_check.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/_log.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/compat.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/datetime.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/egg_link.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/entrypoints.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/filetypes.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/glibc.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/hashes.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/logging.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/misc.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/packaging.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/retry.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/subprocess.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/unpacking.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/urls.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/virtualenv.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/utils/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/git.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py delete mode 100644 .venv/Lib/site-packages/pip/_internal/wheel_builder.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/core.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/certifi/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/database.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/index.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/util.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/version.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/distro.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/distro/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/codec.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/compat.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/core.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/ext.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_elffile.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_parser.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/licenses/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/licenses/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/licenses/__pycache__/_spdx.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/licenses/_spdx.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/metadata.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/tags.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/packaging/version.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/android.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/api.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/version.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/console.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filter.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatter.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexer.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/modeline.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/plugin.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/scanner.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/style.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/token.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/unistring.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pygments/util.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/pyproject_hooks/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/api.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/auth.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/certs.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/compat.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/help.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/models.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/packages.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/structures.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/requests/utils.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__main__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_export_format.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_extension.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_fileno.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_inspect.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_log_render.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_loop.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_null_file.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_palettes.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_pick.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_ratio.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_spinners.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_stack.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_timer.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_windows.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/_wrap.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/abc.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/align.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/ansi.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/bar.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/box.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/cells.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/color.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/columns.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/console.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/constrain.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/containers.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/control.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/default_styles.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/diagnose.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/emoji.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/errors.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/filesize.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/highlighter.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/json.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/jupyter.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/layout.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/live.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/live_render.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/logging.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/markup.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/measure.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/padding.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/pager.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/palette.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/panel.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/pretty.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/progress.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/prompt.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/protocol.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/region.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/repr.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/rule.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/scope.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/screen.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/segment.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/spinner.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/status.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/style.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/styled.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/syntax.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/table.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/text.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/theme.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/themes.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/traceback.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/rich/tree.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_parser.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_re.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/_types.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/tomli/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/_api.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/_macos.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/_windows.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/truststore/py.typed delete mode 100644 .venv/Lib/site-packages/pip/_vendor/typing_extensions.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/_version.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 .venv/Lib/site-packages/pip/_vendor/vendor.txt delete mode 100644 .venv/Lib/site-packages/pip/py.typed delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/REQUESTED delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/licenses/LICENSE delete mode 100644 .venv/Lib/site-packages/requests-2.32.4.dist-info/top_level.txt delete mode 100644 .venv/Lib/site-packages/requests/__init__.py delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/__version__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/adapters.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/api.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/auth.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/certs.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/compat.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/cookies.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/help.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/hooks.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/models.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/packages.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/sessions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/status_codes.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/structures.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/requests/__version__.py delete mode 100644 .venv/Lib/site-packages/requests/_internal_utils.py delete mode 100644 .venv/Lib/site-packages/requests/adapters.py delete mode 100644 .venv/Lib/site-packages/requests/api.py delete mode 100644 .venv/Lib/site-packages/requests/auth.py delete mode 100644 .venv/Lib/site-packages/requests/certs.py delete mode 100644 .venv/Lib/site-packages/requests/compat.py delete mode 100644 .venv/Lib/site-packages/requests/cookies.py delete mode 100644 .venv/Lib/site-packages/requests/exceptions.py delete mode 100644 .venv/Lib/site-packages/requests/help.py delete mode 100644 .venv/Lib/site-packages/requests/hooks.py delete mode 100644 .venv/Lib/site-packages/requests/models.py delete mode 100644 .venv/Lib/site-packages/requests/packages.py delete mode 100644 .venv/Lib/site-packages/requests/sessions.py delete mode 100644 .venv/Lib/site-packages/requests/status_codes.py delete mode 100644 .venv/Lib/site-packages/requests/structures.py delete mode 100644 .venv/Lib/site-packages/requests/utils.py delete mode 100644 .venv/Lib/site-packages/soupsieve-2.7.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/soupsieve-2.7.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/soupsieve-2.7.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/soupsieve-2.7.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/soupsieve-2.7.dist-info/licenses/LICENSE.md delete mode 100644 .venv/Lib/site-packages/soupsieve/__init__.py delete mode 100644 .venv/Lib/site-packages/soupsieve/__meta__.py delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/__meta__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/css_match.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/css_parser.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/css_types.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/pretty.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/__pycache__/util.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/soupsieve/css_match.py delete mode 100644 .venv/Lib/site-packages/soupsieve/css_parser.py delete mode 100644 .venv/Lib/site-packages/soupsieve/css_types.py delete mode 100644 .venv/Lib/site-packages/soupsieve/pretty.py delete mode 100644 .venv/Lib/site-packages/soupsieve/py.typed delete mode 100644 .venv/Lib/site-packages/soupsieve/util.py delete mode 100644 .venv/Lib/site-packages/typing_extensions-4.14.0.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/typing_extensions-4.14.0.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/typing_extensions-4.14.0.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/typing_extensions-4.14.0.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/typing_extensions-4.14.0.dist-info/licenses/LICENSE delete mode 100644 .venv/Lib/site-packages/typing_extensions.py delete mode 100644 .venv/Lib/site-packages/urllib3-2.5.0.dist-info/INSTALLER delete mode 100644 .venv/Lib/site-packages/urllib3-2.5.0.dist-info/METADATA delete mode 100644 .venv/Lib/site-packages/urllib3-2.5.0.dist-info/RECORD delete mode 100644 .venv/Lib/site-packages/urllib3-2.5.0.dist-info/WHEEL delete mode 100644 .venv/Lib/site-packages/urllib3-2.5.0.dist-info/licenses/LICENSE.txt delete mode 100644 .venv/Lib/site-packages/urllib3/__init__.py delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/_base_connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/_collections.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/_request_methods.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/_version.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/connectionpool.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/fields.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/filepost.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/poolmanager.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/__pycache__/response.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/_base_connection.py delete mode 100644 .venv/Lib/site-packages/urllib3/_collections.py delete mode 100644 .venv/Lib/site-packages/urllib3/_request_methods.py delete mode 100644 .venv/Lib/site-packages/urllib3/_version.py delete mode 100644 .venv/Lib/site-packages/urllib3/connection.py delete mode 100644 .venv/Lib/site-packages/urllib3/connectionpool.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/__init__.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/__pycache__/socks.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__init__.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/fetch.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/request.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/response.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/connection.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/fetch.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/request.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/emscripten/response.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/pyopenssl.py delete mode 100644 .venv/Lib/site-packages/urllib3/contrib/socks.py delete mode 100644 .venv/Lib/site-packages/urllib3/exceptions.py delete mode 100644 .venv/Lib/site-packages/urllib3/fields.py delete mode 100644 .venv/Lib/site-packages/urllib3/filepost.py delete mode 100644 .venv/Lib/site-packages/urllib3/http2/__init__.py delete mode 100644 .venv/Lib/site-packages/urllib3/http2/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/http2/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/http2/__pycache__/probe.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/http2/connection.py delete mode 100644 .venv/Lib/site-packages/urllib3/http2/probe.py delete mode 100644 .venv/Lib/site-packages/urllib3/poolmanager.py delete mode 100644 .venv/Lib/site-packages/urllib3/py.typed delete mode 100644 .venv/Lib/site-packages/urllib3/response.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/__init__.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/connection.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/proxy.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/request.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/response.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/retry.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/ssl_.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/ssltransport.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/timeout.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/url.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/util.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/__pycache__/wait.cpython-312.pyc delete mode 100644 .venv/Lib/site-packages/urllib3/util/connection.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/proxy.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/request.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/response.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/retry.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/ssl_.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/ssl_match_hostname.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/ssltransport.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/timeout.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/url.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/util.py delete mode 100644 .venv/Lib/site-packages/urllib3/util/wait.py delete mode 100644 .venv/Scripts/Activate.ps1 delete mode 100644 .venv/Scripts/activate delete mode 100644 .venv/Scripts/activate.bat delete mode 100644 .venv/Scripts/deactivate.bat delete mode 100644 .venv/Scripts/normalizer.exe delete mode 100644 .venv/Scripts/pip.exe delete mode 100644 .venv/Scripts/pip3.12.exe delete mode 100644 .venv/Scripts/pip3.exe delete mode 100644 .venv/Scripts/python.exe delete mode 100644 .venv/Scripts/pythonw.exe delete mode 100644 .venv/pyvenv.cfg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cafc1c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv/ \ No newline at end of file diff --git a/.venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc b/.venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc deleted file mode 100644 index cc08b472bc3970671a871274a4ea17fc91f9d102..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162089 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 aJS87 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 -License: MIT License -License-File: AUTHORS -License-File: LICENSE -Keywords: HTML,XML,parse,soup -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Classifier: Topic :: Text Processing :: Markup :: SGML -Classifier: Topic :: Text Processing :: Markup :: XML -Requires-Python: >=3.7.0 -Requires-Dist: soupsieve>1.2 -Requires-Dist: typing-extensions>=4.0.0 -Provides-Extra: cchardet -Requires-Dist: cchardet; extra == 'cchardet' -Provides-Extra: chardet -Requires-Dist: chardet; extra == 'chardet' -Provides-Extra: charset-normalizer -Requires-Dist: charset-normalizer; extra == 'charset-normalizer' -Provides-Extra: html5lib -Requires-Dist: html5lib; extra == 'html5lib' -Provides-Extra: lxml -Requires-Dist: lxml; extra == 'lxml' -Description-Content-Type: text/markdown - -Beautiful Soup is a library that makes it easy to scrape information -from web pages. It sits atop an HTML or XML parser, providing Pythonic -idioms for iterating, searching, and modifying the parse tree. - -# Quick start - -``` ->>> from bs4 import BeautifulSoup ->>> soup = BeautifulSoup("

SomebadHTML") ->>> print(soup.prettify()) - - -

- Some - - bad - - HTML - - -

- - ->>> soup.find(string="bad") -'bad' ->>> soup.i -HTML -# ->>> soup = BeautifulSoup("SomebadXML", "xml") -# ->>> print(soup.prettify()) - - - Some - - bad - - XML - - -``` - -To go beyond the basics, [comprehensive documentation is available](https://www.crummy.com/software/BeautifulSoup/bs4/doc/). - -# Links - -* [Homepage](https://www.crummy.com/software/BeautifulSoup/bs4/) -* [Documentation](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) -* [Discussion group](https://groups.google.com/group/beautifulsoup/) -* [Development](https://code.launchpad.net/beautifulsoup/) -* [Bug tracker](https://bugs.launchpad.net/beautifulsoup/) -* [Complete changelog](https://git.launchpad.net/beautifulsoup/tree/CHANGELOG) - -# Note on Python 2 sunsetting - -Beautiful Soup's support for Python 2 was discontinued on December 31, -2020: one year after the sunset date for Python 2 itself. From this -point onward, new Beautiful Soup development will exclusively target -Python 3. The final release of Beautiful Soup 4 to support Python 2 -was 4.9.3. - -# Supporting the project - -If you use Beautiful Soup as part of your professional work, please consider a -[Tidelift subscription](https://tidelift.com/subscription/pkg/pypi-beautifulsoup4?utm_source=pypi-beautifulsoup4&utm_medium=referral&utm_campaign=readme). -This will support many of the free software projects your organization -depends on, not just Beautiful Soup. - -If you use Beautiful Soup for personal projects, the best way to say -thank you is to read -[Tool Safety](https://www.crummy.com/software/BeautifulSoup/zine/), a zine I -wrote about what Beautiful Soup has taught me about software -development. - -# Building the documentation - -The bs4/doc/ directory contains full documentation in Sphinx -format. Run `make html` in that directory to create HTML -documentation. - -# Running the unit tests - -Beautiful Soup supports unit test discovery using Pytest: - -``` -$ pytest -``` - diff --git a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/RECORD b/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/RECORD deleted file mode 100644 index ccf512f..0000000 --- a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/RECORD +++ /dev/null @@ -1,90 +0,0 @@ -beautifulsoup4-4.13.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -beautifulsoup4-4.13.4.dist-info/METADATA,sha256=zXwPMgMEIdymEV_lAL0QzP34i6osem_P2nfqgaEexRo,3809 -beautifulsoup4-4.13.4.dist-info/RECORD,, -beautifulsoup4-4.13.4.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -beautifulsoup4-4.13.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 -beautifulsoup4-4.13.4.dist-info/licenses/AUTHORS,sha256=uYkjiRjh_aweRnF8tAW2PpJJeickE68NmJwd9siry28,2201 -beautifulsoup4-4.13.4.dist-info/licenses/LICENSE,sha256=VbTY1LHlvIbRDvrJG3TIe8t3UmsPW57a-LnNKtxzl7I,1441 -bs4/__init__.py,sha256=ZkHAdXHt3PEkwDrx_Z4ABuz-T_-TSO8aL6Vpy9uiI8M,44212 -bs4/__pycache__/__init__.cpython-312.pyc,, -bs4/__pycache__/_deprecation.cpython-312.pyc,, -bs4/__pycache__/_typing.cpython-312.pyc,, -bs4/__pycache__/_warnings.cpython-312.pyc,, -bs4/__pycache__/css.cpython-312.pyc,, -bs4/__pycache__/dammit.cpython-312.pyc,, -bs4/__pycache__/diagnose.cpython-312.pyc,, -bs4/__pycache__/element.cpython-312.pyc,, -bs4/__pycache__/exceptions.cpython-312.pyc,, -bs4/__pycache__/filter.cpython-312.pyc,, -bs4/__pycache__/formatter.cpython-312.pyc,, -bs4/_deprecation.py,sha256=ucZjfBAUF1B0f5ldNIIhlkHsYjHtvwELWlE3_pAR6Vs,2394 -bs4/_typing.py,sha256=3FgPPPrdsTa-kvn1R36o1k_2SfilcUWm4M9i7G4qFl8,7118 -bs4/_warnings.py,sha256=ZuOETgcnEbZgw2N0nnNXn6wvtrn2ut7AF0d98bvkMFc,4711 -bs4/builder/__init__.py,sha256=TYAKmGFuVfTsI53reHijcZKETnPuvse57KZ6LsZsJRo,31130 -bs4/builder/__pycache__/__init__.cpython-312.pyc,, -bs4/builder/__pycache__/_html5lib.cpython-312.pyc,, -bs4/builder/__pycache__/_htmlparser.cpython-312.pyc,, -bs4/builder/__pycache__/_lxml.cpython-312.pyc,, -bs4/builder/_html5lib.py,sha256=3MXq29SYg9XoS9gu2hgTDU02IQkv8kIBx3rW1QWY3fg,22846 -bs4/builder/_htmlparser.py,sha256=cu9PFkxkqVIIe9nU3fVy-JJhINEhY8cGbsuCwZCnQCA,17872 -bs4/builder/_lxml.py,sha256=9L5pJ7ekI-G3HhOhoxcpjZPqDMRfUoWj4Nnku6B2uR8,18545 -bs4/css.py,sha256=XGQq7HQUDyYEbDorFMGIGek7QGPiFuZYnvNEQ59GyxM,12685 -bs4/dammit.py,sha256=oHd1elJ44kMobBGSQRuG7Wln6M-BLz1unOuUscaL9h0,51472 -bs4/diagnose.py,sha256=zy7_GPQHsTtNf8s10WWIRcC5xH5_8LKs295Aa7iFUyI,7832 -bs4/element.py,sha256=7w9cLT9oTU8lrWm9nnlPqHpa_v4U8UuyIUsWnTHYLbw,109768 -bs4/exceptions.py,sha256=Q9FOadNe8QRvzDMaKSXe2Wtl8JK_oAZW7mbFZBVP_GE,951 -bs4/filter.py,sha256=8lzv5yE0mw7jhYwPyDiFCfXAB4-wDiIgn7m8fmIKcGA,29031 -bs4/formatter.py,sha256=5O4gBxTTi5TLU6TdqsgYI9Io0Gc_6-oCAWpfHI3Thn0,10464 -bs4/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -bs4/tests/__init__.py,sha256=ieOudaXvOWA_g4Gb25adCnhEabtEpRwf9_DdplXKdXQ,52671 -bs4/tests/__pycache__/__init__.cpython-312.pyc,, -bs4/tests/__pycache__/test_builder.cpython-312.pyc,, -bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc,, -bs4/tests/__pycache__/test_css.cpython-312.pyc,, -bs4/tests/__pycache__/test_dammit.cpython-312.pyc,, -bs4/tests/__pycache__/test_element.cpython-312.pyc,, -bs4/tests/__pycache__/test_filter.cpython-312.pyc,, -bs4/tests/__pycache__/test_formatter.cpython-312.pyc,, -bs4/tests/__pycache__/test_fuzz.cpython-312.pyc,, -bs4/tests/__pycache__/test_html5lib.cpython-312.pyc,, -bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc,, -bs4/tests/__pycache__/test_lxml.cpython-312.pyc,, -bs4/tests/__pycache__/test_navigablestring.cpython-312.pyc,, -bs4/tests/__pycache__/test_pageelement.cpython-312.pyc,, -bs4/tests/__pycache__/test_soup.cpython-312.pyc,, -bs4/tests/__pycache__/test_tag.cpython-312.pyc,, -bs4/tests/__pycache__/test_tree.cpython-312.pyc,, -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase,sha256=yUdXkbpNK7LVOQ0LBHMoqZ1rWaBfSXWytoO_xdSm7Ho,15 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase,sha256=Uv_dx4a43TSfoNkjU-jHW2nSXkqHFg4XdAw7SWVObUk,23 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase,sha256=OEyVA0Ej4FxswOElrUNt0In4s4YhrmtaxE_NHGZvGtg,30 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase,sha256=G4vpNBOz-RwMpi6ewEgNEa13zX0sXhmL7VHOyIcdKVQ,15347 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase,sha256=3d8z65o4p7Rur-RmCHoOjzqaYQ8EAtjmiBYTHNyAdl4,19469 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase,sha256=NfGIlit1k40Ip3mlnBkYOkIDJX6gHtjlErwl7gsBjAQ,12 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase,sha256=xy4i1U0nhFHcnyc5pRKS6JRMvuoCNUur-Scor6UxIGw,4317 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase,sha256=Q-UTYpQBUsWoMgIUspUlzveSI-41s4ABC3jajRb-K0o,11502 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase,sha256=2bq3S8KxZgk8EajLReHD8m4_0Lj_nrkyJAxB_z_U0D0,5 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase,sha256=MZDu31LPLfgu6jP9IZkrlwNes3f_sL8WFP5BChkUKdY,35 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase,sha256=w58r-s6besG5JwPXpnz37W2YTj9-_qxFbk6hiEnKeIQ,51495 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase,sha256=q8rkdMECEXKcqVhOf5zWHkSBTQeOPt0JiLg2TZiPCuk,10380 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase,sha256=QfzoOxKwNuqG-4xIrea6MOQLXhfAAOQJ0r9u-J6kSNs,19 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase,sha256=MJ2pHFuuCQUiQz1Kor2sof7LWeRERQ6QK43YNqQHg9o,47 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase,sha256=EItOpSdeD4ewK-qgJ9vtxennwn_huguzXgctrUT7fqE,3546 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase,sha256=a2aJTG4FceGSJXsjtxoS8S4jk_8rZsS3aznLkeO2_dY,124 -bs4/tests/fuzz/crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase,sha256=jRFRtCKlP3-3EDLc_iVRTcE6JNymv0rYcVM6qRaPrxI,2607 -bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase,sha256=7NsdCiXWAhNkmoW1pvF7rbZExyLAQIWtDtSHXIsH6YU,103 -bs4/tests/test_builder.py,sha256=BBMBirb4mb-fVdJj4dxQCxrdcjQeulKSKBFrPFVpVOk,1095 -bs4/tests/test_builder_registry.py,sha256=tpJ5Niva_cF49SdzIb1gMo0W4Tiodr8BYSOE3O6P_g8,5064 -bs4/tests/test_css.py,sha256=T_HCMzpe6hTr8d2YFXm0DScr8gT8d6h0MYlhZfo6A4U,18625 -bs4/tests/test_dammit.py,sha256=TQCVe6kKVYSuYjwTtIvIaOYYmWYPMnR_3PK45kimLg4,17840 -bs4/tests/test_element.py,sha256=u7FbTtKE6pYJetD1PgS3fCU1-QQXfB7GaLwfI3s4ROY,4373 -bs4/tests/test_filter.py,sha256=JzvU3eI4r1QyNIHKqhxbZ-M7q5qgw-S7Y73MGI2tNr4,27395 -bs4/tests/test_formatter.py,sha256=a6TaeNOVeg_ZYseiP7atmFyYJkQJqlk-jlVxMlyJC2o,6943 -bs4/tests/test_fuzz.py,sha256=zyaoWgCt8hnRkXecBYM9x91fI_Ao9eQUcsBi76ooJ08,7123 -bs4/tests/test_html5lib.py,sha256=ljMOAds__k9zhfT4jVnxxhZkLEggaT7wqDexzDNwus4,9206 -bs4/tests/test_htmlparser.py,sha256=iDHEI69GcisNP48BeHdLAWlqPGhrBwxftnUM8_3nsR4,6662 -bs4/tests/test_lxml.py,sha256=4fZIsNVbm2zdRQFNNwD-lqwf_QtUtiU4QbtLXISQZBw,7453 -bs4/tests/test_navigablestring.py,sha256=5-vs86ujXcs6LjT1lPYQHLi2ag3eBtFfnrOrjzV665M,5599 -bs4/tests/test_pageelement.py,sha256=lAw-sVP3zJX0VdHXXN1Ia3tci5dgK10Gac5o9G46IIk,16195 -bs4/tests/test_soup.py,sha256=I-mhNheo2-PTvfJToDI43EO4RmGlpKJsYOS19YoQ7-8,22669 -bs4/tests/test_tag.py,sha256=ue32hxQs_a1cMuzyu7MNjK42t0IOGMA6POPLIArMOts,9690 -bs4/tests/test_tree.py,sha256=Iw2e2spk19PEtCObE0ymgJH4n4F5_KbMvpcOeblHBsI,55074 diff --git a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/REQUESTED b/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/WHEEL b/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/WHEEL deleted file mode 100644 index 12228d4..0000000 --- a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.27.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/AUTHORS b/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/AUTHORS deleted file mode 100644 index 18926c2..0000000 --- a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/AUTHORS +++ /dev/null @@ -1,49 +0,0 @@ -Behold, mortal, the origins of Beautiful Soup... -================================================ - -Leonard Richardson is the primary maintainer. - -Aaron DeVore, Isaac Muse and Chris Papademetrious have made -significant contributions to the code base. - -Mark Pilgrim provided the encoding detection code that forms the base -of UnicodeDammit. - -Thomas Kluyver and Ezio Melotti finished the work of getting Beautiful -Soup 4 working under Python 3. - -Simon Willison wrote soupselect, which was used to make Beautiful Soup -support CSS selectors. Isaac Muse wrote SoupSieve, which made it -possible to _remove_ the CSS selector code from Beautiful Soup. - -Sam Ruby helped with a lot of edge cases. - -Jonathan Ellis was awarded the prestigious Beau Potage D'Or for his -work in solving the nestable tags conundrum. - -An incomplete list of people have contributed patches to Beautiful -Soup: - - Istvan Albert, Andrew Lin, Anthony Baxter, Oliver Beattie, Andrew -Boyko, Tony Chang, Francisco Canas, "Delong", Zephyr Fang, Fuzzy, -Roman Gaufman, Yoni Gilad, Richie Hindle, Toshihiro Kamiya, Peteris -Krumins, Kent Johnson, Marek Kapolka, Andreas Kostyrka, Roel Kramer, -Ben Last, Robert Leftwich, Stefaan Lippens, "liquider", Staffan -Malmgren, Ksenia Marasanova, JP Moins, Adam Monsen, John Nagle, "Jon", -Ed Oskiewicz, Martijn Peters, Greg Phillips, Giles Radford, Stefano -Revera, Arthur Rudolph, Marko Samastur, James Salter, Jouni Seppänen, -Alexander Schmolck, Tim Shirley, Geoffrey Sneddon, Ville Skyttä, -"Vikas", Jens Svalgaard, Andy Theyers, Eric Weiser, Glyn Webster, John -Wiseman, Paul Wright, Danny Yoo - -An incomplete list of people who made suggestions or found bugs or -found ways to break Beautiful Soup: - - Hanno Böck, Matteo Bertini, Chris Curvey, Simon Cusack, Bruce Eckel, - Matt Ernst, Michael Foord, Tom Harris, Bill de hOra, Donald Howes, - Matt Patterson, Scott Roberts, Steve Strassmann, Mike Williams, - warchild at redho dot com, Sami Kuisma, Carlos Rocha, Bob Hutchison, - Joren Mc, Michal Migurski, John Kleven, Tim Heaney, Tripp Lilley, Ed - Summers, Dennis Sutch, Chris Smith, Aaron Swartz, Stuart - Turner, Greg Edwards, Kevin J Kalupson, Nikos Kouremenos, Artur de - Sousa Rocha, Yichun Wei, Per Vognsen diff --git a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/LICENSE b/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/LICENSE deleted file mode 100644 index 08e3a9c..0000000 --- a/.venv/Lib/site-packages/beautifulsoup4-4.13.4.dist-info/licenses/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Beautiful Soup is made available under the MIT license: - - Copyright (c) Leonard Richardson - - 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. - -Beautiful Soup incorporates code from the html5lib library, which is -also made available under the MIT license. Copyright (c) James Graham -and other contributors - -Beautiful Soup has an optional dependency on the soupsieve library, -which is also made available under the MIT license. Copyright (c) -Isaac Muse diff --git a/.venv/Lib/site-packages/bs4/__init__.py b/.venv/Lib/site-packages/bs4/__init__.py deleted file mode 100644 index 324fcfa..0000000 --- a/.venv/Lib/site-packages/bs4/__init__.py +++ /dev/null @@ -1,1170 +0,0 @@ -"""Beautiful Soup Elixir and Tonic - "The Screen-Scraper's Friend". - -http://www.crummy.com/software/BeautifulSoup/ - -Beautiful Soup uses a pluggable XML or HTML parser to parse a -(possibly invalid) document into a tree representation. Beautiful Soup -provides methods and Pythonic idioms that make it easy to navigate, -search, and modify the parse tree. - -Beautiful Soup works with Python 3.7 and up. It works better if lxml -and/or html5lib is installed, but they are not required. - -For more than you ever wanted to know about Beautiful Soup, see the -documentation: http://www.crummy.com/software/BeautifulSoup/bs4/doc/ -""" - -__author__ = "Leonard Richardson (leonardr@segfault.org)" -__version__ = "4.13.4" -__copyright__ = "Copyright (c) 2004-2025 Leonard Richardson" -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -__all__ = [ - "AttributeResemblesVariableWarning", - "BeautifulSoup", - "Comment", - "Declaration", - "ProcessingInstruction", - "ResultSet", - "CSS", - "Script", - "Stylesheet", - "Tag", - "TemplateString", - "ElementFilter", - "UnicodeDammit", - "CData", - "Doctype", - - # Exceptions - "FeatureNotFound", - "ParserRejectedMarkup", - "StopParsing", - - # Warnings - "AttributeResemblesVariableWarning", - "GuessedAtParserWarning", - "MarkupResemblesLocatorWarning", - "UnusualUsageWarning", - "XMLParsedAsHTMLWarning", -] - -from collections import Counter -import sys -import warnings - -# The very first thing we do is give a useful error if someone is -# running this code under Python 2. -if sys.version_info.major < 3: - raise ImportError( - "You are trying to use a Python 3-specific version of Beautiful Soup under Python 2. This will not work. The final version of Beautiful Soup to support Python 2 was 4.9.3." - ) - -from .builder import ( - builder_registry, - TreeBuilder, -) -from .builder._htmlparser import HTMLParserTreeBuilder -from .dammit import UnicodeDammit -from .css import CSS -from ._deprecation import ( - _deprecated, -) -from .element import ( - CData, - Comment, - DEFAULT_OUTPUT_ENCODING, - Declaration, - Doctype, - NavigableString, - PageElement, - ProcessingInstruction, - PYTHON_SPECIFIC_ENCODINGS, - ResultSet, - Script, - Stylesheet, - Tag, - TemplateString, -) -from .formatter import Formatter -from .filter import ( - ElementFilter, - SoupStrainer, -) -from typing import ( - Any, - cast, - Counter as CounterType, - Dict, - Iterator, - List, - Sequence, - Optional, - Type, - Union, -) - -from bs4._typing import ( - _Encoding, - _Encodings, - _IncomingMarkup, - _InsertableElement, - _RawAttributeValue, - _RawAttributeValues, - _RawMarkup, -) - -# Import all warnings and exceptions into the main package. -from bs4.exceptions import ( - FeatureNotFound, - ParserRejectedMarkup, - StopParsing, -) -from bs4._warnings import ( - AttributeResemblesVariableWarning, - GuessedAtParserWarning, - MarkupResemblesLocatorWarning, - UnusualUsageWarning, - XMLParsedAsHTMLWarning, -) - - -class BeautifulSoup(Tag): - """A data structure representing a parsed HTML or XML document. - - Most of the methods you'll call on a BeautifulSoup object are inherited from - PageElement or Tag. - - Internally, this class defines the basic interface called by the - tree builders when converting an HTML/XML document into a data - structure. The interface abstracts away the differences between - parsers. To write a new tree builder, you'll need to understand - these methods as a whole. - - These methods will be called by the BeautifulSoup constructor: - * reset() - * feed(markup) - - The tree builder may call these methods from its feed() implementation: - * handle_starttag(name, attrs) # See note about return value - * handle_endtag(name) - * handle_data(data) # Appends to the current data node - * endData(containerClass) # Ends the current data node - - No matter how complicated the underlying parser is, you should be - able to build a tree using 'start tag' events, 'end tag' events, - 'data' events, and "done with data" events. - - If you encounter an empty-element tag (aka a self-closing tag, - like HTML's
tag), call handle_starttag and then - handle_endtag. - """ - - #: Since `BeautifulSoup` subclasses `Tag`, it's possible to treat it as - #: a `Tag` with a `Tag.name`. Hoever, this name makes it clear the - #: `BeautifulSoup` object isn't a real markup tag. - ROOT_TAG_NAME: str = "[document]" - - #: If the end-user gives no indication which tree builder they - #: want, look for one with these features. - DEFAULT_BUILDER_FEATURES: Sequence[str] = ["html", "fast"] - - #: A string containing all ASCII whitespace characters, used in - #: during parsing to detect data chunks that seem 'empty'. - ASCII_SPACES: str = "\x20\x0a\x09\x0c\x0d" - - # FUTURE PYTHON: - element_classes: Dict[Type[PageElement], Type[PageElement]] #: :meta private: - builder: TreeBuilder #: :meta private: - is_xml: bool - known_xml: Optional[bool] - parse_only: Optional[SoupStrainer] #: :meta private: - - # These members are only used while parsing markup. - markup: Optional[_RawMarkup] #: :meta private: - current_data: List[str] #: :meta private: - currentTag: Optional[Tag] #: :meta private: - tagStack: List[Tag] #: :meta private: - open_tag_counter: CounterType[str] #: :meta private: - preserve_whitespace_tag_stack: List[Tag] #: :meta private: - string_container_stack: List[Tag] #: :meta private: - _most_recent_element: Optional[PageElement] #: :meta private: - - #: Beautiful Soup's best guess as to the character encoding of the - #: original document. - original_encoding: Optional[_Encoding] - - #: The character encoding, if any, that was explicitly defined - #: in the original document. This may or may not match - #: `BeautifulSoup.original_encoding`. - declared_html_encoding: Optional[_Encoding] - - #: This is True if the markup that was parsed contains - #: U+FFFD REPLACEMENT_CHARACTER characters which were not present - #: in the original markup. These mark character sequences that - #: could not be represented in Unicode. - contains_replacement_characters: bool - - def __init__( - self, - markup: _IncomingMarkup = "", - features: Optional[Union[str, Sequence[str]]] = None, - builder: Optional[Union[TreeBuilder, Type[TreeBuilder]]] = None, - parse_only: Optional[SoupStrainer] = None, - from_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - element_classes: Optional[Dict[Type[PageElement], Type[PageElement]]] = None, - **kwargs: Any, - ): - """Constructor. - - :param markup: A string or a file-like object representing - markup to be parsed. - - :param features: Desirable features of the parser to be - used. This may be the name of a specific parser ("lxml", - "lxml-xml", "html.parser", or "html5lib") or it may be the - type of markup to be used ("html", "html5", "xml"). It's - recommended that you name a specific parser, so that - Beautiful Soup gives you the same results across platforms - and virtual environments. - - :param builder: A TreeBuilder subclass to instantiate (or - instance to use) instead of looking one up based on - `features`. You only need to use this if you've implemented a - custom TreeBuilder. - - :param parse_only: A SoupStrainer. Only parts of the document - matching the SoupStrainer will be considered. This is useful - when parsing part of a document that would otherwise be too - large to fit into memory. - - :param from_encoding: A string indicating the encoding of the - document to be parsed. Pass this in if Beautiful Soup is - guessing wrongly about the document's encoding. - - :param exclude_encodings: A list of strings indicating - encodings known to be wrong. Pass this in if you don't know - the document's encoding but you know Beautiful Soup's guess is - wrong. - - :param element_classes: A dictionary mapping BeautifulSoup - classes like Tag and NavigableString, to other classes you'd - like to be instantiated instead as the parse tree is - built. This is useful for subclassing Tag or NavigableString - to modify default behavior. - - :param kwargs: For backwards compatibility purposes, the - constructor accepts certain keyword arguments used in - Beautiful Soup 3. None of these arguments do anything in - Beautiful Soup 4; they will result in a warning and then be - ignored. - - Apart from this, any keyword arguments passed into the - BeautifulSoup constructor are propagated to the TreeBuilder - constructor. This makes it possible to configure a - TreeBuilder by passing in arguments, not just by saying which - one to use. - """ - if "convertEntities" in kwargs: - del kwargs["convertEntities"] - warnings.warn( - "BS4 does not respect the convertEntities argument to the " - "BeautifulSoup constructor. Entities are always converted " - "to Unicode characters." - ) - - if "markupMassage" in kwargs: - del kwargs["markupMassage"] - warnings.warn( - "BS4 does not respect the markupMassage argument to the " - "BeautifulSoup constructor. The tree builder is responsible " - "for any necessary markup massage." - ) - - if "smartQuotesTo" in kwargs: - del kwargs["smartQuotesTo"] - warnings.warn( - "BS4 does not respect the smartQuotesTo argument to the " - "BeautifulSoup constructor. Smart quotes are always converted " - "to Unicode characters." - ) - - if "selfClosingTags" in kwargs: - del kwargs["selfClosingTags"] - warnings.warn( - "Beautiful Soup 4 does not respect the selfClosingTags argument to the " - "BeautifulSoup constructor. The tree builder is responsible " - "for understanding self-closing tags." - ) - - if "isHTML" in kwargs: - del kwargs["isHTML"] - warnings.warn( - "Beautiful Soup 4 does not respect the isHTML argument to the " - "BeautifulSoup constructor. Suggest you use " - "features='lxml' for HTML and features='lxml-xml' for " - "XML." - ) - - def deprecated_argument(old_name: str, new_name: str) -> Optional[Any]: - if old_name in kwargs: - warnings.warn( - 'The "%s" argument to the BeautifulSoup constructor ' - 'was renamed to "%s" in Beautiful Soup 4.0.0' - % (old_name, new_name), - DeprecationWarning, - stacklevel=3, - ) - return kwargs.pop(old_name) - return None - - parse_only = parse_only or deprecated_argument("parseOnlyThese", "parse_only") - if parse_only is not None: - # Issue a warning if we can tell in advance that - # parse_only will exclude the entire tree. - if parse_only.excludes_everything: - warnings.warn( - f"The given value for parse_only will exclude everything: {parse_only}", - UserWarning, - stacklevel=3, - ) - - from_encoding = from_encoding or deprecated_argument( - "fromEncoding", "from_encoding" - ) - - if from_encoding and isinstance(markup, str): - warnings.warn( - "You provided Unicode markup but also provided a value for from_encoding. Your from_encoding will be ignored." - ) - from_encoding = None - - self.element_classes = element_classes or dict() - - # We need this information to track whether or not the builder - # was specified well enough that we can omit the 'you need to - # specify a parser' warning. - original_builder = builder - original_features = features - - builder_class: Type[TreeBuilder] - if isinstance(builder, type): - # A builder class was passed in; it needs to be instantiated. - builder_class = builder - builder = None - elif builder is None: - if isinstance(features, str): - features = [features] - if features is None or len(features) == 0: - features = self.DEFAULT_BUILDER_FEATURES - possible_builder_class = builder_registry.lookup(*features) - if possible_builder_class is None: - raise FeatureNotFound( - "Couldn't find a tree builder with the features you " - "requested: %s. Do you need to install a parser library?" - % ",".join(features) - ) - builder_class = possible_builder_class - - # At this point either we have a TreeBuilder instance in - # builder, or we have a builder_class that we can instantiate - # with the remaining **kwargs. - if builder is None: - builder = builder_class(**kwargs) - if ( - not original_builder - and not ( - original_features == builder.NAME - or ( - isinstance(original_features, str) - and original_features in builder.ALTERNATE_NAMES - ) - ) - and markup - ): - # The user did not tell us which TreeBuilder to use, - # and we had to guess. Issue a warning. - if builder.is_xml: - markup_type = "XML" - else: - markup_type = "HTML" - - # This code adapted from warnings.py so that we get the same line - # of code as our warnings.warn() call gets, even if the answer is wrong - # (as it may be in a multithreading situation). - caller = None - try: - caller = sys._getframe(1) - except ValueError: - pass - if caller: - globals = caller.f_globals - line_number = caller.f_lineno - else: - globals = sys.__dict__ - line_number = 1 - filename = globals.get("__file__") - if filename: - fnl = filename.lower() - if fnl.endswith((".pyc", ".pyo")): - filename = filename[:-1] - if filename: - # If there is no filename at all, the user is most likely in a REPL, - # and the warning is not necessary. - values = dict( - filename=filename, - line_number=line_number, - parser=builder.NAME, - markup_type=markup_type, - ) - warnings.warn( - GuessedAtParserWarning.MESSAGE % values, - GuessedAtParserWarning, - stacklevel=2, - ) - else: - if kwargs: - warnings.warn( - "Keyword arguments to the BeautifulSoup constructor will be ignored. These would normally be passed into the TreeBuilder constructor, but a TreeBuilder instance was passed in as `builder`." - ) - - self.builder = builder - self.is_xml = builder.is_xml - self.known_xml = self.is_xml - self._namespaces = dict() - self.parse_only = parse_only - - if hasattr(markup, "read"): # It's a file-type object. - markup = markup.read() - elif not isinstance(markup, (bytes, str)) and not hasattr(markup, "__len__"): - raise TypeError( - f"Incoming markup is of an invalid type: {markup!r}. Markup must be a string, a bytestring, or an open filehandle." - ) - elif len(markup) <= 256 and ( - (isinstance(markup, bytes) and b"<" not in markup and b"\n" not in markup) - or (isinstance(markup, str) and "<" not in markup and "\n" not in markup) - ): - # Issue warnings for a couple beginner problems - # involving passing non-markup to Beautiful Soup. - # Beautiful Soup will still parse the input as markup, - # since that is sometimes the intended behavior. - if not self._markup_is_url(markup): - self._markup_resembles_filename(markup) - - # At this point we know markup is a string or bytestring. If - # it was a file-type object, we've read from it. - markup = cast(_RawMarkup, markup) - - rejections = [] - success = False - for ( - self.markup, - self.original_encoding, - self.declared_html_encoding, - self.contains_replacement_characters, - ) in self.builder.prepare_markup( - markup, from_encoding, exclude_encodings=exclude_encodings - ): - self.reset() - self.builder.initialize_soup(self) - try: - self._feed() - success = True - break - except ParserRejectedMarkup as e: - rejections.append(e) - pass - - if not success: - other_exceptions = [str(e) for e in rejections] - raise ParserRejectedMarkup( - "The markup you provided was rejected by the parser. Trying a different parser or a different encoding may help.\n\nOriginal exception(s) from parser:\n " - + "\n ".join(other_exceptions) - ) - - # Clear out the markup and remove the builder's circular - # reference to this object. - self.markup = None - self.builder.soup = None - - def copy_self(self) -> "BeautifulSoup": - """Create a new BeautifulSoup object with the same TreeBuilder, - but not associated with any markup. - - This is the first step of the deepcopy process. - """ - clone = type(self)("", None, self.builder) - - # Keep track of the encoding of the original document, - # since we won't be parsing it again. - clone.original_encoding = self.original_encoding - return clone - - def __getstate__(self) -> Dict[str, Any]: - # Frequently a tree builder can't be pickled. - d = dict(self.__dict__) - if "builder" in d and d["builder"] is not None and not self.builder.picklable: - d["builder"] = type(self.builder) - # Store the contents as a Unicode string. - d["contents"] = [] - d["markup"] = self.decode() - - # If _most_recent_element is present, it's a Tag object left - # over from initial parse. It might not be picklable and we - # don't need it. - if "_most_recent_element" in d: - del d["_most_recent_element"] - return d - - def __setstate__(self, state: Dict[str, Any]) -> None: - # If necessary, restore the TreeBuilder by looking it up. - self.__dict__ = state - if isinstance(self.builder, type): - self.builder = self.builder() - elif not self.builder: - # We don't know which builder was used to build this - # parse tree, so use a default we know is always available. - self.builder = HTMLParserTreeBuilder() - self.builder.soup = self - self.reset() - self._feed() - - @classmethod - @_deprecated( - replaced_by="nothing (private method, will be removed)", version="4.13.0" - ) - def _decode_markup(cls, markup: _RawMarkup) -> str: - """Ensure `markup` is Unicode so it's safe to send into warnings.warn. - - warnings.warn had this problem back in 2010 but fortunately - not anymore. This has not been used for a long time; I just - noticed that fact while working on 4.13.0. - """ - if isinstance(markup, bytes): - decoded = markup.decode("utf-8", "replace") - else: - decoded = markup - return decoded - - @classmethod - def _markup_is_url(cls, markup: _RawMarkup) -> bool: - """Error-handling method to raise a warning if incoming markup looks - like a URL. - - :param markup: A string of markup. - :return: Whether or not the markup resembled a URL - closely enough to justify issuing a warning. - """ - problem: bool = False - if isinstance(markup, bytes): - problem = ( - any(markup.startswith(prefix) for prefix in (b"http:", b"https:")) - and b" " not in markup - ) - elif isinstance(markup, str): - problem = ( - any(markup.startswith(prefix) for prefix in ("http:", "https:")) - and " " not in markup - ) - else: - return False - - if not problem: - return False - warnings.warn( - MarkupResemblesLocatorWarning.URL_MESSAGE % dict(what="URL"), - MarkupResemblesLocatorWarning, - stacklevel=3, - ) - return True - - @classmethod - def _markup_resembles_filename(cls, markup: _RawMarkup) -> bool: - """Error-handling method to issue a warning if incoming markup - resembles a filename. - - :param markup: A string of markup. - :return: Whether or not the markup resembled a filename - closely enough to justify issuing a warning. - """ - markup_b: bytes - - # We're only checking ASCII characters, so rather than write - # the same tests twice, convert Unicode to a bytestring and - # operate on the bytestring. - if isinstance(markup, str): - markup_b = markup.encode("utf8") - else: - markup_b = markup - - # Step 1: does it end with a common textual file extension? - filelike = False - lower = markup_b.lower() - extensions = [b".html", b".htm", b".xml", b".xhtml", b".txt"] - if any(lower.endswith(ext) for ext in extensions): - filelike = True - if not filelike: - return False - - # Step 2: it _might_ be a file, but there are a few things - # we can look for that aren't very common in filenames. - - # Characters that have special meaning to Unix shells. (< was - # excluded before this method was called.) - # - # Many of these are also reserved characters that cannot - # appear in Windows filenames. - for byte in markup_b: - if byte in b"?*#&;>$|": - return False - - # Two consecutive forward slashes (as seen in a URL) or two - # consecutive spaces (as seen in fixed-width data). - # - # (Paths to Windows network shares contain consecutive - # backslashes, so checking that doesn't seem as helpful.) - if b"//" in markup_b: - return False - if b" " in markup_b: - return False - - # A colon in any position other than position 1 (e.g. after a - # Windows drive letter). - if markup_b.startswith(b":"): - return False - colon_i = markup_b.rfind(b":") - if colon_i not in (-1, 1): - return False - - # Step 3: If it survived all of those checks, it's similar - # enough to a file to justify issuing a warning. - warnings.warn( - MarkupResemblesLocatorWarning.FILENAME_MESSAGE % dict(what="filename"), - MarkupResemblesLocatorWarning, - stacklevel=3, - ) - return True - - def _feed(self) -> None: - """Internal method that parses previously set markup, creating a large - number of Tag and NavigableString objects. - """ - # Convert the document to Unicode. - self.builder.reset() - - if self.markup is not None: - self.builder.feed(self.markup) - # Close out any unfinished strings and close all the open tags. - self.endData() - while ( - self.currentTag is not None and self.currentTag.name != self.ROOT_TAG_NAME - ): - self.popTag() - - def reset(self) -> None: - """Reset this object to a state as though it had never parsed any - markup. - """ - Tag.__init__(self, self, self.builder, self.ROOT_TAG_NAME) - self.hidden = True - self.builder.reset() - self.current_data = [] - self.currentTag = None - self.tagStack = [] - self.open_tag_counter = Counter() - self.preserve_whitespace_tag_stack = [] - self.string_container_stack = [] - self._most_recent_element = None - self.pushTag(self) - - def new_tag( - self, - name: str, - namespace: Optional[str] = None, - nsprefix: Optional[str] = None, - attrs: Optional[_RawAttributeValues] = None, - sourceline: Optional[int] = None, - sourcepos: Optional[int] = None, - string: Optional[str] = None, - **kwattrs: _RawAttributeValue, - ) -> Tag: - """Create a new Tag associated with this BeautifulSoup object. - - :param name: The name of the new Tag. - :param namespace: The URI of the new Tag's XML namespace, if any. - :param prefix: The prefix for the new Tag's XML namespace, if any. - :param attrs: A dictionary of this Tag's attribute values; can - be used instead of ``kwattrs`` for attributes like 'class' - that are reserved words in Python. - :param sourceline: The line number where this tag was - (purportedly) found in its source document. - :param sourcepos: The character position within ``sourceline`` where this - tag was (purportedly) found. - :param string: String content for the new Tag, if any. - :param kwattrs: Keyword arguments for the new Tag's attribute values. - - """ - attr_container = self.builder.attribute_dict_class(**kwattrs) - if attrs is not None: - attr_container.update(attrs) - tag_class = self.element_classes.get(Tag, Tag) - - # Assume that this is either Tag or a subclass of Tag. If not, - # the user brought type-unsafety upon themselves. - tag_class = cast(Type[Tag], tag_class) - tag = tag_class( - None, - self.builder, - name, - namespace, - nsprefix, - attr_container, - sourceline=sourceline, - sourcepos=sourcepos, - ) - - if string is not None: - tag.string = string - return tag - - def string_container( - self, base_class: Optional[Type[NavigableString]] = None - ) -> Type[NavigableString]: - """Find the class that should be instantiated to hold a given kind of - string. - - This may be a built-in Beautiful Soup class or a custom class passed - in to the BeautifulSoup constructor. - """ - container = base_class or NavigableString - - # The user may want us to use some other class (hopefully a - # custom subclass) instead of the one we'd use normally. - container = cast( - Type[NavigableString], self.element_classes.get(container, container) - ) - - # On top of that, we may be inside a tag that needs a special - # container class. - if self.string_container_stack and container is NavigableString: - container = self.builder.string_containers.get( - self.string_container_stack[-1].name, container - ) - return container - - def new_string( - self, s: str, subclass: Optional[Type[NavigableString]] = None - ) -> NavigableString: - """Create a new `NavigableString` associated with this `BeautifulSoup` - object. - - :param s: The string content of the `NavigableString` - :param subclass: The subclass of `NavigableString`, if any, to - use. If a document is being processed, an appropriate - subclass for the current location in the document will - be determined automatically. - """ - container = self.string_container(subclass) - return container(s) - - def insert_before(self, *args: _InsertableElement) -> List[PageElement]: - """This method is part of the PageElement API, but `BeautifulSoup` doesn't implement - it because there is nothing before or after it in the parse tree. - """ - raise NotImplementedError( - "BeautifulSoup objects don't support insert_before()." - ) - - def insert_after(self, *args: _InsertableElement) -> List[PageElement]: - """This method is part of the PageElement API, but `BeautifulSoup` doesn't implement - it because there is nothing before or after it in the parse tree. - """ - raise NotImplementedError("BeautifulSoup objects don't support insert_after().") - - def popTag(self) -> Optional[Tag]: - """Internal method called by _popToTag when a tag is closed. - - :meta private: - """ - if not self.tagStack: - # Nothing to pop. This shouldn't happen. - return None - tag = self.tagStack.pop() - if tag.name in self.open_tag_counter: - self.open_tag_counter[tag.name] -= 1 - if ( - self.preserve_whitespace_tag_stack - and tag == self.preserve_whitespace_tag_stack[-1] - ): - self.preserve_whitespace_tag_stack.pop() - if self.string_container_stack and tag == self.string_container_stack[-1]: - self.string_container_stack.pop() - # print("Pop", tag.name) - if self.tagStack: - self.currentTag = self.tagStack[-1] - return self.currentTag - - def pushTag(self, tag: Tag) -> None: - """Internal method called by handle_starttag when a tag is opened. - - :meta private: - """ - # print("Push", tag.name) - if self.currentTag is not None: - self.currentTag.contents.append(tag) - self.tagStack.append(tag) - self.currentTag = self.tagStack[-1] - if tag.name != self.ROOT_TAG_NAME: - self.open_tag_counter[tag.name] += 1 - if tag.name in self.builder.preserve_whitespace_tags: - self.preserve_whitespace_tag_stack.append(tag) - if tag.name in self.builder.string_containers: - self.string_container_stack.append(tag) - - def endData(self, containerClass: Optional[Type[NavigableString]] = None) -> None: - """Method called by the TreeBuilder when the end of a data segment - occurs. - - :param containerClass: The class to use when incorporating the - data segment into the parse tree. - - :meta private: - """ - if self.current_data: - current_data = "".join(self.current_data) - # If whitespace is not preserved, and this string contains - # nothing but ASCII spaces, replace it with a single space - # or newline. - if not self.preserve_whitespace_tag_stack: - strippable = True - for i in current_data: - if i not in self.ASCII_SPACES: - strippable = False - break - if strippable: - if "\n" in current_data: - current_data = "\n" - else: - current_data = " " - - # Reset the data collector. - self.current_data = [] - - # Should we add this string to the tree at all? - if ( - self.parse_only - and len(self.tagStack) <= 1 - and (not self.parse_only.allow_string_creation(current_data)) - ): - return - - containerClass = self.string_container(containerClass) - o = containerClass(current_data) - self.object_was_parsed(o) - - def object_was_parsed( - self, - o: PageElement, - parent: Optional[Tag] = None, - most_recent_element: Optional[PageElement] = None, - ) -> None: - """Method called by the TreeBuilder to integrate an object into the - parse tree. - - :meta private: - """ - if parent is None: - parent = self.currentTag - assert parent is not None - previous_element: Optional[PageElement] - if most_recent_element is not None: - previous_element = most_recent_element - else: - previous_element = self._most_recent_element - - next_element = previous_sibling = next_sibling = None - if isinstance(o, Tag): - next_element = o.next_element - next_sibling = o.next_sibling - previous_sibling = o.previous_sibling - if previous_element is None: - previous_element = o.previous_element - - fix = parent.next_element is not None - - o.setup(parent, previous_element, next_element, previous_sibling, next_sibling) - - self._most_recent_element = o - parent.contents.append(o) - - # Check if we are inserting into an already parsed node. - if fix: - self._linkage_fixer(parent) - - def _linkage_fixer(self, el: Tag) -> None: - """Make sure linkage of this fragment is sound.""" - - first = el.contents[0] - child = el.contents[-1] - descendant: PageElement = child - - if child is first and el.parent is not None: - # Parent should be linked to first child - el.next_element = child - # We are no longer linked to whatever this element is - prev_el = child.previous_element - if prev_el is not None and prev_el is not el: - prev_el.next_element = None - # First child should be linked to the parent, and no previous siblings. - child.previous_element = el - child.previous_sibling = None - - # We have no sibling as we've been appended as the last. - child.next_sibling = None - - # This index is a tag, dig deeper for a "last descendant" - if isinstance(child, Tag) and child.contents: - # _last_decendant is typed as returning Optional[PageElement], - # but the value can't be None here, because el is a Tag - # which we know has contents. - descendant = cast(PageElement, child._last_descendant(False)) - - # As the final step, link last descendant. It should be linked - # to the parent's next sibling (if found), else walk up the chain - # and find a parent with a sibling. It should have no next sibling. - descendant.next_element = None - descendant.next_sibling = None - - target: Optional[Tag] = el - while True: - if target is None: - break - elif target.next_sibling is not None: - descendant.next_element = target.next_sibling - target.next_sibling.previous_element = child - break - target = target.parent - - def _popToTag( - self, name: str, nsprefix: Optional[str] = None, inclusivePop: bool = True - ) -> Optional[Tag]: - """Pops the tag stack up to and including the most recent - instance of the given tag. - - If there are no open tags with the given name, nothing will be - popped. - - :param name: Pop up to the most recent tag with this name. - :param nsprefix: The namespace prefix that goes with `name`. - :param inclusivePop: It this is false, pops the tag stack up - to but *not* including the most recent instqance of the - given tag. - - :meta private: - """ - # print("Popping to %s" % name) - if name == self.ROOT_TAG_NAME: - # The BeautifulSoup object itself can never be popped. - return None - - most_recently_popped = None - - stack_size = len(self.tagStack) - for i in range(stack_size - 1, 0, -1): - if not self.open_tag_counter.get(name): - break - t = self.tagStack[i] - if name == t.name and nsprefix == t.prefix: - if inclusivePop: - most_recently_popped = self.popTag() - break - most_recently_popped = self.popTag() - - return most_recently_popped - - def handle_starttag( - self, - name: str, - namespace: Optional[str], - nsprefix: Optional[str], - attrs: _RawAttributeValues, - sourceline: Optional[int] = None, - sourcepos: Optional[int] = None, - namespaces: Optional[Dict[str, str]] = None, - ) -> Optional[Tag]: - """Called by the tree builder when a new tag is encountered. - - :param name: Name of the tag. - :param nsprefix: Namespace prefix for the tag. - :param attrs: A dictionary of attribute values. Note that - attribute values are expected to be simple strings; processing - of multi-valued attributes such as "class" comes later. - :param sourceline: The line number where this tag was found in its - source document. - :param sourcepos: The character position within `sourceline` where this - tag was found. - :param namespaces: A dictionary of all namespace prefix mappings - currently in scope in the document. - - If this method returns None, the tag was rejected by an active - `ElementFilter`. You should proceed as if the tag had not occurred - in the document. For instance, if this was a self-closing tag, - don't call handle_endtag. - - :meta private: - """ - # print("Start tag %s: %s" % (name, attrs)) - self.endData() - - if ( - self.parse_only - and len(self.tagStack) <= 1 - and not self.parse_only.allow_tag_creation(nsprefix, name, attrs) - ): - return None - - tag_class = self.element_classes.get(Tag, Tag) - # Assume that this is either Tag or a subclass of Tag. If not, - # the user brought type-unsafety upon themselves. - tag_class = cast(Type[Tag], tag_class) - tag = tag_class( - self, - self.builder, - name, - namespace, - nsprefix, - attrs, - self.currentTag, - self._most_recent_element, - sourceline=sourceline, - sourcepos=sourcepos, - namespaces=namespaces, - ) - if tag is None: - return tag - if self._most_recent_element is not None: - self._most_recent_element.next_element = tag - self._most_recent_element = tag - self.pushTag(tag) - return tag - - def handle_endtag(self, name: str, nsprefix: Optional[str] = None) -> None: - """Called by the tree builder when an ending tag is encountered. - - :param name: Name of the tag. - :param nsprefix: Namespace prefix for the tag. - - :meta private: - """ - # print("End tag: " + name) - self.endData() - self._popToTag(name, nsprefix) - - def handle_data(self, data: str) -> None: - """Called by the tree builder when a chunk of textual data is - encountered. - - :meta private: - """ - self.current_data.append(data) - - def decode( - self, - indent_level: Optional[int] = None, - eventual_encoding: _Encoding = DEFAULT_OUTPUT_ENCODING, - formatter: Union[Formatter, str] = "minimal", - iterator: Optional[Iterator[PageElement]] = None, - **kwargs: Any, - ) -> str: - """Returns a string representation of the parse tree - as a full HTML or XML document. - - :param indent_level: Each line of the rendering will be - indented this many levels. (The ``formatter`` decides what a - 'level' means, in terms of spaces or other characters - output.) This is used internally in recursive calls while - pretty-printing. - :param eventual_encoding: The encoding of the final document. - If this is None, the document will be a Unicode string. - :param formatter: Either a `Formatter` object, or a string naming one of - the standard formatters. - :param iterator: The iterator to use when navigating over the - parse tree. This is only used by `Tag.decode_contents` and - you probably won't need to use it. - """ - if self.is_xml: - # Print the XML declaration - encoding_part = "" - declared_encoding: Optional[str] = eventual_encoding - if eventual_encoding in PYTHON_SPECIFIC_ENCODINGS: - # This is a special Python encoding; it can't actually - # go into an XML document because it means nothing - # outside of Python. - declared_encoding = None - if declared_encoding is not None: - encoding_part = ' encoding="%s"' % declared_encoding - prefix = '\n' % encoding_part - else: - prefix = "" - - # Prior to 4.13.0, the first argument to this method was a - # bool called pretty_print, which gave the method a different - # signature from its superclass implementation, Tag.decode. - # - # The signatures of the two methods now match, but just in - # case someone is still passing a boolean in as the first - # argument to this method (or a keyword argument with the old - # name), we can handle it and put out a DeprecationWarning. - warning: Optional[str] = None - if isinstance(indent_level, bool): - if indent_level is True: - indent_level = 0 - elif indent_level is False: - indent_level = None - warning = f"As of 4.13.0, the first argument to BeautifulSoup.decode has been changed from bool to int, to match Tag.decode. Pass in a value of {indent_level} instead." - else: - pretty_print = kwargs.pop("pretty_print", None) - assert not kwargs - if pretty_print is not None: - if pretty_print is True: - indent_level = 0 - elif pretty_print is False: - indent_level = None - warning = f"As of 4.13.0, the pretty_print argument to BeautifulSoup.decode has been removed, to match Tag.decode. Pass in a value of indent_level={indent_level} instead." - - if warning: - warnings.warn(warning, DeprecationWarning, stacklevel=2) - elif indent_level is False or pretty_print is False: - indent_level = None - return prefix + super(BeautifulSoup, self).decode( - indent_level, eventual_encoding, formatter, iterator - ) - - -# Aliases to make it easier to get started quickly, e.g. 'from bs4 import _soup' -_s = BeautifulSoup -_soup = BeautifulSoup - - -class BeautifulStoneSoup(BeautifulSoup): - """Deprecated interface to an XML parser.""" - - def __init__(self, *args: Any, **kwargs: Any): - kwargs["features"] = "xml" - warnings.warn( - "The BeautifulStoneSoup class was deprecated in version 4.0.0. Instead of using " - 'it, pass features="xml" into the BeautifulSoup constructor.', - DeprecationWarning, - stacklevel=2, - ) - super(BeautifulStoneSoup, self).__init__(*args, **kwargs) - - -# If this file is run as a script, act as an HTML pretty-printer. -if __name__ == "__main__": - import sys - - soup = BeautifulSoup(sys.stdin) - print((soup.prettify())) diff --git a/.venv/Lib/site-packages/bs4/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index d92a27517e4104b9424c07210964fbae36bf7918..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39622 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 Nn{(xyS-xNB{{^B7P|*MY diff --git a/.venv/Lib/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc deleted file mode 100644 index 6010cc4649d57105eff7bace582a261507439890..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3750 zcmb7`O>7&-6@X`d_$%tya;(UXJWX0#geA(cjml6AH;xT7O>Cv8T-X(uQY-F|TzR?6 z&g@E|s-!Alz#>r8IW&lYrhpGVP_TjMkVB3-2FPU%Uxcj>1=>q)4CE%QPknEfe{yU$ z8DQU=o!>Vz-+MD(_Vy+Tq@QPhTbfT0@=yF}rJx3Wb{!BO6P?TxUD9P!nwJ7C&&!|{ zQz@(SYB@3=k%+Fcs2+hY%A$p+9=op2$GXe(IEyf~C^5AlzX+oi;(7ww#Pwv@2kW6< z50oXUayq5mlL&c}nH9!q!L{;^VOxS0Y)*An;ViFVK_;2JTrvbTEQj%emS+@y9Kp;2 zbuHm&izcI*rPH!jrTLO(6&YPIoRaN2bVcKqVHGp= z1I7Z&e__#z#vLQ?ni`*=Wm`DZE`SZNhM;ZHrrHV^{)ENUw(>0b2Gd-}D7Yq_v)u~S zxm^+MsnCXBR$-kMJ(+p+)d?yL=+jknBB`^2VWHu4;dQ54!JTMrEYru+P!9{!9Ghq8 znUdpF#LU!Gg;hkR5{#R%c@h67k53;zF?Dt!m;4IhnN7>Sa?Yyy@$;H#;`aM-+thQG zR)(C#R>E9t88!~iFRx&yW{QBu|K0aM+#olk8}i2l0SuEaIdUsskT;|avLP1~UA~^W z+bn)xSyPtOR-2C26(`#I18miT+U_0M+k1|rqpMfWnFgG+Z2>xt!;MAPVH6iY9XJp` z1&%p5w$3??5oN6*jA8uV@I0~) zzTFatj}%yNyLPF)+;(g5!kYY7qRTZ2q*7Brs(*_)?M3U6d(peiO_hifYxP_sHR*11 zJXmDxao=78SI5rf^Gpa_Vh01T-v?Ms~b46Bw!{%9*vx+UU<*>{#Ccy#+YBS(?%h`*@ zVpbRqo2-CYT9JwDqBu2`Yb_hYN~P*YG^Ajaw#%8G3yLylOgpcc;%p}PJ%k3m0pdUF zR0P;ZQ0wU?RoE=vS+zodD&ZD@lx+SOpWav82NWhO(Y*B$-sdR zom*EQ^dIr!M|NQp;zyP>(`B>y?$d8mvIH%@7bQrB9I&F))E_{Jye75yK~8uNOt|{e z6%PCLEH-!w+VEZ!eJJ`-41h?h9MR^(DE5Q!W1@Mm5q$Q^vaHBx}Ll2rB-E3kwT0Fx?;g4m>smOo%!Ts1FAE(PhqPJwi*h`p;c;d{bFD;M@;sFR5ULL zsjow(6;dIP!e5wlxht=9@`Y$SM5@1-A-?bBGu?gCt>?p2!^KabySNAfK>b&IAPg4c^^tmVYifIZd(?Z| z@Rok(8QkN-OF3PbHXv9W{nJV_T+~&se|jr=zkk|`Plv!t0jB&%I0Ht=4v3@AHjj@( z%ahmzR}4fpqOr*7khatJUP0(ifA-3^sJc<}dmzLHmqBi^x+hfO%mH%8A%n=l^YIzL z!97eiq=Kv~fS9}{17a#5hWqzjw9v_di_(J3NAeALmOlTgtdYA-G+}g|r4x0r(tuC*&b;vgT-k`r**aPkW_wIYKL7BWpq0d#%f)Ca)2I zUJ9Y-N1;)7u=V4);GLDr1z|TG=`#NqwB>0O!Bx69+WIMcYv!6)^y;ZDZaUXq>!M_x zqV8T7VC)v*a3S{Yzj>*4X=iAne)-dPH{Y$l^ZC!dcy3XSYUIX#pb@DJVbn|fS@U7toi7^PciS!)>d?Jy)Cj#{u zM(soz;&JkDPz_EpaL9`vY`G-bkXAYy&QIXr=pgNDqNmFmj;@HW2{8r&=5NS7kwc%v z8wAvytKXn%jFQxTPaO`YNcyo{PPg-L*64A;jq69l7kwBI&;(9V;O!GQd@#)>2}THa zCw``E>#oVp@@Z&fh`k_LDB1{(_MmuRSuWdi+=NbiQ&U?0wHEZvX1xEp~cjj=vy|E;+O0ab@P4%F7^ JN2mhh{s+@#nWX># diff --git a/.venv/Lib/site-packages/bs4/__pycache__/_typing.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/_typing.cpython-312.pyc deleted file mode 100644 index 7589facfdd678d20c17e72460dbb85717b62468b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3552 zcmaJ@O;8)j6>g12{|FGj5fK!kNac5!5F3EbDp9Y!)`pFc&Dj` z**)hNKgf6=1lZ+2L zt4EmBP9>#7OfjjG=^#QS;;czCzRTIGAEzDu6yv)c`xHLq@TVEyWAjQc?sxc6#`iJa ztMqQT@R*~?FipRsi5}COVVan&!TrZHXPIWe_QLAk=G1-6sd$!I3_2EBe8%xM&iJ7g zf7ao1j30LRaU8(o?ELI=I>)qeN1Fp}?wEFhX%kF4A%4Xqfk{4yZNl+zp7BY04`qa% z?j++nlE+pzri%0{82 z$wkYzA{(IAtnkCfEA!Ia?fJR8ca|3{&m#>CGG41|#xO`>y<*_s%Eby^Ea-;Sy)3I( zFUxtXw6s>ovi!2JLH#^{1>hvKB5&aNB37|xSbL{Buge7MIwaIA-J3tn2xX^?LTUYboHvA5n}z(Qke4+<&gXI25OBfR#6(!B z8k;3;R2SAOg`zQD(1HRy&j`*rwR`65pl5{=5nzp=7t{jy6`nnV2=MD?Eek=x&kGt> zg!L*lWIGv~1)_|XWnxre0dW>UbzeaJa?Hf?>UK@t<&tiBv8J$*V535`Jl`y&Gt!oI zNXhr8iaxlOKcEb6@j5O(CsAMtEgu;G(5Vqk=06YTuC6`OG11qSWb&e-uj!=<$>TMG z!O@y(b4FoYH)I2}xtCabxwcqXU(*W)hS*uG`r5iabxty>^c~BUs}MDoNq+N9@_!#h z&Ni8%(Rcv1&@a)!Lztkvi{i28L|SARG$am?aghWJIyD!F0BHHj_DlU{8B!varo)K0eFi(@ota5(T1*G|K#R8LkE4a z1{;NxJx*R^<1c~8cIt=WLl4+A{K(sWz$bUQ|H>y1-5~s(x07L;TOHCJEniaMT-f=R zA){6Kl`{`W^Pp7doej38y45MQuK5aq*Y>p)K4KoNE?SWzvDsK+;O8YIiermBm2 zY_$v4Ox{d8$|tPbJb@Bsh1SBO-tsgn{Ce?ItNYiaPCB84knTxGkjqIzx8ij1Jpv6O z53S)?BV&>2q?_*31?j-8Flbk6cCwgstgkJ}Mt<{FMa$E6N_y#q%g8ZHI~c3?7}YY=Gj5hT%Y}5& zghJ9it(AQQ3b|C$jU(z!U#qo0IcE73-j@3nOsck4U(Q^#B6e$#@M{BWv>oe&UTQ+y z5TSR_^4b>m_3=^KPa!~oekMqW0=r>hI%}uU0bqro_vEnswP7y-iBKKQz)q-#&gco* zcP;}n%d=iJuuigc-XTe{rj?+<(ZD2$&>Kl|6wXnYpzsxi^Asj2(6&V`P`F6p5(U~& z$Q1yKUoVx4=1aErppj$!$y?N;u60{9#Z0iY&)8bEyHGw1VoKO=xf58}H2&4pYeyU{~18iAI< zbvG!{7(wyW?qtnVBYUY2uRd}gFZ?-Rre^BHvs)e8v3)cPy(Sjl$?sm+`Mw^_Yz5!l z*+&^@SJA<(z`HB^XrSRmvE**79zAO-&w?^BVxrFN%sxtjb||qGeplT`ahMBfGd;DZ zn(4WE;--lr+pxn;;K#DHCG*-{Gkdo_x@e-<4)BYOPLxcWsB0TsreIgkoU7qRuAc43 zhlq1=jdm8hIW}#krt8Dk?SQXCzzLdChnc!mk6(5IxeV*a&ztAx&4q8x^WWC9-yj=%Jn6Z7@aTTWEB8gV3y)p~2by`EaQ zp19~_aj_9Zsk61Y+J(Jz?OJ{0l8Jh@3;XC2?C+HL)t>(04<8?XS>97;YUj*ri{_cd zdV0x3eLE1<66`jbt=%)P-#4@O>!(*u6y3?}qg58|0Y9*F+dOrxJ~VCe)9~3yax84S zENv(?cEAtqY?`Cr)Z;fy{svg2zyjiFS_o54*ppEF^jOVpj?b85GxgN0iF&u;ux6oN n0|_&6s~%g}3cY*0j}{IRqqR^y(OfxoFgQsM_HSsCec}EK^4{ow diff --git a/.venv/Lib/site-packages/bs4/__pycache__/_warnings.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/_warnings.cpython-312.pyc deleted file mode 100644 index 3988abf8f814133a4bca16f9effe253f527af4ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5603 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%0Ai9R;KEqfHka zo=bT}W5uHzr<~<)WVuK4KXlJn`3LWd<`j$`8ohtCcDcrO)| zkK78qZOk-g9$hoCm3-pzNADha=ahZ^n+v7voIj`#?CaJGiRVe#xuX@M%SY}WTX;UJ zCR(&$_6@U>(qjn|dfQjO$y{m3qGTsD)daUWVH&m$+xjZOwXBI#q-1k~Go{KUTLz(V=^RVv zYs0q0`BLC}h8C&EqXvd9m53z+!Ejn%R#Kc3LHrYOI9rL&EQ0kSP3FVphV9^f8L4d< z;Dpxa()D}t2}%Xn)RKpDfl^pLklHpo^}F+iGLPiwHAq}_?OwKXtulr(lod(On~``T z{oXh`DkIg&O?2R$o(4~mam3IUuf1EVG?3#xlu)Vx2`NXjc1Nybs5 zVx+}h&rnKn^wVydde~wSDL{H}(yW|XDb#-qYq&|acq#~rtI>LT6J7s3)WK^Ln=O;h zVd66I>e#oCYt3$h#)+|X15r!7nJyf(dNj}zWDz;H6n233cyO*MUK45PLEcbAR~X9i zI6~hSzO#u^lV2%SMzAoWPba-6U5vJ&y2dl>-4TmgUF?~PJ9h>9`;xr60}|L^fcRhc z$IsI5nN3O!29{C{K!?v@N4|`f!y5Xb}wqu|S7L5tb{~Q&WDfWfaO;raiWr1-sVSy&2rco@N{lYPd zpY2j=k^acWd;(TLcn^gfD3KaY`w4fT7Z6CER&#`I>WK-lp3qN`c8Nq zx|qA*(f&y8qEk(801HKOD@U3x<>Zgo_6<9(BNzPxL^Z+h`~Nhe_b{$N`03h4MuLrwNdSg4G{|X5KleBJQw4yq?;-=`*mC=;|`{sQc3xEX{5L=p2c*wG=I@}d!%gHRW294s0+Q*)|zPk zf@$jlXeiUx@@V0Lv4Kb-g1zwgdhecS(ZcbJNKx&ywHEd<(24lC)de3X`$S2^14k#| z=bB#5c&UZaSHo8+1Ugt+cHF$&Ry?+5d`Dzn!xahmRXCZ6(0G?{N2;_fm?(%#xJ<4- zSMaj^)so2O)~U6vk(F&%D3o%*YYA909UU-Wtr>l)J;dn zTNs+*He`iM5V<)ChbMA#N|)K?i4+CdjuTBYjMz*AbLd!Cw(NxKQwH3GGBwvHo8Lis zL1%5Cs~uQ2V>Z82i{W!|QHGvUI7nr|b;;>>2zMhbrJHlQP=WxHmRe|}alrY>gV-W}G3VeXgUeNUk|R}#T!Hk7@~mQ{PA zXca=|1tfWqy!a85TrJlCdgWTcC2}2Lz1#q}R9*(STwVdVQeFkPTD}SJW_bOMZw4BvHAFW4jX4)IkoW;b)0W#$_YCEp=KHNdC^_{?%$aewO%Xb4VmG1#uF1G`& zlEx?x%%_?caaOKLW4# z&7&C@B@1|zXrlw%wX2*aBb+A3;CI)q}rs4y^!I z$ygPzMT{*5R?S!qFfU`Zz?Lvp2dtj424G7WTLx@7V=I8IWNa0%)r{Q)>}JN+09(u0 zI$-M=+W_nq#x?@m#MowFjpA(s+k(F)4&Mr_nXzrawlj7supNx;1h$K@-N5!R)&guV zW48gjov}NBwKCQQY#(EH0t5E~yc>V_FxC$2UdHwVJHXg|z&aQ^2+YUWAz+?~s+2lffZ9tHME#y$n?F~-J$J@&cgHflQo>KP9IEU;%8dk)y=82dc1=NX#>_5x#H0QN=3z69*cjD1CZCtqJg$T`Md z0`^tLz6R{;jC}*xHyQgDu$LM8Hn8t7_FZ7$lz^|`?|Y2>Ij~oax_%$jUvT&jfc+(7 ze+BHX8T%VxQ;bD`oo8$s*agO31NKA4W`IQ*dmWg{*pGl+WbDVl{+6-719pkAp8)$Q zV?P7-24g=52A&D{5BU2>#$v$!iE4}MKjZIT@b|Cy`?p6e;BgDV<2=x0>HOuuu27hMZLdJuOi)*i_&2rqU(gjFvJvtB!SPk( zijLI3!QU_aR={8Roq)e)&C1$k2mV%)6Z)b7bIpHYTB2rYi)7-%G`>pAsT;MUn8}Zv z-0iThl6Q9FhPnlt91N1p>R5xLQ<&JNv5(CrY!N~M?31h+FWFs^Ci?tc7c$+$XrM3B z(QzeYaS~tk;4+Nc!2*!HTvx~6u%RirsP#d3%EQb=XZ0##?=WZI6X;Zep&$-v31Lk# ztQ|Hb4E?xMK>GrXR!J;P25^80j1~G`;dR1WLab-56Yi~AVi88(N4W9-dIQ5V%JaY8 z!2jzFtg(mx^#=Zb>kZ88O`Ikc!g0~-Xm>dr_UVgPb)M^T!JZz&N0+zB<2VH2o}2LV z#=Zgg^J)$j!j)KK*Scxka0!Pa2kgX}q!6~^g9rIzM0_9=%GUifzxG@zx8b2S;KR)H{WVmgegk6_Wv(ao>@3N`bM~#Tae%(DOE%hGa|buxIXfA` z!p<^R-&RF3m8|-GN7)|-Uz=kGA3muC3-TeuTYFo=8C7-7>3>)~W|O;Nkx%8W+6hI& z_z`Zw-_>z5`(Ki~u@Tu#?!!=3#1AK5N*zcge)x!r)ImA<7dBk25(|ybYB`ZE%}8e~ z5|T>=%An8Jq(7_0Bc)NdaGstAi=Fv8t}pC`Y;blkvzx<0l$7KYo#Y;7IDH`ASoCBU zYO+T2Z-AWt$h17?cZ5vUbAHKpk)>h#b#j)?$p#V*Vf9#s&A3jE6!+p2UKUoaXpW%^?q`aGK)mvP<-+bJ~Xv;+Xj+7^G z9g}T(55PxZ($IQF-_h%Q(lz^SFlCgEcY`)gytx6%o8GcbSd@*0rNLI-BbH!>V0Pro zt8Iu7%SU3j5d3=~95gjmJL~$6=G%5RHZ||TXQ>h&sAy>O<|u!G$537DuWKw4h17+b zx*fur5}&9?M|30({SS%pMxB_KLh#9gU^g#GsCJ>x<6|83Ld5z7tz=>Qg!b(Lq1mcA z`cWXpZFv<$&7$MOustZ;L7$dX(=}gtZ>I3+R5aB*)wowp{lcRJHg`#1;nIA6 zc|m5daMp~(@KI04Fb`qlH93;xOP;0V6J8cwST3$h*+(2M7z@Z{{9<0&qjyi|Ee3AC zSX>iz=0=@WQDb#?5uc=doBkTPI+o6eCZdajv3;a z_L1Z*J*X1>bSDm+h-_)a8OQn+a`F4rU{2Y;iH)zpJz{N@+>-`BGMEdb70a`FgH%tad_Q7j1#sHjuhftDT75O z`H!^i-MUwIkYJAjs7~y%fGu6TCr#HJlc(`?!n3YTY1|g7Do%cZFCZNOCltRut^9?* zR{EBbs6ej|8jf+umr(+y`ayis$k&tbP7nu;8=4Hez%8ykag`K`^$f)aWxN^U1ajup zIoI5gd=W^kQtf(_Y7O((VcBs|Aq|5WvDYSe=xYd2t;B!%OcpiEICF*0CJB)nJo8On zX~xkei0SADdwbf&N_Qdl?97AagYQ@A!#xOTd5{ip?O#ho{j87~Jv1mzLbeDZh;pBX+q z9C1})H_y{qk7rHDSUeuhx(K(uEb!##7U9bT(V}@XMN1+@OD6iy7p;mes2U%hyggEV z^Gx-|NcG0)>dlb_n_pfPS+IS~LZ4ls8|Bb3CkG~%M;5J~S+pUtXv6fPjgbW#U(Sy# zXhtgfw#rE6n_1E#?{j$*z0*}2M)yQZt7l3ZBBc$}rOQT}z#F+B3)dKjH;;(Z@&+?{ zeVz4?X1>0`jL_jgSGfL2AVeSOMK~RU9y&ajcA`FnK-EPb^k{8v>uB7)qp`KQ6{_we z-p3$5WgDztvu5?$`sGRZ3Uyv{OVi%1J6g84cJP<0aE{^~Z5_Ao+uPRMD!dHH{Rdry zPi>sFCyCxObJ#Bl4lAYNun8wW8nf?qW1}8igj4e)ZC{dwwYn7iD&;m4b~#RHP$=2Z zqESEX2fmV$x4yfPwBl5oHBgt8IEmht*v6Q0ONgPn;bVGfsT}rDdWtO&$s8|(bn6t( zchLIrZ2IO*{*Yyo{?6LG!Q)Xv3hlTRyM)4}dK=&~;}-g4_<+gyFu28slUSrieE3V- z46gGrnsR9tL~u`{$lru|f?;7zVvpKnQ%@p}y`-az$idH-#EErtX@Z4mSw-)HCp7ki zQAfk3@IJYRjJ0st#m?kzFlpwseBK+Ki%4+?5s7bW>pI%3lQgv_L50P0Fq1#nf@8A| zlGj%9BN+vtAiai5uTu@2bt?B&iwz}-JGX>L%Gca`vi`9HUT?OV$v#iSQ#)BxQPc4C z7r0xADJd(SKSPGZIZfhht4jz|9Z8?lQdsLDg-6Y3KGEstFM50Jf(ySvCH$P?@VToX z4#R`4O((aCJ({zpyzuNQm^BB+F~{_YFIl;O0Z5vPY-sNBV4TW88PMDX9e;nD(pt?FXc z;-_~$zH{PT(^Z?`oEAQ}MrXtIC3r&CtC-hmq&jx#>i44AhPEwhFG_3K-3u2x4(J{e;f2F(C zvZEhnQ|R5apMVZo)Vm}dU_f1p?H=sMk3_`%jRlGuY`Sd25H?2S4K`l>Q3fKu_(EQa zI34{NToTR0y><5250n^E43^C4Xo(NXeV@7+DInPQ%O59OHC8-+)3mF0%3jM8gHEGa zk%(|=)~mMyT<;{=5bb?UsSl_6Dgj=PdGP)nf@A25DtsCZ+uw9ESsf1R{n;-X8_Qs)S4lBMr|W%pf@uR)}fRty{EtSv_* zXSua$&daTx{4Nklzw5L#4URcK3=3oHsV>iPoB*8jhD;|+N;w@*kXpk?HDkcGC9^)O zNGfg9A6%O8jhdv=inY?*bUk9&_7V@K&-BEx2t(MEg-rl%?6|%`S~%NVy|%&Uc7v&V zaKtHfsM`i``Y*l{P7(!B|57Qj37Xw#N6{Kn7kE!6f9*ySvf4YmzIf(bDW$2wI%d@* z(Op$jy|NCEt(rPo@R_+Z*kDjo<);WzdI$^=(E`n5fAS=wQI~eQ(On{(wX9Ak>X{OMdzxgi?>WWn{Z}cR#DVl zbl%-Kw)L@HXLn7cKks_Rb zUNW|wY#*Q4dj+Qo6hS_@i{cI`Bl|M8cjsXH_L=pk*FSR0l+&a8`_39ER#cfsN*@ri zMTD?v4qukTHtdWf!H{Z>p3tAEk5T_&t&U3MU)a!gyUft=tfb*l8bil3wRo*+8ov*? zc?(TJbx`N(Kh{jTmYR7deQ$>G3K`Ke~?03J29v4L#1vKfghs4 zo{&$g)ylP8=0gaz?QQM}bR*?zQT;zrO`ACKPa&Obl_!?pycLl*Z{@Iu8IDr6o{;{8 zYlu_~axKRi&)>wc2Dufa^$@ne@B^=)NF4MXI!xs9l|=R$s|O`VKDFMG`BGN8D%}nXY^@?6NBc42F9M@wr2FR zs9N~2m+@!uDdr7~J;(5K3_m|;skuWWc%B0$Ra20W7tm_;jD0~hi4OZk)wGgBzQpj$ zJnvxiE2>G<^+hJnF?>lii2?OhCcidl-nfymuMb+5FI~mxHwYD_e{;~XQVabS$GxnY z#L)jXliy+ZU50NHD5}f2!)g(f`&nf!=EvHgW=B^{=I7U`5F5MhX1I1L4S%E2mBMme`feEswu$8zcTzc zhX2km&hWBo>SN>z!>bJ6WcUk)|Dl?es-^*N22;Oe_$!9LX80Dv|77?ZhX2Lzw+w%$ zyiR?8B>?LMKYh=0vG*9n$&bh0O9YvQzW3qSgNcYw#om`7J`;O?f*6l|AVEAH8zF-7 z|KRN<_RAd&r3RaEvzVaPC*W5j&koG!~; z@n|uhjL{w(jd&vVu>|o*jJAGgF&~N18kMNzqcK{l5)ltR5u+J_xc}p^PZ$v=zZ!eg zhTlLr1|>?s3(Dn^qLF8@29 zi9K!LPsb(*)SX567h+#D@Gr)`WZ++lec8aj9Q%rae!(cUdlhi}BbY2e?CeapbV6?<97zk4$FZ3BOI>^lbjp4fK{{JpV1 zGw=svuNe6IV&60H_s9O+z&{Xs)xbw$-#746F)}xC-M;(5*bfZ+L$SX!@P}fwuqM*{ zNsLz21pcQnntclV;TYMX1U?#z82IVfc?17&Y}&vdiLqsghT3;O5_`=E|7h%o2L7?w zjDeqtMGbr`MqEJL>ugLl@Q=qxQj73U#4Z~6qp=?w_$On3Yv7-X{hfh77Q1BNU)E zWB+2{&&B@Lz&{uJHv|8C?B5Oi`B>b*Cu5fl{Ds&R1OGzos)2to_NIYRUyS|Az|X~gZQw7(-ZJp7#{Sd5zb1K4A^w8m?}45I*@LRmq8h93e}5{|FFOME;80-6ZlPJjlhI&aUu z-EBLz+|$rOTXBxs~smeQnuTp;?F3;+$(^@I>&JDm9LVz|1*yy41&f z@vcd|9g#Op&JcAQO2Z))C^tCk^sHvQpTvOSR>ad2yx<2fY zPTxW_=(fO##L5cxpJRED_oC~zM~~it$p@UjB_@vR)8muYZ<_jHQ0k+@cgfbo3)`Up zjcF3Y~e4MepRJs691Ur-6YwQ@0q=Dlj(U?`YktEi~eA?&M1Fhuo5GtC^+r z5t!;696sv3pN?h@!|Wx#qio!d?rWI5v=$JjHsiD#{W0P7*@6#5(M#yb zsA9(BB~@EL2w~P)MM7Ch-We5=f;{ua=T}H|RQ2=JSRf7FHmfVsT1%qe>ffXiL!r|c9f_f! zKT1+JBXb4LJzB%38V#-zUoAv;Glo>Ea=5ki7uFySgIGxwUjfjfQ~<(pZGb{Z9ar%jW&<19Jj(BWUT*@;fegoyl3Y{i|37n&pO5|uNTk1oGy89rLO_y7LMhAxNN*? zqH?BoO9cNbwvh3-O!ups*mce_Rk`7U`xYcNf>+K|u8&l%Keshf*?7UdCF;%_z5ld* z)Dm4#e%e9#^93DWBDr$KQ%q-<<1^pRqOtPxj(L~z=8fz{x~$?E=YoiH!Ptoj$Aoig z;pz*{o8Uq6@QG6=#vIeGswsPw=uS9#gpR@L3}al}OI?8mhj;Psb0kGR^{0;zpgEm5 zmtsC)1q4X^i{mHK3ENKK5dxP8{FDG`56aI7(4>La{uG+RD5T=D?O!2 zX$M^7Y%|%a_<##S(3-{p7fjow(u(owsoKqvipEIEmUsq-X43f%4o02Ekr!D^XB$Ue zxR`buM_%xq;uwcnx$oVBb+>}~W38w6;K&QCKQG4l7GCs?Vvl~<1!{tmE;>&in6_3R zqOf#q(Rjwh%JJ+->C#BSvT5tGOBt^B?uuJIw!HC*r)wUsiAz8y`mfR@euqgaERW{S zzihMAr=8q8+BQ}>HZX>Da_?2iVoST?w$itd7LJ!*#rK8iJ4h?mU9l{(RYr@;<9uDx zz}HI|Iir=Q=3liTE)EOirtPLH7Q1ap6b_txU4(Q*uUXGmd^PB*4Ky61=!lIpe5c4h zSrVyPe+6G^;;$5m(74-W%OCgBSsnS4_H%hJWYKvY`SFSjTftZ$F5xn9>tyRQd#(~1 zFDqY{7PY&ka!@;D3Yn;g7ZFjc#gq_H%0zj59uZ|AP_g-hFVG?u65$aM<%CxV zypr%LDYr73Q=$JazXm}p0`nQpztU(zrjxgh$fK*#9W3MfCRR>bCe}ROG38kmDP294 zw>px2(^aV)Z}d*n7V{Env(bXMg;1@{2<1jYJ=2-sM$3z5FhQ+0njd#CL9K@DSxiu? zA&-j*YBeOwVS-yNFP_H)H5-x@FhR`*qKFA^>tognI&Xb{9wCYBMAA79SI3K6rCiB&`t##b|O zlZd&Qi8X>)%fvb&^5g57*dStVVPc~oHZif;B&bGyJM=Lue%K~KVj+RZE6sw$LITHb z7bI2@Ko-Pz2oh@u9J@=9SSsMyy@JG0<=EQ=33k9_t03E$%#ZIABp4%NbK`dj@@^&z zRU>x@a;G4#>=NW| zEq0F}TQqX7Aa7$bKYqI)q4V*5TLlR*$>cskLgp}emmr}4GI@_6+colDLE@7L9D6{J z_i1E@AP;J!PmqT+vQvY6n*_O4 zBbx=eO(VAp@>Y%9A;_H?xl53{HFA$2TLgJ!uOM$@67N@#cW8-Q1=*&N`viHXM&2dJ zyEXD2LAGn;y@G^AM!a7^-lvfrf;^~^K0zMR$WB4Z8tE5gmqvCA@~}n*1PSAnc)x;# zi#L)My)49JFafbggo6o)JtDH0fY>9# z#RSA26_CRO#2&@uF#)khF$GLO>`_b+6A*h8Q^Ewq9uf1HfY_sC^O=CyBVr*F5PL+F zGf~0BPbK0%Tc zB=Rmnk`yHJ9zl{6B=TNCk`yHJfFMZ<64@b0l7d9~1W8hm$WB3$6eQ9wNRomeuXGEN zq#(rx1W8hm$fJTJDM)0mAV~@m85AT*K_c%LBuPOcLxLnJNMyetNeU8qT#zIMi5w6l zNkJmtAxM&fL=Fp*q#%*+5+q4MA{))({c2>BAV~^RY_lLq3KF?pkR$~`UfCf?l7bYw zOOPZ5iQFSdl7d9;6(mVPB5xNYNkJl81xZqn$bEt&DM;j9f+Q(OOwUyvjPiR>06NkJk5f+Q&j^2$*`k`$!aUO|!+ zBr+&Sl7d9uFG!MtM1}-OQjo}gL6Q_C^0**L3KBUWNRonCBi-?L2$G~A#SROSq#%*+ z5+q4MA{&{dUM49>WRoCC3KH2YNRom?ZWkm;K_YhulB6J!y97y65ag9Tf+Q(Ov3mtc zQjo~o1xZqn$W}p;6eMz=AV~@md6ytb3KDsbAV~@md9NTz3KDrhkR%0(><}bLK_Y#E zBq>N_ryxlR66qHtNkJmJ1xZqn$bcY83KDr#kR%0(>=h(QL6Db&f`k-wmA;-`g8x_h zIf%YUTs0ONZyp^ z>nu9dpn(rSz=_d{73pAg4EFTU`90V;rocWZDYP=Fq!AzslA4a4!8qW#TVbP;oq}w% zIW44Q5S|8{V%f6fpj>Q*!cvmNU&t0mrn-rwg(6{8$^)k6h@2ht8BVxj)BVZ51*2$a zRYQkXEE~28DdXb=iU^ESD!cwsPt^f?Y)}acS4#GihQU+K)tqfR`hrR?zT7wHSHuCY zY%eRPaw-W_QDIgY<~VV>@2wQ568JF1qy-NhLFbj*8t-dlgV_&YByP7zi{QBbo^YZ`LR^_BPr|0(!w7}8Gk1&`mt2@OS8jd z{-vaYUldEG#lJLLOy;Y0$>fH8q^9m<_NaZVG~%wBmX^fL`KFwoS@SLx%s<%@Uu-kg zjP}PRT*iwhDj%PJl~CAD3O1WgI!8LErA?QtunbA2%#oG&e&YnDUYri z%OC3;zj>@DQnF+!Z%HJ(ZdzJ>$yqqE<>8&Dc8(6r6jejBn@FE7S~gknV$};()6Sct zj)IXD53f75ZnS5n(2Ij&C#t6lS4?hsaqA0PryXly?}4*L7fMXmzM)f$m<-gFMzOgUqPZ%TBHZ+1$iycwx3BGp}x8h)AffW?%5 zSt9sLCH+vQY0(vl;IHDX1(H4QisV8bb2h$b4P~?FQiyt+u8>}-ux-n+yi$|a zywvO+$W^M&m&CbT-5+fv8D)&?TroewKVe8E=iHC` zzMh?ZAskoYuHEjLo_>7Y{k^~bZh(8lU5F?-w*bg*Y@ z%o%qDUGb`5RooqP$2~z$+#B@9tAo`Xk*cW~`rBePabM7vAG0=C3w6fWy5Kri)&=WW zSs$!t<@(@yRyG71#Lc4XJRjU3Hj8%AAy!EnMYrSgv+8{NI zKBFH@u^c^BeAb`d%0IjXr-q3m6UGUne|zTf!_n|?A}K4;h%l5+M3iVUA@366;bsbig?j-Jkrr+WLlVGwtyHxWt30m36;dKM<( z#jp~lZU9X+Q%OnFL?pj<1eYKl_QJuL{pXy!rlDa(&;)SrvxTlpQ==PHL%bTSAV+5E1UXVO$McU9IjS~#!bh~*sWvv~> z)~CpYAB~f9##3aR`_w+}vOZTz`T#E~%+pdfPwhQx+^M%6-K9SjOMQhL0jTEm8T|E` zAC_<^IUQ9b#+9OSG8R^lApzCLlL;Y3lV@U5Tn^an0;K(^Fb&5AWCHtzfn;0)mWF&m zP)5RvkdP!%7L=rLMiQiRsTgoONepNmHDXx%fdCE(I@B7qjdXLK%TCc~%Hje&Z*O5hWfA0PMgx zRV%*ijYZF>eC%92mU*mKNF;$#*BB!x;+rnW1YPKW}2ErCbn0+|4-tDHsvxe!UFV`8FJ!99$| zQ5?YZ)Cc4CXVz=u>F}3~nR%#C`I!e*c`Aj)%$7kqfy;ueXB#9;B-2zs*72w^0vpl= zqQE*Ng@NBo^57>;utf|`wo6(sWkkn?KxRviM5R_49(V$xMB2lKuIZ=SclVg%<4yRI5LS$!2k>jfTCWuR40!xpY#Rr0ir=%Sc!bD+;B^n<=i68rsl^bec-3qlrK*mpzyG~-VFF5x6 z_=TL~&=P<625(z%G`&&tgAL!?kaO%>;sd|+Ju-FVeNW>wf1|GTdffv{bq`E;uefVw z$FJA5=IUC1?QZ>zr*_pu>K|OS5?8}@r;u|B^S&kLwi{0Gino8^=@U8ciQgLyuBufR z@iwjch_!0AF=uI7vDRLLX&IOmO+gA-H+hOhlXY);`ccEs-m4P3feDmawBR}18 zEq(oor*ls{y}0lAV%tEjW?;#A0;aN7&pwy4G-J0O?tSM5)-7{<5CKeB;h;yXik|9ONpG>_#=89S_rCIZ~=AAfY+nf9Fxai_2ic zh=v%6bCX7nWDTPx_)?KXqsSMeI5_Dkl#Ni(^Yjs9 zhf>h&vIQ-4(qtf@6(Si{q!&#?pkZct(fqn0Yj}hE2I?+tgq(&oPnst!N{!wjYkrLr zK_eMOUR{wy>uVftw4mBnczQacu;~JwWP$;Sov4VKmJQNhFKH zlu2wRP$NkZ#E>lHMQ%Vi1;a(c31+@1I0=XiQBoudHUcwf08+~OLn9^@<&+eO4uKt% zS0!+`Xr<%^VZkIKicLZ1(rg$IiO^aTmx?UKhW?Bul2fVo*fq&Vp5A9f{K&ym!}|`BEPRErVSrf`7VymjLxl}KfGAwpX$D0 z@y>32-I(W%FU-6!w{Owi42<4UJ1f3^XvwkZhPQss_iE#`d8NTW*Ye%n-`;&?+d{*$ zSCx03%{4r`aO|0-hG%E0rcKl1z)inznjinc3vaw|wfkTD{<&|#-M(z?xNRgGPI7ku z1`@$cPX))x3e;RC5&@S90e1-(G>Qg^N9F>izX{w6CNOk-q8aKel3B7yykwPll-ENB z%<(T;B^&Eu6>Z=au;<&`^R;Ht0ksZrLg?e7+r!Dm)aI#zcUQ@~8{Vr*+I!&LUGnaQ zcTdTCHN1OE-q9^mJ;D2HRZn{&0m@_qNc7=SNS}$s!m=zRhZx>!^%`pkYpo?& zLsUUy8@remhWvy%9r9!f`Z6*Q2~a#wTWb;du%rObNJS&41LBm(P>{azYBe$$f1_s-Y55CFKUTE&;X%7?(68a=QJq4MJ(;_8n zRP4@!1}Yv^fJ0=2d)8Rl0tab?Y>KQpiOqGR0bT9>Wc*(RvI z$cPj<8w$set4xF8Y?hiO0b^&3l8 zdkiXM9Ja7dmwp5Z5m(uCzg2>Y58uCv{lO6gYh1B9*$S<5doH<`t%7#Cs05T@+F!K} z3#{XC`(Qg;$eRXjAvi@D20HRfK)X7#@qP=yuU~_%cTndjf^VBUobw3F*3At5&kuAv zfZoy5e*Ac6R~ht({$rJ^1#G_G0zh19O8AUS-!gs_2w@bd=H z4cKs^|Ed0?&-S++zCWPObmD9xIi3iK2x;Rz$WZ$En*gPZ8h?Qv7d)HifgrapTm7H& z{+a;%W4-s;U0WWDQ_)PrJrEbZT}E)rxu0cj>!qq?>m~;5o7|wkMzw}Q=zIu;RC_2C zPl{;}a3R$h3VkIVj^)2tLLm_Fp%BwinNXr=m{AvIXm+XmnPf6XkK+4r%uZl-3bWIg zJ&)O!F*}2q2-%z3fiv+%JFynCB>d(7gX}!HZ7`Xvt5uxIJKM2JpqM*+2aDAzvTet0 zo7v?5u*$n?f^yYNJigh^xh-?&t{A^PxzMmH=WENk1FIJNXeFDrtYY(3JF!>Yalq4U z4` zY`ssbHOAU8UxOWYT=C&pJFufL7r`oFUc8G1I~}$iW$_jigiOZnhlf%v=q-51gz=G4 zY*CSlwl8Q&oZpc7S-G)U3^e6+$G_0zEE$KXc54})Ok1q*OqzfuuVJ%#$iSE7AyrL_u1!;2E4=;dPrdZiEWgaxvJ(Kc zPl_hfswFg*90!eAtvwSFhlWQ+&&J}3)K{pijE$e0$UrPE0s%h=t$}@|nqyL8SQ#lh zI1|jo4(>cWpqpfpD+ViyhXc+AfPWHP4#BkRDsFaxl-BLoLVF(3;1qy0yGA@iKsn`~ao|V8Yk8TFt_>M~o z7y~pq2CetA^Ha$!6spYp^_x@^3@|KFid8Ad!1`n(s^-W@5`68T!OHjzm2s7es+>}x zy_zV_O|$SFaaqQOpqAQ+%`w$}!&N=I?;Foeb1M$#^jBu~&bGh2|AuG7O#4kw-E{kk z)pp^Ti_gtGH}~M8t1)M7oZ(g-q-q1`v`*JlkH(ctmGFX!ei$af!&pm27Y*l$QlO;L zBhqP2-&oj8W9EzZZl(;v8Ekp!vu!9n0>G5v47$c1hW{Ou-A{pegG%*tTksT%xKjji zl!s;&Nrc7et}q?kZ*iA7a6Gkupi9Ec^szLO6I3Sa*nJ8p*TcjS*#WTB?}CyiIz zzuEcvw(kbM9k}AX(!SUbxbEBilg9sLNbyzwPT)|q89Gq3$-tmP+>!AJ^R|wyFdaP) zwf}~n^M;I_INcW?oq04@)BV%hYhyocT&(F{baXH9-5NzZ6Y02axXESvjT^vd^lg~w zGJ$|IhXLnd3^f0_a~Y8R;)u zhxMLyyba-W42Gj>QIU!vc|=ChfjN+$GjsSjV>fWw0#Q<9Y6AA|Km{_YgPLyW;jv^&mez@SaPU z=5BcFE;n6jn&;*pT=cepzs}*Eefs6cZq_wkp1d?Ue`>LA_jJ#S(|7Uc%+a~7`IEVg zZOhKUimPV!D=&X3U;ldV8$&-xd@phJ>1*8Lw*8A6A6s@FU`<~6(%J)c&yVCb29}+> zSL;aC=GA)Q^v#NwqnD!d*2Q)HoWp;mH|N;9!0)}6cOz3|MEYAm&{7TPQ*NA~@MWn; zyrnEuG!#W>k?_ii3*3a@@*9SmSfY7|2QmFLifPd@X@olq1@c@=0PE6Xk}r}UL>LS@ zfkCwYv-LNLRuK0_Ai5`t>`1g{4KJErTG5~}G?n`#p1n!P~#(DUxd98aW z#hv-gBbDATab-NPi{l?zLf`sDj%b zg@_Z}5GlX8VXM3+RE$Ke6?xLv%5HAlE!^DjWCG7fbV6XkVz`757Tc6$8;&tTnE-grLcc43v7MH{Lql?)7&pmmJsvKN zRju8=KeHX1AsfZJ9G^C{-_0Dr>{h18a*;E83&*5~{VCcZ zEAW@U08(U%+{8Hg!CycOy>E%{zu|DtIu{*{Q(Aoei@$jI9p&d=(7t_G-!#AO%DM&N zfvY>N#TV=PrXBfMv;|_p9^Yl#CEKfx>Gm7W^>bV29ZSw#C6z2b{c#~a{m8Y)e#QN& z{l82L`}=b>{maf{z?kcgaKCSW=+8}Xo7!e=DF|9H2xBDQ^2kD}ib+eRP9e;D_562rS>XJ^3lZW{+VGX~2XUIo>^3AVdbe5`f- zO(#jT$JWxWLH8>OU+WqYF!};RSAZ>RDa&WMw>kYXEL^@TXg8x(dYfV?8i3`Pz;?@P zXTWkXB*M}tuC*c+t-MJyux~`@iUe9HtQZpn=GSEKB503Ap)_IkTQZNpl@dX_UuX}gpyt@{?fvG1~-0LsCIP>CE z&&?vaJKW#wm=mw;TXH;v#P9t2(U*=c`1W2^t_{BP=n~&|(^-A7Z>Ddqe$m-H)%hWB zyUzP^yl?jO65k9|dY!M$@wKzbdAiK+(Ci*?^5J!4xGT(S=i&xXv_Kn`;L*?BLY4={ z7HYD7F8VuAv!HVRZ#an1(5u)Q@yg#uqfp@W;}{tB2^oBa^zX685KU_F>eB0XjE}Oz z&{!|-k?KHf&~G}S(?T^X6DjaFP^26!^6kJUl&+eK5s5_W7s@wf@c#ogKx388WA-h~ z{FtE@K+$@pqnI7StP``Xn4t$q^HaD(p)dqb0U7YhHY^2Q7^)GhUd<3bk1bJ`W}KSh zLDC^?0%s1kv33LOEY@~lhPbL)4`@!*gA@%@Bs=*L$l=Bg$ElJGe;|PgPVt($vzl|V7S=MEO2d3)-nEYmfM zWZg>5jw#3Vz#`dk+wA0Av)~$qVlHwAi`z{mu7{fi7bTYSTkf#(wx@>MH!H6aDCVId z6t{N?+#znhW0hce72v?~b{FU5cFwUOcV0E($UEQh;mA8z1;RV0Gru;j{|%G_7f;Qc Vy7>Ie^Wex?=9^ZHgl}LQ`~Rx^Zdw2U diff --git a/.venv/Lib/site-packages/bs4/__pycache__/element.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/element.cpython-312.pyc deleted file mode 100644 index 3737cf63058cf53f55a9d3660cbc62c15bcd6f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107895 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

&q#1O8OziQHlK0?PWNR7QpN5N}FSBn-M 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 diff --git a/.venv/Lib/site-packages/bs4/__pycache__/filter.cpython-312.pyc b/.venv/Lib/site-packages/bs4/__pycache__/filter.cpython-312.pyc deleted file mode 100644 index a50b6684e24272b8c8f26f8a920b5bbe2bcec958..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28583 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 diff --git a/.venv/Lib/site-packages/bs4/_deprecation.py b/.venv/Lib/site-packages/bs4/_deprecation.py deleted file mode 100644 index a0d7fdc..0000000 --- a/.venv/Lib/site-packages/bs4/_deprecation.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Helper functions for deprecation. - -This interface is itself unstable and may change without warning. Do -not use these functions yourself, even as a joke. The underscores are -there for a reason. No support will be given. - -In particular, most of this will go away without warning once -Beautiful Soup drops support for Python 3.11, since Python 3.12 -defines a `@typing.deprecated() -decorator. `_ -""" - -import functools -import warnings - -from typing import ( - Any, - Callable, -) - - -def _deprecated_alias(old_name: str, new_name: str, version: str): - """Alias one attribute name to another for backward compatibility - - :meta private: - """ - - @property - def alias(self) -> Any: - ":meta private:" - warnings.warn( - f"Access to deprecated property {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return getattr(self, new_name) - - @alias.setter - def alias(self, value: str) -> None: - ":meta private:" - warnings.warn( - f"Write to deprecated property {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return setattr(self, new_name, value) - - return alias - - -def _deprecated_function_alias( - old_name: str, new_name: str, version: str -) -> Callable[[Any], Any]: - def alias(self, *args: Any, **kwargs: Any) -> Any: - ":meta private:" - warnings.warn( - f"Call to deprecated method {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return getattr(self, new_name)(*args, **kwargs) - - return alias - - -def _deprecated(replaced_by: str, version: str) -> Callable: - def deprecate(func: Callable) -> Callable: - @functools.wraps(func) - def with_warning(*args: Any, **kwargs: Any) -> Any: - ":meta private:" - warnings.warn( - f"Call to deprecated method {func.__name__}. (Replaced by {replaced_by}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - return with_warning - - return deprecate diff --git a/.venv/Lib/site-packages/bs4/_typing.py b/.venv/Lib/site-packages/bs4/_typing.py deleted file mode 100644 index ac4ec34..0000000 --- a/.venv/Lib/site-packages/bs4/_typing.py +++ /dev/null @@ -1,196 +0,0 @@ -# Custom type aliases used throughout Beautiful Soup to improve readability. - -# Notes on improvements to the type system in newer versions of Python -# that can be used once Beautiful Soup drops support for older -# versions: -# -# * ClassVar can be put on class variables now. -# * In 3.10, x|y is an accepted shorthand for Union[x,y]. -# * In 3.10, TypeAlias gains capabilities that can be used to -# improve the tree matching types (I don't remember what, exactly). -# * In 3.9 it's possible to specialize the re.Match type, -# e.g. re.Match[str]. In 3.8 there's a typing.re namespace for this, -# but it's removed in 3.12, so to support the widest possible set of -# versions I'm not using it. - -from typing_extensions import ( - runtime_checkable, - Protocol, - TypeAlias, -) -from typing import ( - Any, - Callable, - Dict, - IO, - Iterable, - Mapping, - Optional, - Pattern, - TYPE_CHECKING, - Union, -) - -if TYPE_CHECKING: - from bs4.element import ( - AttributeValueList, - NamespacedAttribute, - NavigableString, - PageElement, - ResultSet, - Tag, - ) - - -@runtime_checkable -class _RegularExpressionProtocol(Protocol): - """A protocol object which can accept either Python's built-in - `re.Pattern` objects, or the similar ``Regex`` objects defined by the - third-party ``regex`` package. - """ - - def search( - self, string: str, pos: int = ..., endpos: int = ... - ) -> Optional[Any]: ... - - @property - def pattern(self) -> str: ... - - -# Aliases for markup in various stages of processing. -# -#: The rawest form of markup: either a string, bytestring, or an open filehandle. -_IncomingMarkup: TypeAlias = Union[str, bytes, IO[str], IO[bytes]] - -#: Markup that is in memory but has (potentially) yet to be converted -#: to Unicode. -_RawMarkup: TypeAlias = Union[str, bytes] - -# Aliases for character encodings -# - -#: A data encoding. -_Encoding: TypeAlias = str - -#: One or more data encodings. -_Encodings: TypeAlias = Iterable[_Encoding] - -# Aliases for XML namespaces -# - -#: The prefix for an XML namespace. -_NamespacePrefix: TypeAlias = str - -#: The URL of an XML namespace -_NamespaceURL: TypeAlias = str - -#: A mapping of prefixes to namespace URLs. -_NamespaceMapping: TypeAlias = Dict[_NamespacePrefix, _NamespaceURL] - -#: A mapping of namespace URLs to prefixes -_InvertedNamespaceMapping: TypeAlias = Dict[_NamespaceURL, _NamespacePrefix] - -# Aliases for the attribute values associated with HTML/XML tags. -# - -#: The value associated with an HTML or XML attribute. This is the -#: relatively unprocessed value Beautiful Soup expects to come from a -#: `TreeBuilder`. -_RawAttributeValue: TypeAlias = str - -#: A dictionary of names to `_RawAttributeValue` objects. This is how -#: Beautiful Soup expects a `TreeBuilder` to represent a tag's -#: attribute values. -_RawAttributeValues: TypeAlias = ( - "Mapping[Union[str, NamespacedAttribute], _RawAttributeValue]" -) - -#: An attribute value in its final form, as stored in the -# `Tag` class, after it has been processed and (in some cases) -# split into a list of strings. -_AttributeValue: TypeAlias = Union[str, "AttributeValueList"] - -#: A dictionary of names to :py:data:`_AttributeValue` objects. This is what -#: a tag's attributes look like after processing. -_AttributeValues: TypeAlias = Dict[str, _AttributeValue] - -#: The methods that deal with turning :py:data:`_RawAttributeValue` into -#: :py:data:`_AttributeValue` may be called several times, even after the values -#: are already processed (e.g. when cloning a tag), so they need to -#: be able to acommodate both possibilities. -_RawOrProcessedAttributeValues: TypeAlias = Union[_RawAttributeValues, _AttributeValues] - -#: A number of tree manipulation methods can take either a `PageElement` or a -#: normal Python string (which will be converted to a `NavigableString`). -_InsertableElement: TypeAlias = Union["PageElement", str] - -# Aliases to represent the many possibilities for matching bits of a -# parse tree. -# -# This is very complicated because we're applying a formal type system -# to some very DWIM code. The types we end up with will be the types -# of the arguments to the SoupStrainer constructor and (more -# familiarly to Beautiful Soup users) the find* methods. - -#: A function that takes a PageElement and returns a yes-or-no answer. -_PageElementMatchFunction: TypeAlias = Callable[["PageElement"], bool] - -#: A function that takes the raw parsed ingredients of a markup tag -#: and returns a yes-or-no answer. -# Not necessary at the moment. -# _AllowTagCreationFunction:TypeAlias = Callable[[Optional[str], str, Optional[_RawAttributeValues]], bool] - -#: A function that takes the raw parsed ingredients of a markup string node -#: and returns a yes-or-no answer. -# Not necessary at the moment. -# _AllowStringCreationFunction:TypeAlias = Callable[[Optional[str]], bool] - -#: A function that takes a `Tag` and returns a yes-or-no answer. -#: A `TagNameMatchRule` expects this kind of function, if you're -#: going to pass it a function. -_TagMatchFunction: TypeAlias = Callable[["Tag"], bool] - -#: A function that takes a single string and returns a yes-or-no -#: answer. An `AttributeValueMatchRule` expects this kind of function, if -#: you're going to pass it a function. So does a `StringMatchRule`. -_StringMatchFunction: TypeAlias = Callable[[str], bool] - -#: Either a tag name, an attribute value or a string can be matched -#: against a string, bytestring, regular expression, or a boolean. -_BaseStrainable: TypeAlias = Union[str, bytes, Pattern[str], bool] - -#: A tag can be matched either with the `_BaseStrainable` options, or -#: using a function that takes the `Tag` as its sole argument. -_BaseStrainableElement: TypeAlias = Union[_BaseStrainable, _TagMatchFunction] - -#: A tag's attribute vgalue can be matched either with the -#: `_BaseStrainable` options, or using a function that takes that -#: value as its sole argument. -_BaseStrainableAttribute: TypeAlias = Union[_BaseStrainable, _StringMatchFunction] - -#: A tag can be matched using either a single criterion or a list of -#: criteria. -_StrainableElement: TypeAlias = Union[ - _BaseStrainableElement, Iterable[_BaseStrainableElement] -] - -#: An attribute value can be matched using either a single criterion -#: or a list of criteria. -_StrainableAttribute: TypeAlias = Union[ - _BaseStrainableAttribute, Iterable[_BaseStrainableAttribute] -] - -#: An string can be matched using the same techniques as -#: an attribute value. -_StrainableString: TypeAlias = _StrainableAttribute - -#: A dictionary may be used to match against multiple attribute vlaues at once. -_StrainableAttributes: TypeAlias = Dict[str, _StrainableAttribute] - -#: Many Beautiful soup methods return a PageElement or an ResultSet of -#: PageElements. A PageElement is either a Tag or a NavigableString. -#: These convenience aliases make it easier for IDE users to see which methods -#: are available on the objects they're dealing with. -_OneElement: TypeAlias = Union["PageElement", "Tag", "NavigableString"] -_AtMostOneElement: TypeAlias = Optional[_OneElement] -_QueryResults: TypeAlias = "ResultSet[_OneElement]" diff --git a/.venv/Lib/site-packages/bs4/_warnings.py b/.venv/Lib/site-packages/bs4/_warnings.py deleted file mode 100644 index 4309473..0000000 --- a/.venv/Lib/site-packages/bs4/_warnings.py +++ /dev/null @@ -1,98 +0,0 @@ -"""Define some custom warnings.""" - - -class GuessedAtParserWarning(UserWarning): - """The warning issued when BeautifulSoup has to guess what parser to - use -- probably because no parser was specified in the constructor. - """ - - MESSAGE: str = """No parser was explicitly specified, so I'm using the best available %(markup_type)s parser for this system ("%(parser)s"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently. - -The code that caused this warning is on line %(line_number)s of the file %(filename)s. To get rid of this warning, pass the additional argument 'features="%(parser)s"' to the BeautifulSoup constructor. -""" - - -class UnusualUsageWarning(UserWarning): - """A superclass for warnings issued when Beautiful Soup sees - something that is typically the result of a mistake in the calling - code, but might be intentional on the part of the user. If it is - in fact intentional, you can filter the individual warning class - to get rid of the warning. If you don't like Beautiful Soup - second-guessing what you are doing, you can filter the - UnusualUsageWarningclass itself and get rid of these entirely. - """ - - -class MarkupResemblesLocatorWarning(UnusualUsageWarning): - """The warning issued when BeautifulSoup is given 'markup' that - actually looks like a resource locator -- a URL or a path to a file - on disk. - """ - - #: :meta private: - GENERIC_MESSAGE: str = """ - -However, if you want to parse some data that happens to look like a %(what)s, then nothing has gone wrong: you are using Beautiful Soup correctly, and this warning is spurious and can be filtered. To make this warning go away, run this code before calling the BeautifulSoup constructor: - - from bs4 import MarkupResemblesLocatorWarning - import warnings - - warnings.filterwarnings("ignore", category=MarkupResemblesLocatorWarning) - """ - - URL_MESSAGE: str = ( - """The input passed in on this line looks more like a URL than HTML or XML. - -If you meant to use Beautiful Soup to parse the web page found at a certain URL, then something has gone wrong. You should use an Python package like 'requests' to fetch the content behind the URL. Once you have the content as a string, you can feed that string into Beautiful Soup.""" - + GENERIC_MESSAGE - ) - - FILENAME_MESSAGE: str = ( - """The input passed in on this line looks more like a filename than HTML or XML. - -If you meant to use Beautiful Soup to parse the contents of a file on disk, then something has gone wrong. You should open the file first, using code like this: - - filehandle = open(your filename) - -You can then feed the open filehandle into Beautiful Soup instead of using the filename.""" - + GENERIC_MESSAGE - ) - - -class AttributeResemblesVariableWarning(UnusualUsageWarning, SyntaxWarning): - """The warning issued when Beautiful Soup suspects a provided - attribute name may actually be the misspelled name of a Beautiful - Soup variable. Generally speaking, this is only used in cases like - "_class" where it's very unlikely the user would be referencing an - XML attribute with that name. - """ - - MESSAGE: str = """%(original)r is an unusual attribute name and is a common misspelling for %(autocorrect)r. - -If you meant %(autocorrect)r, change your code to use it, and this warning will go away. - -If you really did mean to check the %(original)r attribute, this warning is spurious and can be filtered. To make it go away, run this code before creating your BeautifulSoup object: - - from bs4 import AttributeResemblesVariableWarning - import warnings - - warnings.filterwarnings("ignore", category=AttributeResemblesVariableWarning) -""" - - -class XMLParsedAsHTMLWarning(UnusualUsageWarning): - """The warning issued when an HTML parser is used to parse - XML that is not (as far as we can tell) XHTML. - """ - - MESSAGE: str = """It looks like you're using an HTML parser to parse an XML document. - -Assuming this really is an XML document, what you're doing might work, but you should know that using an XML parser will be more reliable. To parse this document as XML, make sure you have the Python package 'lxml' installed, and pass the keyword argument `features="xml"` into the BeautifulSoup constructor. - -If you want or need to use an HTML parser on this document, you can make this warning go away by filtering it. To do that, run this code before calling the BeautifulSoup constructor: - - from bs4 import XMLParsedAsHTMLWarning - import warnings - - warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning) -""" diff --git a/.venv/Lib/site-packages/bs4/builder/__init__.py b/.venv/Lib/site-packages/bs4/builder/__init__.py deleted file mode 100644 index 5f2b38d..0000000 --- a/.venv/Lib/site-packages/bs4/builder/__init__.py +++ /dev/null @@ -1,848 +0,0 @@ -from __future__ import annotations - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -from collections import defaultdict -import re -from types import ModuleType -from typing import ( - Any, - cast, - Dict, - Iterable, - List, - Optional, - Pattern, - Set, - Tuple, - Type, - TYPE_CHECKING, -) -import warnings -import sys -from bs4.element import ( - AttributeDict, - AttributeValueList, - CharsetMetaAttributeValue, - ContentMetaAttributeValue, - RubyParenthesisString, - RubyTextString, - Stylesheet, - Script, - TemplateString, - nonwhitespace_re, -) - -# Exceptions were moved to their own module in 4.13. Import here for -# backwards compatibility. -from bs4.exceptions import ParserRejectedMarkup - -from bs4._typing import ( - _AttributeValues, - _RawAttributeValue, -) - -from bs4._warnings import XMLParsedAsHTMLWarning - -if TYPE_CHECKING: - from bs4 import BeautifulSoup - from bs4.element import ( - NavigableString, - Tag, - ) - from bs4._typing import ( - _AttributeValue, - _Encoding, - _Encodings, - _RawOrProcessedAttributeValues, - _RawMarkup, - ) - -__all__ = [ - "HTMLTreeBuilder", - "SAXTreeBuilder", - "TreeBuilder", - "TreeBuilderRegistry", -] - -# Some useful features for a TreeBuilder to have. -FAST = "fast" -PERMISSIVE = "permissive" -STRICT = "strict" -XML = "xml" -HTML = "html" -HTML_5 = "html5" - -__all__ = [ - "TreeBuilderRegistry", - "TreeBuilder", - "HTMLTreeBuilder", - "DetectsXMLParsedAsHTML", - - "ParserRejectedMarkup", # backwards compatibility only as of 4.13.0 -] - -class TreeBuilderRegistry(object): - """A way of looking up TreeBuilder subclasses by their name or by desired - features. - """ - - builders_for_feature: Dict[str, List[Type[TreeBuilder]]] - builders: List[Type[TreeBuilder]] - - def __init__(self) -> None: - self.builders_for_feature = defaultdict(list) - self.builders = [] - - def register(self, treebuilder_class: type[TreeBuilder]) -> None: - """Register a treebuilder based on its advertised features. - - :param treebuilder_class: A subclass of `TreeBuilder`. its - `TreeBuilder.features` attribute should list its features. - """ - for feature in treebuilder_class.features: - self.builders_for_feature[feature].insert(0, treebuilder_class) - self.builders.insert(0, treebuilder_class) - - def lookup(self, *features: str) -> Optional[Type[TreeBuilder]]: - """Look up a TreeBuilder subclass with the desired features. - - :param features: A list of features to look for. If none are - provided, the most recently registered TreeBuilder subclass - will be used. - :return: A TreeBuilder subclass, or None if there's no - registered subclass with all the requested features. - """ - if len(self.builders) == 0: - # There are no builders at all. - return None - - if len(features) == 0: - # They didn't ask for any features. Give them the most - # recently registered builder. - return self.builders[0] - - # Go down the list of features in order, and eliminate any builders - # that don't match every feature. - feature_list = list(features) - feature_list.reverse() - candidates = None - candidate_set = None - while len(feature_list) > 0: - feature = feature_list.pop() - we_have_the_feature = self.builders_for_feature.get(feature, []) - if len(we_have_the_feature) > 0: - if candidates is None: - candidates = we_have_the_feature - candidate_set = set(candidates) - else: - # Eliminate any candidates that don't have this feature. - candidate_set = candidate_set.intersection(set(we_have_the_feature)) - - # The only valid candidates are the ones in candidate_set. - # Go through the original list of candidates and pick the first one - # that's in candidate_set. - if candidate_set is None or candidates is None: - return None - for candidate in candidates: - if candidate in candidate_set: - return candidate - return None - - -#: The `BeautifulSoup` constructor will take a list of features -#: and use it to look up `TreeBuilder` classes in this registry. -builder_registry: TreeBuilderRegistry = TreeBuilderRegistry() - - -class TreeBuilder(object): - """Turn a textual document into a Beautiful Soup object tree. - - This is an abstract superclass which smooths out the behavior of - different parser libraries into a single, unified interface. - - :param multi_valued_attributes: If this is set to None, the - TreeBuilder will not turn any values for attributes like - 'class' into lists. Setting this to a dictionary will - customize this behavior; look at :py:attr:`bs4.builder.HTMLTreeBuilder.DEFAULT_CDATA_LIST_ATTRIBUTES` - for an example. - - Internally, these are called "CDATA list attributes", but that - probably doesn't make sense to an end-user, so the argument name - is ``multi_valued_attributes``. - - :param preserve_whitespace_tags: A set of tags to treat - the way

 tags are treated in HTML. Tags in this set
-     are immune from pretty-printing; their contents will always be
-     output as-is.
-
-    :param string_containers: A dictionary mapping tag names to
-     the classes that should be instantiated to contain the textual
-     contents of those tags. The default is to use NavigableString
-     for every tag, no matter what the name. You can override the
-     default by changing :py:attr:`DEFAULT_STRING_CONTAINERS`.
-
-    :param store_line_numbers: If the parser keeps track of the line
-     numbers and positions of the original markup, that information
-     will, by default, be stored in each corresponding
-     :py:class:`bs4.element.Tag` object. You can turn this off by
-     passing store_line_numbers=False; then Tag.sourcepos and
-     Tag.sourceline will always be None. If the parser you're using
-     doesn't keep track of this information, then store_line_numbers
-     is irrelevant.
-
-    :param attribute_dict_class: The value of a multi-valued attribute
-      (such as HTML's 'class') willl be stored in an instance of this
-      class.  The default is Beautiful Soup's built-in
-      `AttributeValueList`, which is a normal Python list, and you
-      will probably never need to change it.
-    """
-
-    USE_DEFAULT: Any = object()  #: :meta private:
-
-    def __init__(
-        self,
-        multi_valued_attributes: Dict[str, Set[str]] = USE_DEFAULT,
-        preserve_whitespace_tags: Set[str] = USE_DEFAULT,
-        store_line_numbers: bool = USE_DEFAULT,
-        string_containers: Dict[str, Type[NavigableString]] = USE_DEFAULT,
-        empty_element_tags: Set[str] = USE_DEFAULT,
-        attribute_dict_class: Type[AttributeDict] = AttributeDict,
-        attribute_value_list_class: Type[AttributeValueList] = AttributeValueList,
-    ):
-        self.soup = None
-        if multi_valued_attributes is self.USE_DEFAULT:
-            multi_valued_attributes = self.DEFAULT_CDATA_LIST_ATTRIBUTES
-        self.cdata_list_attributes = multi_valued_attributes
-        if preserve_whitespace_tags is self.USE_DEFAULT:
-            preserve_whitespace_tags = self.DEFAULT_PRESERVE_WHITESPACE_TAGS
-        self.preserve_whitespace_tags = preserve_whitespace_tags
-        if empty_element_tags is self.USE_DEFAULT:
-            self.empty_element_tags = self.DEFAULT_EMPTY_ELEMENT_TAGS
-        else:
-            self.empty_element_tags = empty_element_tags
-        # TODO: store_line_numbers is probably irrelevant now that
-        # the behavior of sourceline and sourcepos has been made consistent
-        # everywhere.
-        if store_line_numbers == self.USE_DEFAULT:
-            store_line_numbers = self.TRACKS_LINE_NUMBERS
-        self.store_line_numbers = store_line_numbers
-        if string_containers == self.USE_DEFAULT:
-            string_containers = self.DEFAULT_STRING_CONTAINERS
-        self.string_containers = string_containers
-        self.attribute_dict_class = attribute_dict_class
-        self.attribute_value_list_class = attribute_value_list_class
-
-    NAME: str = "[Unknown tree builder]"
-    ALTERNATE_NAMES: Iterable[str] = []
-    features: Iterable[str] = []
-
-    is_xml: bool = False
-    picklable: bool = False
-
-    soup: Optional[BeautifulSoup]  #: :meta private:
-
-    #: A tag will be considered an empty-element
-    #: tag when and only when it has no contents.
-    empty_element_tags: Optional[Set[str]] = None  #: :meta private:
-    cdata_list_attributes: Dict[str, Set[str]]  #: :meta private:
-    preserve_whitespace_tags: Set[str]  #: :meta private:
-    string_containers: Dict[str, Type[NavigableString]]  #: :meta private:
-    tracks_line_numbers: bool  #: :meta private:
-
-    #: A value for these tag/attribute combinations is a space- or
-    #: comma-separated list of CDATA, rather than a single CDATA.
-    DEFAULT_CDATA_LIST_ATTRIBUTES: Dict[str, Set[str]] = defaultdict(set)
-
-    #: Whitespace should be preserved inside these tags.
-    DEFAULT_PRESERVE_WHITESPACE_TAGS: Set[str] = set()
-
-    #: The textual contents of tags with these names should be
-    #: instantiated with some class other than `bs4.element.NavigableString`.
-    DEFAULT_STRING_CONTAINERS: Dict[str, Type[bs4.element.NavigableString]] = {}
-
-    #: By default, tags are treated as empty-element tags if they have
-    #: no contents--that is, using XML rules. HTMLTreeBuilder
-    #: defines a different set of DEFAULT_EMPTY_ELEMENT_TAGS based on the
-    #: HTML 4 and HTML5 standards.
-    DEFAULT_EMPTY_ELEMENT_TAGS: Optional[Set[str]] = None
-
-    #: Most parsers don't keep track of line numbers.
-    TRACKS_LINE_NUMBERS: bool = False
-
-    def initialize_soup(self, soup: BeautifulSoup) -> None:
-        """The BeautifulSoup object has been initialized and is now
-        being associated with the TreeBuilder.
-
-        :param soup: A BeautifulSoup object.
-        """
-        self.soup = soup
-
-    def reset(self) -> None:
-        """Do any work necessary to reset the underlying parser
-        for a new document.
-
-        By default, this does nothing.
-        """
-        pass
-
-    def can_be_empty_element(self, tag_name: str) -> bool:
-        """Might a tag with this name be an empty-element tag?
-
-        The final markup may or may not actually present this tag as
-        self-closing.
-
-        For instance: an HTMLBuilder does not consider a 

tag to be - an empty-element tag (it's not in - HTMLBuilder.empty_element_tags). This means an empty

tag - will be presented as "

", not "

" or "

". - - The default implementation has no opinion about which tags are - empty-element tags, so a tag will be presented as an - empty-element tag if and only if it has no children. - "" will become "", and "bar" will - be left alone. - - :param tag_name: The name of a markup tag. - """ - if self.empty_element_tags is None: - return True - return tag_name in self.empty_element_tags - - def feed(self, markup: _RawMarkup) -> None: - """Run incoming markup through some parsing process.""" - raise NotImplementedError() - - def prepare_markup( - self, - markup: _RawMarkup, - user_specified_encoding: Optional[_Encoding] = None, - document_declared_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - ) -> Iterable[Tuple[_RawMarkup, Optional[_Encoding], Optional[_Encoding], bool]]: - """Run any preliminary steps necessary to make incoming markup - acceptable to the parser. - - :param markup: The markup that's about to be parsed. - :param user_specified_encoding: The user asked to try this encoding - to convert the markup into a Unicode string. - :param document_declared_encoding: The markup itself claims to be - in this encoding. NOTE: This argument is not used by the - calling code and can probably be removed. - :param exclude_encodings: The user asked *not* to try any of - these encodings. - - :yield: A series of 4-tuples: (markup, encoding, declared encoding, - has undergone character replacement) - - Each 4-tuple represents a strategy that the parser can try - to convert the document to Unicode and parse it. Each - strategy will be tried in turn. - - By default, the only strategy is to parse the markup - as-is. See `LXMLTreeBuilderForXML` and - `HTMLParserTreeBuilder` for implementations that take into - account the quirks of particular parsers. - - :meta private: - - """ - yield markup, None, None, False - - def test_fragment_to_document(self, fragment: str) -> str: - """Wrap an HTML fragment to make it look like a document. - - Different parsers do this differently. For instance, lxml - introduces an empty tag, and html5lib - doesn't. Abstracting this away lets us write simple tests - which run HTML fragments through the parser and compare the - results against other HTML fragments. - - This method should not be used outside of unit tests. - - :param fragment: A fragment of HTML. - :return: A full HTML document. - :meta private: - """ - return fragment - - def set_up_substitutions(self, tag: Tag) -> bool: - """Set up any substitutions that will need to be performed on - a `Tag` when it's output as a string. - - By default, this does nothing. See `HTMLTreeBuilder` for a - case where this is used. - - :return: Whether or not a substitution was performed. - :meta private: - """ - return False - - def _replace_cdata_list_attribute_values( - self, tag_name: str, attrs: _RawOrProcessedAttributeValues - ) -> _AttributeValues: - """When an attribute value is associated with a tag that can - have multiple values for that attribute, convert the string - value to a list of strings. - - Basically, replaces class="foo bar" with class=["foo", "bar"] - - NOTE: This method modifies its input in place. - - :param tag_name: The name of a tag. - :param attrs: A dictionary containing the tag's attributes. - Any appropriate attribute values will be modified in place. - :return: The modified dictionary that was originally passed in. - """ - - # First, cast the attrs dict to _AttributeValues. This might - # not be accurate yet, but it will be by the time this method - # returns. - modified_attrs = cast(_AttributeValues, attrs) - if not modified_attrs or not self.cdata_list_attributes: - # Nothing to do. - return modified_attrs - - # There is at least a possibility that we need to modify one of - # the attribute values. - universal: Set[str] = self.cdata_list_attributes.get("*", set()) - tag_specific = self.cdata_list_attributes.get(tag_name.lower(), None) - for attr in list(modified_attrs.keys()): - modified_value: _AttributeValue - if attr in universal or (tag_specific and attr in tag_specific): - # We have a "class"-type attribute whose string - # value is a whitespace-separated list of - # values. Split it into a list. - original_value: _AttributeValue = modified_attrs[attr] - if isinstance(original_value, _RawAttributeValue): - # This is a _RawAttributeValue (a string) that - # needs to be split and converted to a - # AttributeValueList so it can be an - # _AttributeValue. - modified_value = self.attribute_value_list_class( - nonwhitespace_re.findall(original_value) - ) - else: - # html5lib calls setAttributes twice for the - # same tag when rearranging the parse tree. On - # the second call the attribute value here is - # already a list. This can also happen when a - # Tag object is cloned. If this happens, leave - # the value alone rather than trying to split - # it again. - modified_value = original_value - modified_attrs[attr] = modified_value - return modified_attrs - - -class SAXTreeBuilder(TreeBuilder): - """A Beautiful Soup treebuilder that listens for SAX events. - - This is not currently used for anything, and it will be removed - soon. It was a good idea, but it wasn't properly integrated into the - rest of Beautiful Soup, so there have been long stretches where it - hasn't worked properly. - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - warnings.warn( - "The SAXTreeBuilder class was deprecated in 4.13.0 and will be removed soon thereafter. It is completely untested and probably doesn't work; do not use it.", - DeprecationWarning, - stacklevel=2, - ) - super(SAXTreeBuilder, self).__init__(*args, **kwargs) - - def feed(self, markup: _RawMarkup) -> None: - raise NotImplementedError() - - def close(self) -> None: - pass - - def startElement(self, name: str, attrs: Dict[str, str]) -> None: - attrs = AttributeDict((key[1], value) for key, value in list(attrs.items())) - # print("Start %s, %r" % (name, attrs)) - assert self.soup is not None - self.soup.handle_starttag(name, None, None, attrs) - - def endElement(self, name: str) -> None: - # print("End %s" % name) - assert self.soup is not None - self.soup.handle_endtag(name) - - def startElementNS( - self, nsTuple: Tuple[str, str], nodeName: str, attrs: Dict[str, str] - ) -> None: - # Throw away (ns, nodeName) for now. - self.startElement(nodeName, attrs) - - def endElementNS(self, nsTuple: Tuple[str, str], nodeName: str) -> None: - # Throw away (ns, nodeName) for now. - self.endElement(nodeName) - # handler.endElementNS((ns, node.nodeName), node.nodeName) - - def startPrefixMapping(self, prefix: str, nodeValue: str) -> None: - # Ignore the prefix for now. - pass - - def endPrefixMapping(self, prefix: str) -> None: - # Ignore the prefix for now. - # handler.endPrefixMapping(prefix) - pass - - def characters(self, content: str) -> None: - assert self.soup is not None - self.soup.handle_data(content) - - def startDocument(self) -> None: - pass - - def endDocument(self) -> None: - pass - - -class HTMLTreeBuilder(TreeBuilder): - """This TreeBuilder knows facts about HTML, such as which tags are treated - specially by the HTML standard. - """ - - #: Some HTML tags are defined as having no contents. Beautiful Soup - #: treats these specially. - DEFAULT_EMPTY_ELEMENT_TAGS: Set[str] = set( - [ - # These are from HTML5. - "area", - "base", - "br", - "col", - "embed", - "hr", - "img", - "input", - "keygen", - "link", - "menuitem", - "meta", - "param", - "source", - "track", - "wbr", - # These are from earlier versions of HTML and are removed in HTML5. - "basefont", - "bgsound", - "command", - "frame", - "image", - "isindex", - "nextid", - "spacer", - ] - ) - - #: The HTML standard defines these tags as block-level elements. Beautiful - #: Soup does not treat these elements differently from other elements, - #: but it may do so eventually, and this information is available if - #: you need to use it. - DEFAULT_BLOCK_ELEMENTS: Set[str] = set( - [ - "address", - "article", - "aside", - "blockquote", - "canvas", - "dd", - "div", - "dl", - "dt", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "header", - "hr", - "li", - "main", - "nav", - "noscript", - "ol", - "output", - "p", - "pre", - "section", - "table", - "tfoot", - "ul", - "video", - ] - ) - - #: These HTML tags need special treatment so they can be - #: represented by a string class other than `bs4.element.NavigableString`. - #: - #: For some of these tags, it's because the HTML standard defines - #: an unusual content model for them. I made this list by going - #: through the HTML spec - #: (https://html.spec.whatwg.org/#metadata-content) and looking for - #: "metadata content" elements that can contain strings. - #: - #: The Ruby tags ( and ) are here despite being normal - #: "phrasing content" tags, because the content they contain is - #: qualitatively different from other text in the document, and it - #: can be useful to be able to distinguish it. - #: - #: TODO: Arguably


FL<=r)^tWt!kRNd2*(Wf!eqiS0tiIqByy!tqT+roNKXdPN> z*>}HX-|}a)~dMWb+qZNXmjV1`*vu_d&`}zwQ5;%TX}9t>Gmb*YMqr*`gP>C zYb=#=v{yMs@lAb6`l1W1Vh)zvSoIjut*WJ}CF#1Li*Ndts^TsYP?iK*kFl!&@L6mS zv^&JM+#lo{iR>Kh57w6OGuEVq(X@W*3m zC82=V(~TPYJ&G!{6O_B*h8mrVU00*%rL`j))pkbRhfH=y87=Y>>##7NYj*(ag2@?; z@U$cf=>m}Gw(zK42-YrV-@5h2twNylZrw+Lo(ByrKMaJHZ~p4BJEI>3I@i5IW9!?; zzH;ntUB01rHQ4*eC$w(6bNbhRVL4dzHFBDC-`7=aYFqXfTemIOd=jc#87_pj-|hY= z)LU%sS!*81HxCq=cYxCM46OA$o$q;it>>A1&oduZeYd{Qb9Obj{gc}I)rNsW?clrJ zAJy(EHgv8w^cTAitUUio-{8Cc-+l2b=g^P-{cC;4^L@wvt-gBlrNT2W7y4dVIrpeR zsI52KD};L2w+X?v)qs5W`PIHd#fFx@XzN`*Q><;hbMB+sp<;{tQCMF02o;xw>p6kEC5dyf%pddDv{a!I`kwT!$roY{6O$`G}7oMlBiz zyBke0!3OWaX!HvUv80(&6^$yHIHGH#QHOjKjcUX`Y9}c;kKjFlb)4-zoP8x8_9gu3 zeF%O@c<6F@eCs};<5)pDS`76Ur2Y-b<>}b)`8-cNYTV`FBWGoeu(_Q>uHgK09Cg@_ zNx#L7uK`~wxm-w+l0}KZ*Sb_M=Xq6+{a=;po2jaXjJfrH%8(Lx-4m%+f)T$`gYqF7 z>Z}k6D7E+sn_ofpRYzZtwQH0rq&1jdA@}#h&l6Z@{ABu z+v&`y>{oUmu4}Pn=m{pw#Qq91HwC(h9U=>H6Idn#xfW6&%QA>l2JyC_CzGTnXQoM( zWIWo4pV7~$xr8p`{}^hS2Byc5tS>;WV!WFSnKV8p>#0m8JEzN;1(XFXomN4x5+KT% z8CHpsn3(}pMzi1n!DC^Qnbu-j0y2!*4;_+DQXQ5T(utV_XfUIlGZ1ynZkWtt3c7(r z^g7AqO4R20^dqz{WzC*~aMGSd%b4v(d>e3(LePECeCQrz+Eg&IMVZy8(-v3aBz5%i znz_pjve6Fm-V)W;N90L0n-wab7>S_@J?Xp5`~-f(9C0lp|LlfQ*SbcocFTt~CScW>tNBXep16EJ|9K#<2(a66`q4(l}vCQk)gdH)ZUjSsYa*3e03$J@Wl}OK$z~UK&qHfNGyOD;3(|I+D|~d0N3kRtge-235ldhmpo{6d z6Og-Ey(aEr@t~3@m5wFS;0$Oe4wOm7=I0qc#b%j6Ph;c#qET5gKh23Hq%3=JEhfVdLcEq&gfvoKx)e>|sK8%FF&T$XQ)v?F#mvGWR>cA}%ImNw0KwP^V%jE3 zU}B^uy+t>9C6pP^NvhX@yyeTprb1C#8zkGhmOX$*JikV~ znGv`+IUY4v&u0xKEgyC$Qujfv*ZMee`kBwlWJuGQOwy>^M5aEIOEof;VFhtO_4QCz zXBVR;K1V?w^f-wn*5ks9o3s+kjDu82(PyPW@3pmFVL{M>NRjM}_RB5kww$WMrN?N; z%o?0MG3y|`1ZpU0EJ%kyy{vdpLp@T0718)aX)M!(g~k-#T;DA> zm5SPWjwR{m)X}&_9TJs_2CS4NFTU))Lzf^#ZJo%XpgoCvLm_BV!TD*I@nLjYBzQ|M z!)S^_N{un8)xmrjvQ_H*h4IPp3ongFUp{>XT*>*-ljG5;(dQ;Lnrx%p$~J!P{M4(_ z@w4OS#wVtD28A*-OkEf~`NAZan~Cx0#Km(bK>CgP&6Lh)vufJ3Q)tsvQR7xL#Aq+Y zGQz>f!Irrxof|EWVNTcpG?JNF0~&Q#OH+_Ruvr3U!dkA;!E@SL;{QYi{saLOfQ22SS(PD9Wx_8%o3a!)bPdpEl__+%dc2c9er?phl> zn;(SK+*jQ3Eam7gLUeCj>)w~g|ABq1j`94!`107t!QKZ0hnL6h2YVq72D_|WA0bzF z|62D``R=DygI&d*160rUVqn`{X-(dnm-l`Y*jtqQ*5u=P`S@zEv)H|#a@4%2UU zap%~w^s#S{38J~?*Dj{7r876cQ$ang{BUmR;87sM!X_ z0qA9{f;Nj3ErH;(;R?D&?6>m;zHu(g5c%7t+A1$To6P~!!qep*bnWP#`Qwm*sZD(DIo?BX zqJ$pDm;)E0NfDeU3Gz_c3A0GU_{hRr!s zo^Lv)IkVb81mY#t8K6%R3Ks`>EOTFMmT5hYFh-i8D(B#tw*sMPsYCDpVOy(7h72E4 zS>ZBT)Ck!!I;}>_rak9042*1*1O7lh+>{9k=-ALx}gVO_4RUcWV5;G zI#JtRV#T-N1cy%}5hXgRLf(2LRf=WB?O3trl39zu1nER*^v zs?V!&rb3LWrXvckjS{iEuW>O7E+U+~S()sgq`8M)+5xi)<^`GxqV9Ha zpaB|XT_wPqWT(^=*F{2Kt;$!0ztdiimsUIfGG^fTC#;S2%fO*WpdSe$d)qx}OsA(M{io=?Xks>~+Vr4Br zRj$F+O4b?rz!(Jsid_Tei!|&rgm?DP3AgyZS=ulNPeIO7G)G7_6}mKist(H#`aKKP zI(!en)`JF=*XMwh$s9rhr&zjl;`KlhfmdLj7P7>r62`(FgnLv0dTWx1m|5>s zhMIM33?<(M_){i%r%Ln3un$26_FK^$^-X5LXSGts4zyACqE=Egn;{D_Gri>c9qV`G zvDspT%A|M#9(M`h*5%sGQVdcnrM1{F%0c30E-2Un;8vk$6Iu9;g3ZV5fP^x_W~nX# zU6>6aq@@VNX?y--@aZB2_>DP|f@!a}Z77^3vwhai{<8%+PUUC@97E@%D`r;#4`L|4 z$xno1D%J?iyK{!ENqc!tWvB%HpD+Y_gkzL2HR+`>Ii|dvl38 zk2M;tAERlqVoSf-7VG^g?G+WzQkB&Y>-Ux~?OLk3;3MvRAt_EK)($ST&SzxvpJ#z$%*E9QVRb#ulO%W%@N2)l@#GJ5#@K~lw z(%6tcIMr6_jv?-xfKNHuKD15>NF%D9rr-<$!;{S1fO(d=u}Rm|Mfl(+AefRhIj(A5 zl#g`VS_fsWg5F5MR1Q^h9&Cx#z`$jMtWGkMfNoS{%Y^Kt;}AxWfNu(9aYLf~M#$AowGHn-af3gmVoefeYLYp}p&V*T_9j zq3zIe==-&ucc<3+pZTc&nFkHstHEw4&bRljbsf%k9bW4?n(sRL!Q^*(zujNxI=x(7 zZ0Ud#Z@y*UTFb$F%fWkd-%NiaT{v{=yHcU$+;Z@f#@0JsYi+~%w&6nC$e%avSsr^( z+pw~jua$r2(mmyawW>Yfc~+3|JWz3 zJJwqF=3DpP>ngN9yWw^XG=F7cy;&GIurg5`Jh&3Nll>^%x4utk+Pl7A2zRaeI@v}r z6w>Bt8p%1GTQRQC8#86Z=xv&UI0Xs?S12IMMy`R``bI5GCtdkvh7!5f@)X<7c^MvY zq&e1P3T!_)?Q{4<5+MyU2k<0n{XL1X^V(opfg$(A#Ke%_k@QPQ|E$4Q^VkOhhE@>*}H4KioN=T&hGVU_Uae59bFHw*PzhZzh1*$L&Em`>$U7P zEc74SU{$T-JX_t+?Xl(Fg0!R9KY07amCFTbu-GNvKE0eONb-Y**4w9+#|lzwvAN^+ zndNLj>UiMqE=aVlNA|Bu&8w|D3(~$~$4EgMDRvDMq=90~lLhI?Vq0fH>U`)Ej*N>R zP8OazvnqA3_8uxoXC8Wm{RjV`X;tdGJ6Dhnp`sVX&xxy2=j!$s3etJ__8&U3Ds`>O z`wP-j7-RRqs?>6)k$GWyJ#8Cducu}s+~j#;W5ng@TMr3`j~0&{FYZ6I9_aDxco1%1 z_uv-=dk(Hw(VI``KfGQ|Zvf3+mJ5yeFNzyAh}<|W)_Phudim(C9#}rx?W}qH?Js6RcTEz_?LyrZ}nI>m$EDy5#CYw|h$5$RoNVCS5wl}2{X$*(ji)yN-EniW5OgGvj0KP7l`hLs?G zL-?)1Z|$;hQ;dYc^|We3=u&JC(9B`P;?9a$$2k1ESqX|AlP6#@ zAJ`;f+5do z;HfBNZ8kqktOa|PgfBxWz9c4uCD+%)UlXB02ECui{U)(6Jdzp!+65I*hN21Z1O%AEtJJ?8{TUuh~MfccU+1_nHmTT&23ISiFD^$%7J4027CxC*Y_dEPjQ6I7pC(*>n@=t z;rayj`Igq7R7utTM}DC?^k({wlJ^b2tE~Et-J2=+j%^m$X@FSP;>P3c70dxd`+LZ! zeG!3E7-hRbuA!ozWM%j+^^v48bg|sZfP}J#wN7XR<1TkLd5mq9%!z8Qv7#{+`#n^; zL3`P4q38>47HtU|Sv&udwNpA^qlm8yS)}j>2Z*SWif6MhSQ*2P-I4fQ@!WPjFMNsI zmbOUS>ZlSdEI1$!A=_M4Y=yWc%9bc~_6eG>y?8MVGs5MNAY8&!-V)IjR6?@ol557r z4K;6uaT^0or>J1O)s;P1yAvb1MADvax>dkrWcy6Qu=vWR~ zcHDGJJetfve$$VS*!lmACVxBXVoJ}|&Z+#fli%2RulL@<9sTaUe|-J!!aEs6nYz!$ zW)VtT#D-+y+p&^c8IPc3`EgTJ--#^P#i->R<Nl#_ zeBF6p_uamCrFWHk;~)EuY+hK@E&Pca#IQZqo^K%t@>D)osfLQDbYhNBgL`JVIHYP! zNWsAxa5C+J+P_8x&IN1uk#0_0uB`$*rKI}=oIaGjEj$(i+w;Edcj4I6&&O_}EbB16 zv$5~M3mZFOUBv^>I=7`4DUC+d{tfb3)UqnA^CS7bG>mBz_MB4#z*7@ZL(WN`n9Oxn zjH^8P`!u#jQ~))mPpHOG$+o<&?aq$7n8%%)Nryd;#Ew6HEX3f_;~dE!;oC%5?OS-) z{yl;Ud@aEo9k0Y!XX0N|x3SF8Z93yw`$p{@-^af0%^gM-4txSqIZd@zj~83&OyZ_d zO;BZWS$VJEOo#P-o@F}6-OY2|TLHB!%MYoCoCu?bn^(lo>X_+J^vB3khOS|NpsbPH z_KJQ~X80TG1<`v5jxP-Xeq)BbDWvEMdJ>YLVPDe1q_ z0Q=Ygi;tsDoq1p9o!O6l1AO!-QTDL4xfwk+xii%;JQ%ag1luY=UzYk1jcE7K%>P@H z0nDe}V0%S_j?*blth?!V|3UtH{4D!@P+ha(LHtJ0<>}e*yHL>QMu4}$4Ik?HlqzGW z#+r?zMf(ZzH*sSXFC`(BU$;RA5pnU3>v!zK=MYofIEW_^&uyl99H~_-l_}X(pIWW@ z)qomQs^0NH9QC1GHIg%5dLcM7r^|I_$&+R`P~nPJKA50vU>1AF;ln&ecrEkD*o)Uep*40KhJ0xTZD39mh!k zkBYN3is72WcOo@wc$lgkB96KU{*kWaNMAF2uu?A&UuQ^U^fEk5la9+)*bN+phk4){ z?i;AoN7c{Z^pjCFJ&W|TVt`tvQs|4}f%!6}qKOo4;xMX66RoH>4KLW#Y(hbGbnA_# zUBQenAKal{qbjDrolV#ALQVy^-p2!jgQ6P#Y4EMrzOazV;?fsbKCZ`f!=)&OTS;8U zOA>#$DF_CHqyl@I;h#y&#$)W>Aj6AyT$qAioM*(nGZI-V0fBw^+mF8|@OJ=z2l02v z@RDsDz4|Nk%5WtU00FGehC3a*Zh)`R`At49fYQq?nua)!lj5kq$~+Yg_>fl=eyBmi zwE(EoG5QRypfS(;ojCjA$rmhV`AJ;43c)qUS=~S!*}#O9UQ37oLN-KgXlP zH5t&>F<;Y}n}!>(8474C)P@+-{xki$vcMOZ?f*AEw7V31pQ0tWOr_!2%_dn35QS&@ z=vm59gHL$+VWJ5Mb3Qc6{KJ`#cA4)430oMFxG{wy8teLEPwCbPXxoG(X-udTWVNuverXdT)a51;Wz{w0i~R$D_5!!IFnY1c`-)6$ zaNniH&OLaU2@ifdK`>-LM(p<=Bf;mLC!{0ce(bAoOglWcH@@!8CTA!H=&+meYf3VN*-lQaYVf;jmxfv z+!vUG6-I(Zfzwy)pe1TwlE>6{Wf?xT@>Xt<&5)tc}I?v0dp z+-$=*uAM}U7-XXivPQsxy*g13hS*#{Wk!-*-`{4eOEfU*DWsQn+_&-8;WrMiT*uuS z#fH{LL7`{hYja=MznZ!?`OTNV@$v_+77jjF=svw%^+|XC)(NlzbmM5wp}c(P-cmsx zTlT{k*s^UoPz=-6(WEvwU);`i+TVd)M*{>u?Y0SoO89*9oDf)f)M0 zlMhV*!=5)Sh=|T`C?u39nVS#w}vcV<3U~bYPhG^ux(}6gSzIGs$yO1N;Uh$ z46Y15Y^ynfy2v`TA=IEFJ+KemQ$L8T9z0#x2fGoo6Pt-Vqm4I+O-70x8>+M&gZ? zPNfOIb&JhIUD|$tDCWaz8kJLtn;__nz2P@E!2N=M?I^nviCquGobP!mv-yA@<_=*F zPJ0Mj9&WpX)Z4U2-W>4$)t?*=#6uy|_xPD)vH^|3&Ep!N06M(q`FSe3K#SiEV-o@52~5&KM#fhN+1UEfGsD(;htZQ=uj*hH zEt7PL1o`syfZEbnQx?+mUO~`@%O24b#Fw~ix~hfs7H)XN#KKl=AHap3)VVwzjavsq zZ38GjW~z=IA0bCR-Wkw2>zP?dGXmqR)#87rG!QuejA}5U=l~q>1Ui@zQEO2{t!6e~QGZys7}-kWdUd#}0Be0a6~Fs@Cj z>3};-u)PQt_RJe+?zX=h`)b$nnft-L>=+%tRIE&DC&K|FV6Wii=Q$pfB=xOKtEJQ> z@#|vADS_Qky5|hvSFLqss>*<0=Du9M7mqM3q6=pK8TzID9t9+L7*#lmJ~{f_IK&$| zZn;DmLuVCXoO^vlx^STym#9Nh3N; z!BeQkdBVAsU3kk6pcCTb{0!ZJoY8W79ye6Sv2SOA|3#y(NA)mh?cPUM1?((#_0UxT zobxTi4tv03DDYToD&3huIV+wony03tc02(kHiGeOf(uhTkV=4@MM%%EB_BkNKsFuf zDQ(wav+V7<2k-`?^E3D<2R&pYeojr|ykv#8g2NX#5Ygq~fIHtOu(6O154#4xIgMx^ zkx)WoYbM$8Fs3>&6)beAj73jNnHVc;4~Fxmr8R&G9n@9Bz3wE?9|0td=F+&GY>IOc z7|r$}lPCiO9moX|ehlIxczoDcmxKpwc4J1ZO>}$ z2#8fp!-L%?34=^Kt`iqf1z$4%5igI!pv{;9-It4L3ZH)rZXMe?ek+#75@)tN17T|u zwFcB!jZRiPid4pw0H^7{A#d*6B_w9pOU$;7!3--bpn{<$4w9dywx`@;FHjg1;RZN= z>x93>PB^8R5_%;{XS4oqBpO0fo5vx%rDsATcb1$4+>n1n>^CF3a0_8Xh>;`GC22>9 zCJ|-T{vAHcP_3!N9owVF`RC!sVVccLJ94)WqLDv45G}|Ke|O~rT{!#=Q!8d`GI`rz)Bk88O9cI|6*d9IIBb) zlo4RUGT&9SQA%Ue0|g5lizzruL50Rj0B1#jKD3vYB>(_6OzGbYqTERx>BZcp!qKkOM3AMI@Na1%QlOxYG~TOk@Te(*CG zEPuAzp-LPJDZZe8-O^MEUVVb8k~?b)PgXikEXgGc04|>) z{~N+LJP_f;tvIQzMWpvJBD+*Qe|LsgNoQK|ly1ewE%OTLjB(w~QztX?i_Vj4FkjMz zibNuqYJg6*;NSJYwhGaTvo9=SWP<*g4;`mbs(22aA+dpLalz=|THGq=blEu)oK}Hm zmfD=*w_ysO_2?kWab)`Hvf!R>3ofqZb_ZuWj~_yNW3$Om_< z1^4BH`|kCA96a=}R;b&~6^4I+7V&R$1frzrU>muH&uaF05Jz(H;fd0LUeJq6v^EJ- zOGIJl6kR(!vw*YZxPn+C1VLR8bZ|?zPL~n~VDu%E1|8pI|LTHv9<{(W37x;rDl@!z z2kXS0Fi10?(SD{ex=uLCHSlx>Pb2wVgUhj?g()DBoO9Y2snUSst|iC82GY(m#XQ#- zGu?58+PDK*j1Vh+lWvt@z1>EUtj?&}!%nKHi=t~NFJsHmbDi_}Zp3LaW$C7%hk{-T z`Y7n9V1R-_3SOoTOQ%LBrwsr3@eAk9OirG8X&nDj3$Cd=Ic2!PNf{DJ{Dzmp=t1o+ z728Dt!$GDD-$|du>M$!mBP$G<44k<^16quM1=oON;DAXtfN0YcT~1#O-%*ap$F&8d z;(tLW`oHcLMe(nM9+1b{#@m7aD)jz^Q2m#}wohF_(e;|EgLoyGgo(7KO(x6t>($5Q`K*J}h{1LR_{`UjG4 x-Gkr%i9;6^QJ*pQt8ecOjfI47KNA{j6TTDjj5WKz(q zz(qL0bj1`g31-2PFefb$OVS##CT$U0(jKuV9T7*;8F40E5m(Y3aVI?ykBLKBYr>nX zid3<%E#XW0BmQI{5=d4@s*^R5nq+OHHW`crS-w3{7pX%XM`Ba5K2o1-h%_V{BaO+X zNK>*o(#*;@6PuGQk(T6^$d+Vlq_tR&kMOAHN^DJTi)>?QZj@__v?W84P_jMJp6rNp zm^jfT*-_4u=uCD+x>z}HBAo1wY&UUc?iEg``Z{JQHh*N%W*_NcsXnCo#qDDeeQ`=( zqhv2D89>QuvCl}|$x>^OT8sLZOZD`SQF1pc8AQoCakr8B0!!V5)cUg2JyZ5@gK9Z9 zFsuen51$*{J1mLf@yU2X5T(zl<*-Y&92=ifts^lxty)jUN7AZuAT3I<%L!3+zB-YP zr^aIm)pZCY6BC1uxZ@tzZJ#o7K#MyzNS5({Zu@U-9}JWtD-}(q$p3sM#R_84DuJPP}rt!Iw_{bk+l5gxxv?Bk}L|xWSX7oey#ufxq%B82Hxmbtt`b(esr(u zr*GNh!xpvH=s_?>sd`?ET@m{eVp1GWtAX*<_}f?GX>A-)NyPlzNB2rjXhD|n4i6++ciL-2_;Vyzg^bBu4*sFm{R zZ`3XLzix{JS!+JQJ!%yKU$^3tR*O}FPjDb!gZL&KZyVaPAs$4$e##x*B+(^`jhQ*_ zby?&uT}>wwdlT`?{NbzV^n`quio z)A{COd>UuH*UgfKQfZM-UyY^tOLP#*ufZi=NQp8(o=Wrb!LKpCq!ICKA!HB`L9mm=yN}H(UHCmd@^+%!>9Ta zbQRdF`IwZN9LE~ST1%HjoJ6)R>EeQ1m=H(eXqU!yNL!?)@Hmj%~O{& z5>djqu~3&s5;0ju$Ei^^ES|r#=HOrAyTslrz5JyMBT{@KeJRY-ffsnJDGipcQE}P$ zbnHs8k@z@|3pa9=6_MEm;@`$BMrk^|tWY=qR%((TiRq(?p$FV3+_qSJT$C>16ckq? zHJ+HFV4C`gVVg%LY1Or6RHwdzs&(ktxqj8DZ{4t3JAD4wiL)1?g9AhT(V^GR9q&JX zLETig|EE&Y>Ea<(YcMiVN=#veqwM5~l3I`DlA^M<#-b1f;A9|fNVO*!5L27<(L@Ci zODUBVQme%qBZ)~tG^)v}9fxRA8XwVdE$$2F#9tf!R{kZtvz!SaW5ztgMG@27j72bw znrEznc@+Ona=+TaaTjsPZrX0zXKb?RU00ee9&=+>JyiM%mKpoEIl;<&+dr}i_KzJO zp*}ei_imS!OFOg}$Bofw*0>qd>KcfHIuM+r*55JRH<`F8?)NQko5HRksTVb+K6ulO zw7C;f>UvzjS&8x232k8eC4PFRc3J4~=v${9_Ts9udrYT7zs9Pm_j8&cps!m_$40It z#Oq?>RM;l5skV)8{fH7SjV7bS5bC0}HH z$rsb{9T;YMQoh)GT^zrDaWH=Qq6`qQ16c4H(2{)dvb?9SINQFcz6iY&Q>t$QE#VXu zhdtf87RvRmF7RcHO}+*1zjJ?miz@`Uu9s)6OU_Wi%lW!8;r@*GRK99UhJPXB-Lqn| zw7TyM&7PhU{?f?>8lDCk?pNKb%5Um>WL>uz%(X-&n9R5Ge`T{&*AzUc z^t^#{wdS0M73bl{Z)9Hk(i7+TWq;jVdVY9eZ^jqSI>Y}<_Fxe2G#qO-eft;(f24T6 zkjim%+Gzt}zv@=s>Z4Y%QJfv`a5D#^_%? zrhU<`cXbNIKDK=XI+)x|+{Q7V7B2U1na^t9EtS4wd?~Dl#gt6C;uOv(em84+b!!?1K=CsGrWiCCKQ2;N*;MZ8_&Q&S^--0X=<8jhishNj=y5Tr4L9VImN%YwF2&0b(_kq26fOTf@Y6vw|EPbB!uMUp`1 z{hXk?vepjr>=?P z@oDs6M{zNhRJ|itW0KA*NH3y~uw6PxgJQt=6m{wqZ-5MlUIP#ZShrv~q_aqu>8jIa z@VrEnuWB6?MPa&b9gw8tNviNS@BkN`oHuay;GKgR55F+{!CMdC%C#R<+7D*h`=5G) zchB89S1@zcubcDDn}2GvRQaC!xSFP1bx5fWErxR4$CU14OV!6`?RkG~&flTFilD`8T@7kN&IjHO$oE^+G_9)&R z%f6=B(YuK|iTQnsZ}-AQc(a!0cFwzLZuC1NOP*~7JJ%kbJ@Lf5b(!zT@jDfMXO7>m z@cVQ8NrgZ8>6aA#m5jFq#kTIw@%t2hA7c5?-q{mN-mUrY4t+dNoEoTaq_eRgUks82Wh;Q_3tZSd{eu&rTR|UO zo+={+Qn-(F#L{sbNOo8<*Ooqg2aO;A+7=Rrm<3tUEoEHyqC*cOp56k;7t5F26xC92(Dv|oCb>k z5@TG9j!z~pgGdNlrEV;dbez1`$)hV3HfzWI0>Uz_ZSgcq{RmIDtvk%?Z{|Ownmgg$ z;+_Y&wu5=^)`dME9DI22(_rq{o64~_pIgjrZXyI)aZCci;-PhRNas-r6tWb%LKO6> zGe9F@NSbgV#6PAP(=_&t?NiMK5x}!-kuUX5hr!h)6GskT6=TAY!+qN4a!Qyw(k>tF zV*#X6kq?b2zk#O9r>r)DCr?N9@kG<9s1Ew3yVotmhGjpbW~<=c;+Fk~9>1yh`!mjd zHrcRcXlMwc6K6C^n;VTn1QAW9gvkVjz0v4bCu50Xjw4FFN25|Fnvw?KLGTfcjpJ|t zg`~!1WD%;C2s2Cd5d#vftn?CjUm}n8TY8JU zH_4;DVPK81(aa<0DAO(e4epuQXLA;KuDbcw$=SB7wQ0GvZ6We#)8k-f%aL2BXRpr5 zcamA_5rCYn?HOzRd@ySbEjR4UT6gAK+85$V3k3^q?!e*vp(FX-`<{84ZQaX(rh*M$ z9FuL`i(zH!o`Qp-POg2&;#*2+f5AmjH@7*oa7JnFD^Mj6m+qRm_IdZhX;$WO!>3{8 z;NTC0Ov8Dl=7QoHUa6vDhudtu^M?u?K8v9h`V`KXs%)M4_He<1@3L#_iVfew7PIY? z=}}vOqwnLk=j_YYV+36~YOSsMsozb3~k=43oN$#6)Nk zY@$Oji&nuzd4e4=$YMsFv)rgjaDKfi;u4w#4`dr|$WlC_7kOq@(j{0S^{7G)BqE|0 zfDXDo40l0y{;!L~(>|)S{5Cu(6@Oyf9z0kY!5MS&BHO5nK z^Ag0TpwNU~eqfZJG6WbC5TXzn87sBI8YvQ(z%pVF;TfuNMITY99#SSqTxk4Yel-!(nz0JR5T_=9%hDjR7@G}#RE|S>$xn{& z(5DI**84fZc}7AqI#Jq2QNm4Ov&v0-2w?YWBwyI0ojQYRRBKKa*9;APS!23Y3wT+H zj;Lw_zYbEAFdl*1_;@@GfJtXoYu`~qdu13gM)|D1D;i}8J{pxvEcY!9A`)FP-CB8L zd-cBl84Af?g$GvnnGYmizG3t1$!`q&q(tL=#r8C?jmSKQwaWKXH&@mD%*{1+T{Jzr#_8mOW;L?OeBL)qHRJxQF{H@%8w-Ez8MkUs`kBV^?r9z*0EVtAjm~2eNxNb@Ib68l|zg2Wq7x^r@@Br z)Xs|wryeA;!Jb*`(`_B^-}s*8;mt?l<1@;>SF+nq&pIn6{-mZcSJSQ3bT96C)bRK~ zw&vulqj&Nju_w(!amXODLKXfmqHpx{T!ZxbyUyMIkM=A_!ZX~Cbh@}0ST3hBmS zL(QU-4plB+i4&^C@r)U0PHz!Ms~BYBTnk2IEee%Dl}rN>vN7Vj)>S-2B#OcT{Mh_a z@eRC`|-C^?@be8@7mhusnjOgdYVOAG#B;t@#n+nm2Ij(x?#JgkLM$Cqox>1m45gqXC_h;Suse#; zuL5?)=`9gU*gpffp?J~h!07@fC6ELN{|-J93G&!(=-lRQB&=e+yrdWd6ZrGjxxCQ- zq$Y^%!Ik#cf5)+4{dUzt`h%&5* zwLpOQz}J|RN+V286}i{0a7oUmDVvB!10^JpmW#EqnoI%(Mw%oD8;DBO#qI_VKM8^b z^pl(>Wgx_jBL6l?;z$!QGAWV143)1!j{riCQJN{z(oy-+IH+MmEy$QgA~h4@XqvyA zh>c$>$rGW>sD(Cjprk|Wm!y;=jng8RBV(O8{`tswRjI$EHZ*=1)Qf*x*4LJCwz1>* z%Wltyrs?^L+f%-TpfT4kow2T8Yzf((tXn#xkxEM_{aws+-GX^QU+YI?dfNuzqpS>x z2v>@WdcM+>EK>y`?>dBZRNt+~bI=_SnRPI4-D;B8dA?6Bnu0 zaX^n%H`t?p)bWzrfzBI@H@RYaxboDGVzVLtfY<_DW0F%hmvKu*Oi0r9|?v<(M}Ez!%kX`sYD0-*bA?@ryB$~YS|EKgv56$t$TAV&K8 zsKgFSaV;fkWz|yp=pJ7H-xW)cuzI?EgLAXG7;Kz4>0N4^WH({+&@iAaaRC}-ZI$ln zVU{|i=eAMlO;Ut%e}%k@utJ|gz-QaNP+Q>ed8BL2?UD(IeOd7vw>1 zq*ZNDo+L{?mgg?E;6;ibDFL)b(xqzFnhpI}1s~!y#ds~^e#C=Qu5dtglF`#(Tux6P zJx}bp3`9jTahNN?_9Uj;Z5726Z^xz}NJvfqH<57QZ5ZSjn6Q`K3)Mz-R_g}{0MOqG z9a#W@)q)<%VeX65#~%?`frGfmfUzYwNY_((g}m>O_dD>)Z!5bC)7ARC4gMeIf}Bk3 z5Wq(L7VziZr*)0q<}ycoQm4j6z zC$}MwNVD3xllRZuJCh5Blwc?u?8y2%bN-!*e`gu%tudH3W|lFuidQmd(tnILHv;&T z7UYIWHk-IOcq^O_OQq$3IjO-+U+3hb8=M#Yc9t#NjO98f-PowzFWydh|I%wEvw#_M z+O2n|Q`GX&Rr!REm^1P<^?yZa%$Q#0g)~kZFOIxXPa~ z9Y!320`rh+>JGcLds{a`oCXw7(5RHIy=nns)j0jrs3g5d-T*wc$tV}aQdavq1)q?Or;$b4!v0v%f|F|aGa99Z(1~V4iGB3VAyj0u$w0`SC`^U9Q z^*b_w9hv$a5DC8Lec;VCysR|5{4^NK1$&fW&*JOZ;0r5|{MF3aFsdzWv(~%bJKnkB z&zwyRT2uxUw4ncQ0EG?=EZY7su(yEL*WG_goc0+D%fQ78w4@qcSMl;^oSpwaC-Gs~ zBvk7)aY|k{3nDY7tBhGtnSC?~QmmChu=}sxdo>$u&qCo|i8Li(%>Z@}0>5}4^n0bR zwOO?!#BmM9tO2tsRDsCD84ehOET$Z!aR!RxteM+$|IocdzxlO{bBngb<%oj9Y)-7jAQf>t&=Krr{Bw(Mad%JJa(a#owAK%BWY7&IY6( z)W&Bji9|8h@|hr?TqT&UqceSVuj_M>ejhcYe-3Ze6rgftiVO$~vAlI<%Ueo*nI_SK znrsr^N<*x2=E0fwUVZRtcJq#GeQ(C!n{oEC1rOJ)C8K|py4^}1BdBSsG~(GwA%fx> z@k|h!p;PI*6j~sU&ZTMrdoO)L(eIJRNbr9_p*33CZ&Mn1bu?V6`WxI2t!I|20)J;P z?`h6jn+sO6t#`o!84*;UPLu70`L2b%i?xfXO!y_G?TFI!GSRXx6zqOm+k&OQ;j{QE z`+RC$p;%#?$<{S@W5KpCviNeQ+d{c_KAV?-z76B8kGGX>=2IBS#XCl8rEb z^3`)i`>`_fkfB$H`wwaM*RVx{ItucJp=bffQTNHZ))`&fjWw8t!3h>p>WmO``wIUWxR4Nq7XnA7hC#1<^C&53#3b?Y*8{< zhkZC5s((!-)?DR3pfvJM&_MbT0Q+0jkhL}xnP7kYd=>1zveu4eTUEjAu!ZK^{*uFI z#lqQrETOQ;WD8}Qx96I7D$P6Th84L_YIoHQ)0u*m^XRSe4J*4>W}@}*LwdLUe-?) z+SlHSILN?T<2%h9UX8fL8lCcu1flqEWOfe$aL5b-z!1QRF;(O3NS*c~rT8wTsrX)` znOQ^B!}@`&AsR5=MvRv%BAO6x9y@?xt#QaFONkcb)3`K9W6X(JPi$dh+oEHiNGo7T z3lqO+(1XE@<7k(`kyVxwR-`iY{0;&D97g9~6!p!35w4`@(U-}jG0M~rbIc0E;2N2& zgTd>^NH6A(8uUW7eEb>J<-!GsISdQ5_ zS7XlEqBvV}&JM-dv5;Q;@;|-!;l(BAp(6X74>o{{cI6wlfo=9__<~&(0>VR;X^HP* zNtuSNOeu?HA~3SX>3ddE*-mnjzjE0drkm!QmT_<8TyUIN>N1N%%k6#OK#j#Mb$q+K zjHk0y;Q5*=_fSdSrsEfEv-$S?1{9O8)VCgz-uZ=eR)tzcl{fZ}+^RK;eDS`uR+v_i z2%|M_jDYDHH)EYKPa{p=EvU7vV|8l^AzH4&X1c}-?MDg3GdIPR?SpCkK1j`&Q-u~P zj?geCqH|E`q*XG{mo{%uwoxBr=_?q#`Az%yOB>W925gPHz0oWx^r4?7^x&=B10MTS zUK65}*Ej+$l~!WLUT)6CObtH&TewqD`I4nKWQS^PG6e|&Y@-l~7L^cTKg`WRQD{Jw zM{m*}kw+Y`CQWcKlWlr+N_0HQAT?#Mo0P#2Z-KB@e4LgqNid zK&0`SN=E+zh%?nYj;8g2NR#LhMi2+7V-l~cUaj%y2&q9-oA&Xf5_qjueE#X7ArvFh zzek-i`yx$l!35^hwK}vc)0qeaFel)F71_OS*83BWf6jW}d(WHow7lP{cy>Y({=wmg zhcn*3*}(^UmxB!?(3tJdZ)zd~AqW$yYREo2P)C(Afv%?zO-#N&vJ~uI)}KHb_NRg1-0=O2_b%q@x|O=_#obC>Z#K~Py_c21amd!2TQ%us zpVHL#$gDKIFnc!NwB^0vP_a;tehQ%93|ie#e2? zlXnO13_S66{{#l>q4zCIei)2ye$Vy5m22ox8hT)>)36%?5jRYT@6Ozr$@xQ{`9t}R zZcXHJLg_g1X@9okj1p+eSJ&O&d~b8Ex?8F4&Q$M1ozCqa#2?0U9Y>XpquGw*D738A z%pioRqwAcvQ}K3UZRUmd5)TrYqZgo4uj=|KXRgw)O=Yo*fGsR1^eZ3r5{T6Cv1E>e zIW5`nRIaB3I-MoAYKNR5Tc%ZKeBU@7BLc>{%@jCr;$_(zX?eO%KT4~T@6%xlp%Tbk zPu-kwKXEVd{wqtKo_uZH>;QD?^Hvg0W&Q0LXFEf;>Za)F;sZsa^&!|XtF`OXWz`)s zMo<|!{{;p>;``gr%21F2J_XaYlekqsDp`jD85;BohFx?zsM1%e>_sAwblLiv)5LQ# zr|$t?E7qqCG%#cSCYiXvaOEYk{e%@M5uxlwBC#gSm06FP^j4T{RVDOLL9kj8S#g!v zQJ}CQnF4b=oec(J`+{o_EWXM#15gvFZqR2?`pz(7{@qPhC_XBpw@TwDhG&hd+`7IW zq*A7TADV}>w?IDW5gO1$iwhJYunprodhst2-qLK!XhAig?a&{4AQjblabsPi{%)_!h7uutQ z_GCl*{;YNXJXzW?B!YVqu;yq44-F45E0cU6dbc0z&cW`l@Pv&S zGm<^lbd3(COKE>Zrv+dTrv-;2&;XFU8X-P9`Tc=U2D1Jmv(_Ja>Ykk(e-J3HsNbn%35>^?7}Q#)FAu=30jL4A*A_!uFPS#D zB5+&Z-JpL1Y?m66zE##k`C2QrEbH1i^uE?r z;^x5TR9v@pybsBZ*SK=thaKfL`4k;9w11^cLU|SUs(69GSrT7sTnwi1lW0V`&d&x7 zop?j~V12@T#H@GA`+W+C z(4R-@?tQfD!-GoQ-fUpsANDDM0no<{oA1xuo5|JpDD}|UJ^IpzZz=WrXHP$^t)F-P z_L29aO6?vzbkEf80r`DDelMQe)U9mlUOezf_g3T8%s@-w!g5p>1U0{f{N`sIsC z*7Y|X<37QHTubF#%%cLBy6G$%qjSx8uFg2Mw*xm_Gq&4K2sd0&1Bi}0aEZ&}p!{4> z1K+Xos1-GU70SD2ET#C2{Whi8qu5K$p*J?eN|;wL3AT^zI^MkLo^cmf$}!_EYtw-? z-7}8TDDev*?(!Z$v4>z>?!nkSrQa#QnpIeviXs<}zDD@{kPa(%1tPF0oiOG|WK zlqKw#-gOQqnTIWb_H+v>5tx3%Jc)7ZkUD54wK2T3qzAdk>pjIt*CFZOp-Gt4slK?( zo)l>odV=a9b;?8<<_3vT9U5wq0($lYX@m5iP*Wp(8BqLFMAZNcq^{HBDqS8>mZI1D zBdYgJcwsLSGvKG9K&WcM5q4kIno@$%P7RDD@bbM}R-rbR%Hg+1)`&GWt;^Iz7hUVp zOR|vF&Es)>v}i2q8I4PjnrJOFv#wZpUAGd!Xl7f=<&Fcnjsc}( z;0NuQFTIiN_%iH~pL%>5|JIzpTk&^iJ=+&!pLzPwSg@K~6xng&o~U&F>$`?SDhr{{~?HaLgG&sz9e@m}6Zt=`+XC@X^N!j6cL(#{Et-rZ z=j~Ozy^E7iyn72aZc{6!zIn^6W69Z&Z{0QPc;eiw;VA=(V3!HnGl+i*fiFPm8}}E* zi%!4gnq&YHksl%hPYfR6qoFQ#wblwl+*f1r2~7%EBC$(p`+xfCXkiz z{st}3xZ&6@$ry%YS{nI)$GY@@Jpuxjs!(c%soa_Lz^qHB92&9r>u5yV5XN6KtrrbX zBAy#Rl*GiPU!w#@_*r0a!pMPcp*Mf}TbT3*zy9#ov;KXvRuWA1eW&lvnb{L_b@{d~h#z0Q z^XmMG&%8XYL38)AzjoHMe%lRlD~O@sjD@!a*Z#xmnDC`rocSnsP~+b*|FG(&`_9P zt6Sen1xj}4qz=-wki=dyQxR#2LL{8itZ0}$%@d0H$Ro-}`ZMzWD|!EhJSO(}a|->4 zy#GPo|0a)F*8DAnN;*$EfRYs#TzksL7ILk&p3Q)~H&ISL29LD$WOY+g(-*9ETU)-q zsbHb+wq4ry$f-|nDo0*lp~RKIE}O3~YO>fm=5MTU_~21QxOZ{n(cZ_kk4GLieDZRp z_qft^B4cfuAIMry0B{4{bRYe+Ez{kvw4b6MS%8K7se*Nj?U-rNnb~zx>FO_V6#D^w z?|{C~j+*dOGV?nYTe8*rZ=FFCr%i*VXBGzr6|66?Z)aa-=Lx0rB#SM(s#a{sEz|^T zt@&VQ!9w5N{p`y!5nlg z{8GcODxnu2U&!Fq+m>T198#Zox$4IG&DlW5?E!Y}*wGllx*ATu5i4Cts%)viEEDi^ zTd)-%>v-Fg4J_t6D6WB{;}mLxw@L~^?J`h)34#AR)jM7`<0g?Ss@aPm7Me)<@jQLx z5QFMsqtYR}idv=N;aW5BXsFX=Y6?J61Bq04x>|p}XK2!2MelM4@_@vg4Qur1!%NQH zbEnCsY1+&nS)%1uYxIYE_!&{{cYD*J?UxMf+7oIG_38az5blT=lMlb4N5e0Rfq@wGnZDDeEM!)|KK_<0(PcG&(8R~Yk9 diff --git a/.venv/Lib/site-packages/bs4/builder/__pycache__/_htmlparser.cpython-312.pyc b/.venv/Lib/site-packages/bs4/builder/__pycache__/_htmlparser.cpython-312.pyc deleted file mode 100644 index b6638bbd20629f9042fcae67187b3d3448f846e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14625 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 OLCwXVbM$84^M3$lyY|EY diff --git a/.venv/Lib/site-packages/bs4/builder/__pycache__/_lxml.cpython-312.pyc b/.venv/Lib/site-packages/bs4/builder/__pycache__/_lxml.cpython-312.pyc deleted file mode 100644 index 70f3fdb157001978aa4fcc1141fcdbd18c213eb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18452 zcmb_^Yg8OpnpjnLb<>Z6ZlHO;ikGBDqCtRUp*IL*X(VA;AV1pDwp&zzTIvU`Dult! z7(31`@@UuC-W{Q{&KjL{VzhEHO0r3O&g3MT&CaYhyUBK|k?E;0Ihqr1PUf7P6THaB zv(Asr_uYDQ1C7R$GX>nbkMDl>_1*7vZ}C_8`3?%6r!V~08 zoe|d0M)Ljnkph1K)TMZ9*cEa6-6WnDE{qiUi%8rC@nU~5iQB`TNQu9M#2w+%NSVJZ zQtmI0RQM|*mHx^|mA@)d?XQm1_-hD^Gh7>~^VdZ@A8n3r%;;kO7bX0Ld+fTt;XR z4%}t5{DYGf-l|_a8U^E(&gK{Vql@#-tlS4|$=@-tN9ufticRUp41@U-Hgbc;C zA=~Rv%stUbh3N|o%Zlx!EQrBNVL@R|ha^ZpGlnRGVZ}Ts$cklXd<@HmCdULNf9S=t z{efdA`j4GDIqqa$lhX-Th zV+s>~H3Dl369x+oBNzt8VLW*d10tl?h9Gj2l8rK+ev6Vd@}#IZb;V-TF(P-h*j=qw zAGI-Okn)>aEf6_H(a@7Pb$L`<3G0l!g)y$r3++Mqzh7P zTpSiIh{9M*x)8zDkuJ!gRtdHf#C+F;=(P){LzgZ{Az5ezy1N=26{HK7q^`D0>egxt z;57QiCKda^Q6Vb4Iwl^Tstkn4lK2jWW5dC)bl7K<^+8W0-24BF`sECjaCP23a;s~8 z_k3`!aIWX~t+$W-y@Z?m&B9_DM!?|Az)InMv_KakxUXnl!inX?ryx}Fw6?@Ukm`j$ zsRn`>>IFWHbYmxpz-krR=_K%LFT%9RrXM*Wm0{}`agg|iyaOqVdRXhPT@{Fjy zkA;JhG>pLdqb)YQ_7mvA@4#{hl%M7)zv(tZ-jT5ow8H>9t_nVelMxh^j5yVoPUaM2AB%1WS3!rgS;0YYxG?H5Z?ljwftdzC%o(UBm6FSbNo@h z72frH5ATC_1K-QH!Ml+^#<#<}X_k7G_BX>u>=SWSr%I4@zeISm&mf75il?vtc+dIM zLxHnB=LY-F1&*EW8AKL&DHaPW){qnc>Yu72b#pS?i%RvF!JdIs4gMS$M(Ucf;r3~T zKhX!hP?&+9GyRGg(%jn zWK5n62w?#QTtE(vN+R-H#X5%aNc^V4K)h*5TmfDf366*5fC@Vd!#5t}bnr*7U4qCT z(7?KlBH4h8Q@;yLG*0V#f<{J;&2M-hH^-jN)S9G$jlXePkU9CXz^xN6TfW7;u#n%@>od-k3fik_JB&3fq*75 zW(boNp99dT<_+qTs#WVLgyi(g8S1f{vKK5BG%gG!ZTmm%TCyEY+t_7WebQFH z(6rpJC)u#)p>3~t7@*fJB1!ILOq-f3-u4qO@cFWgjsL>ENfBPD7!u)R>1nCUq68r~{9N(5=GK<9tpj(YcVFd-= zSoev`p|HT=CIGr2B*@2x$8ket5z)})kiK#zbi&j)_n>%*i6?0NjpXI1-a&FBgQYOec470w@fCR*;}KL7AI? z?i#&~MZ=R^D9TC0u`z)giHX>AnTw6A?>To8GA3eKXt~S5YZ)}S(f;Cm-p8GfwyG$EtlcPaK~dnqoKQy!aGSQHwoh?KX7n~r z%guCK>mN=P2Ot1FBr}ar`U2+VX*d=0Rbf)GTnmQB z1)>}w9(7+n4{%d0x%XwRJwFNX5;i?UtyWTQ&pVUXCljuwgslm}mCD-ri4Ui5P5
F3FppqaoKY5_GIz) z1iL-$DqeQ&NV<01V?O0Sdm-W4k#aqkus!#LwN=d|SS!usffkG>BWI^gS?t<$SA!Lu zCJI^b`V~dvhOFv8MWa@mSS}dlKun6UF%jokU!`BYzN#eE=NI=bC{=_8^i8>6CxIRv ztG4#i`0!;e2#g`hy}Use$&$fCVh{!l3pWBU#RgVS7<~y|b7u9#XQ4gOd@3tjg-_ialh zCufhRT_v;m>at~TBHWUo0MTnESOQd%;&hw}K&JZeu;~KELc*dldP(LziZu+JvRy9$ zXyT;P)9PDaYEsLPssLNC9u89?E4%evXv4r9b;_Px`9L=2YqV&WON~-9Povo)qn$|} zxl)gT>IYnxH-)IU`6K%GXc}y0uX#Z61a)Uj0J*xV28m#NQ(l+4841T8fDG{&47xEu z6-ucHg7tn)$Z+t0CRZe}4}q#M=*IwiA!0Yh^BCYVD7FAt1tB>Q@LE(-K`If?Vv+Ug z1aJsRM8+v0Fw&}~kwqXmRhye+bc}z3^(G(yRcy70;2)S;hwhD}Y=<`U3nU~U8hY&i!>Gv z$+}cEgRP<14QZ<|B#Irw*;TitJpg=pKpF~;PStHO#X7)!s3@TV3sY>RSl8?;*Z0m1 zzI`ZNTfb1h&@eyxVdPe1@z}k>RBh+=XJ${%$!Sl`yqqX*O0Z3jJmvF^a|aS^tvXe> z#`=TiNFz>F8b+e~esbx-Qdx$n=Gv(^$sj1TsiP^`Fm&RyY?wECx!5QJXHcIEq%FL)5`0k*v&PMQ-Uy?5qkcsz<#GB-zTQse&D(TN!P~O2O zo9VoG-j$-PVlCQ7T?FnlZG%#SOJ$(q>qc{<6l?)2dg{E6U@wr~xp5F{(MePp!=XqB z9f2U9gfWSW3d7*p#WZMFJU)QsU6fQ&*4eW?zlT6}`T!@`)1G6z9X+fgM)mX?FA z1`c%nFeuCuAW?~G3WUrBxl8D(CK3@k!gIqh;=kiUpa;i{Ccw)LniF(EMw8LU4aSJl zBLsQW;>U>o-{5-2IRJm5h)M$LRyZLB0$mLN#5h=404s*f4Njao)nx9-Eb1l|ssKVT zOY=iR1I!uJ8?)wEv)R?f*$-0$mWrC-T3flxVETal1@oUhr%ukI9c7f`xjy03DuBFScnB!4685+e^9KH;G7C4>|VRMXy;cx|s z%bPL$uy6ga^m>yB27WgH0<91gNuaXPNn&Ma8wdAiHpL+ZeI0NDbdpE%LsCQdknB@i zF%W8|E6^lR!Mgq%bccxX`Gpyn4ahnNsLI1v!(fMpi6k7y{QvXA|0uo!?}6hAGcJ$p z^D;^~`lX`iNJHf#YtfVfLVWs6N=hF1I4{d^Qc}2SfxS*u!Knt^N)6~L(LiV77)&D$8&A%^VxnqRp^izW5d&2PD1a4)l@YYzY-L@ohx$vv zBbh;7lf#YGUK&m8*WP~Zv6aeiTxO3Z*`xPM6GP`8vd?|tESVemV0g*d@VEd??7iQ6 zZT{J}Utid}Sbw`a(cb@{u|Hi=w?HqL<}2r{>7w%arUbYD)BZ$J&jYq6QyY{HPvy-+ z?;ctxO%?B0+?MD#{h5#`8hXGEtvaau;zwP36E^Or&IU|1FS9$7?9RllV@qt`qn2H> z1wVB*1BU#nWwt)a)+ZVcF0qHcC~i!%Md{{4=_+r!y!u1uE$7@b>Dso(POHZ;YXjS( zqJFu&WvRSn_C&h4>gJJmk1U)>_)dJ*oG3b*V$XhQrYd&+y@YE1o5yw>YoXWq_E3%j zQPOLRppj&stbsP7=_nLsXd|p_=tLQ9WZD$1%ACkSJ;S0f>N&G462r|4CS^|RMD--T zZpx*RDV*xc(y)+su_7Q zxjcOpj>*Kq`2W}FG8WV(j8(t!KGHV^x4?-O)Q0D-mPY%nk&=-Gkw>mIVw@hk(xAsO z?-6qoCAy~>xmnMPGx|!r2}gR<%y*dydV+e@{2~Q5x zit{wE(eW{o5RoJl=UL)1P;;6fN4FaZb2NowaA+Eog9berlPm zPO{bWLrZMKN>Rxi|GszrmG^v)$|`P7ygM;3fB5>X*HdL}bIeL{>74w2_X7RiVX$Ox zo_hDxvZpEOX<8Us^0Yj*Q&3FmzVAbhSE!<{NwPH$*}7k@xEnq?^`|AvyL*$ndlRl> ze@D^wmX)Gy3$LV#yb0F(e^d$SJ7&g}S7n*-eJNsGlk68=E z*B#U&<04EA%-Ah`oW%K|F%AmIR_p*^@E93B1vrdD$8Xl@wm1jrsjA#-MyO^lE*jF| z47J{(|6QkQQ-XP6JZSBaZoUe+Te)I4pR33Q4xPVB&Vr04_qY8Z76s9d%tPw91OD*B_WcC!0`IR7=^%q2q%IC4PwEnAh57m+8! zvormWON>(Lis3QS^S~8D?0X%4+8(!GF{DZcDuWp=moahsHA*zc?L2b`rC|=Nxn?JB z*INNg+~DwW^OI;suK~0JvXHoe9I(20#jTZESer`FfuToNYQkZkw^j3*u~?TtJnQCCns-|&Fv1biManw;ydQqw1S zy7z>5TWzW=B__!){sA5ZL?GA*QE94X^PPo`_V)HRQrd?0jp4YHyhZ9E+8fX#RR~|j z7#^n)v8uXh-@@ec7~uUN)oUAum|`6t134+EXK+a3;sj=wXwF-7$!9#eit93%YGF7| zhcg=)Jc!^FMpiA#SjU3CV@a`)TMpn`6ea>BN8E!TdlAGImB3Vh3vJ>!CSAkhBKkPM zx==5%S=Ca-Zn&WpCzxiSHK@25e2D?5E1~-f?UbxXHCZgAb6ZIZQrL~sq64HAaR_ga z-7Bt&`Nj{VC0Ap@)|hZLg3CC+aG7mRvdt-W`>L6;7lEx%Qi(G6`)98A&GyW`vQk_# zAN;6zskk}8HYbXkH>T57)!_3CzI}Q%k19bMq`hm_mTuiWYyZMoFgyOe{qu!yANfF9 z==%7;?E|U0wtMvt>N-J*&;@sGlC7PWAF@p=`R=)r@A>EJ-~KI9toCa`SYmf=0RLcO zVf+ujyTtk)vs7KJUUgFThOa2A-Lcu351NFk zP2l+iI`e1fNjl3eqpqM@wBgaYA#iXw<-tR~8Ty75xQOW*C_Xowc%u<_<1ide4N~AI z#Va=5#=)+(Z_t584qdcU_6;Yz29xj&cuk5;1a}BtawQx=KanH*ut2@12tG0Oh7t}5 z_7&Mr;vYd`YG-cUD<_wD4|f-`8Q5JmiY-Yvt6|z#YPT)OAHR0{wa;riX9v=*nxxCS z82a?^1K-JXS@S|DS=Ro*-M(s}>bih>+@8%7%>YWGwk4o}--y}<2sb`Y5{*Rt$f3$* zOmZSxOw(vM!KIovc4R3#In|{NWWdB3LI$Qdqmcn9k4Og7;7y6rM6_+}Fr;&;6>uD= ztEuZ;{7>u$D1&{#tM`Ez%cW)+DpjTvhMH@MTi)2p7=A)M6ovSMrX@P(z?t?Uyoi0N zddTv?Bi09|91%<+wnqq9$=75N6oVvEO-SGFz;1dXxBDjSX zh>Zlu4IGW)(RHFq5><$p0qaynZlZ^xe}W{gKpikQT*d3JkAV1S0s~RMPGWGFilnV# z$yS9HpzoG%(UYq5U3URb>VnMyjL7LpIJuREmc_0g9Jq7f^MZt%R(zp*cmpxzQUUf-Z-2$_4dCAtc0s=*T=e6svrJPms!3WMd z*i8-FKCZf5^>N+px>S7!9J4)g)hAr7P`|Kb+3icZear5Sq`Tvxy9=1L+Xvi^<<$L$ zoIrmtPWImy5P9?nzJ1F8X*kR> zE$BOvsA#4Eh352IO8)|Y6sJaX=vyF%**YJ+1f}91K(PL1gJ~=@Ri2xS#zKFJROE*` zo2h6M)woLL&DZ1eeA3l0%NV6KNn6c4zhrAPa*)dAo0cmNBr6X*v>ki`7sXkA@+xK- zn)H^2W^NTZhk=pdk~p`j)vsLudjlsAtYAv~HxPg?fGCw@Hc@u!k_a=l^4#Ep{1E4} z3xGDyCn|M0ccnUm4{eR=OfgVfe+(DxFCpj2GxhDME<^7bmu@aPL{$JdxVB@!iI97q zb4eq^fk)((KANm|uA5|;_5H*!l(ann_C^65=*YoPR1lBhb#3sq5hjgWLM(?sDF>4P zFA^E{LI4bfK!}&r71i!^AU9SlW8;@XykeCm;cPbo_qWuKdNc$Zymd;RRy2`9Bq@&v)~X=;F*u4RuLPC!lqy#BMj(8X0f)p;g1c<0pbu_`;WrGs z@Zk5N_!p2Veg?rEhMXmSQ*3;=V0_o6K^+AsK*M8=|BL~tdjxY$14u8=V&*vv@cP$O zk%3A7Y~rFA#ZshIK!m;rRd^txsS5IeV&;Pk?4H_5xZei&9U`6(h&wU(9SlexW{ueE z5S#KCZ5q9o)b3B6GrmVr8-mk{SX7+}avB1SZLYjkCVoD1@gmGwrcY!xa3(h+L@pXDt^mj`<4f8= zKt0?)j*Xnepbdit3~DgoF!&Azr!nZp0PjPpj^vGQ~(>L3gVk*~FP3(StX~zpQ z0|`%aih1GZ-AC`&rn=82n5sn0-V}585xXbF>`9k%DTV`2%Rf4mF7c%p-&aL;%TsHm zWtPsh4x8n9dd@3mb$5FAp4B{$v(&AY zQ~M64_a9Do>|J#}OIx0$VHm6Mf?u?L0F4^AQO)~S?P}aXRkv%TuhoNIQGkqWQAlo>Z@T*HTYu00zd`F# z0o0tKR$QKCS6$Lom$21s7V0?Pq?gB`#*_89Ei@-o3pPB{CUPx8Tg&XijK!LLeH<|3 zY;SmS9l>PVQd`t=Za@RcjLt|d3$Qwbj59=@%$4(8S2VQC0_Lp4GvjEEToy2Y7cO(^ zmjzS{Pjlz|9-vnlACc}EcK0q8yoUjO%Q;zAV%PCV+PR`z7Met-~Aw(DbEJI z$A^db{~Z^828vO+S?{0$cgxN0ce|I1eaT`U+~YA>GRN{eQk9*X596O(Vw;TP`Cs=8 z9nGVE*5mBypnlX*+sm2%%);A3KGy3dZqZEplqu8Aa1+E2QS6=$-~Xk z!8Q^(*hX@R?kN5_z^&UPKf#LLjWe{RPKejV4V|#{o-OIxm$2<4+hsufOTZ=m6$bwW z0L_ER0gVT?V6fmIKduvY_+ z0{P|ksPf5^-nM(;qAH&{eqP(Ka0G6a-;+Nby5IF#Wn%A8vUW(7QbXzDa#h5YuQ9ZR zTeI3NEssl0mTq-eKxoJVzbU})9bSU}gRzT)K+{!!3MJk{s6mX3<44Az4ZsrNcWQ8@ zZ&-**s8i&D!hkXuzGRxjPgjXzD%t=}v}54F0Jo!vJ5J2U0C$||!T{X=a63k=82}py zkb*)fk?-=w-$#fd4A6xtwqigyqZ9u3fKU5uSS-QpQVh_dA_lowfw4*q@Jv}D@Y??> z5UVkpC@*AX@UT=>W9l)6d|GiJexBT3R&OH~kOp7H%hjZNO$bG>2DDK(W94laY{y^+ z23`zWFxUx!Vg@AQE=&?yA!Kq0lSvFd#{lgB@hAq!HdPwv#F#-BitV7P&K(y277Bni zDCuhm;LZw7|4*s`M6}B@A_d!6uskbsnVZOWj~`z zzc$&h5P~l;__}Ca@~a|%{TbEvbF&)&Emi=uSOL&tg%V4{BerOUnHf$|MQc_Q-37Wp zW!?NZUevi~S#Cd?Y(JW)JDRNMnQ_j(n4)^p4cpUE^&OBQZhWERgaw;oEu z?~cO>=J1zhQ==(CdFDcEl!-PycJx{4r|J1qk0}y)JiwOG-E*`_ to - build a tree. - - Note that `HTML5TreeBuilder` does not support some common HTML - `TreeBuilder` features. Some of these features could theoretically - be implemented, but at the very least it's quite difficult, - because html5lib moves the parse tree around as it's being built. - - Specifically: - - * This `TreeBuilder` doesn't use different subclasses of - `NavigableString` (e.g. `Script`) based on the name of the tag - in which the string was found. - * You can't use a `SoupStrainer` to parse only part of a document. - """ - - NAME: str = "html5lib" - - features: Sequence[str] = [NAME, PERMISSIVE, HTML_5, HTML] - - #: html5lib can tell us which line number and position in the - #: original file is the source of an element. - TRACKS_LINE_NUMBERS: bool = True - - underlying_builder: "TreeBuilderForHtml5lib" #: :meta private: - user_specified_encoding: Optional[_Encoding] - - def prepare_markup( - self, - markup: _RawMarkup, - user_specified_encoding: Optional[_Encoding] = None, - document_declared_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - ) -> Iterable[Tuple[_RawMarkup, Optional[_Encoding], Optional[_Encoding], bool]]: - # Store the user-specified encoding for use later on. - self.user_specified_encoding = user_specified_encoding - - # document_declared_encoding and exclude_encodings aren't used - # ATM because the html5lib TreeBuilder doesn't use - # UnicodeDammit. - for variable, name in ( - (document_declared_encoding, "document_declared_encoding"), - (exclude_encodings, "exclude_encodings"), - ): - if variable: - warnings.warn( - f"You provided a value for {name}, but the html5lib tree builder doesn't support {name}.", - stacklevel=3, - ) - - # html5lib only parses HTML, so if it's given XML that's worth - # noting. - DetectsXMLParsedAsHTML.warn_if_markup_looks_like_xml(markup, stacklevel=3) - - yield (markup, None, None, False) - - # These methods are defined by Beautiful Soup. - def feed(self, markup: _RawMarkup) -> None: - """Run some incoming markup through some parsing process, - populating the `BeautifulSoup` object in `HTML5TreeBuilder.soup`. - """ - if self.soup is not None and self.soup.parse_only is not None: - warnings.warn( - "You provided a value for parse_only, but the html5lib tree builder doesn't support parse_only. The entire document will be parsed.", - stacklevel=4, - ) - - # self.underlying_builder is probably None now, but it'll be set - # when html5lib calls self.create_treebuilder(). - parser = html5lib.HTMLParser(tree=self.create_treebuilder) - assert self.underlying_builder is not None - self.underlying_builder.parser = parser - extra_kwargs = dict() - if not isinstance(markup, str): - # kwargs, specifically override_encoding, will eventually - # be passed in to html5lib's - # HTMLBinaryInputStream.__init__. - extra_kwargs["override_encoding"] = self.user_specified_encoding - - doc = parser.parse(markup, **extra_kwargs) - - # Set the character encoding detected by the tokenizer. - if isinstance(markup, str): - # We need to special-case this because html5lib sets - # charEncoding to UTF-8 if it gets Unicode input. - doc.original_encoding = None - else: - original_encoding = parser.tokenizer.stream.charEncoding[0] - # The encoding is an html5lib Encoding object. We want to - # use a string for compatibility with other tree builders. - original_encoding = original_encoding.name - doc.original_encoding = original_encoding - self.underlying_builder.parser = None - - def create_treebuilder( - self, namespaceHTMLElements: bool - ) -> "TreeBuilderForHtml5lib": - """Called by html5lib to instantiate the kind of class it - calls a 'TreeBuilder'. - - :param namespaceHTMLElements: Whether or not to namespace HTML elements. - - :meta private: - """ - self.underlying_builder = TreeBuilderForHtml5lib( - namespaceHTMLElements, self.soup, store_line_numbers=self.store_line_numbers - ) - return self.underlying_builder - - def test_fragment_to_document(self, fragment: str) -> str: - """See `TreeBuilder`.""" - return "%s" % fragment - - -class TreeBuilderForHtml5lib(treebuilder_base.TreeBuilder): - soup: "BeautifulSoup" #: :meta private: - parser: Optional[html5lib.HTMLParser] #: :meta private: - - def __init__( - self, - namespaceHTMLElements: bool, - soup: Optional["BeautifulSoup"] = None, - store_line_numbers: bool = True, - **kwargs: Any, - ): - if soup: - self.soup = soup - else: - warnings.warn( - "The optionality of the 'soup' argument to the TreeBuilderForHtml5lib constructor is deprecated as of Beautiful Soup 4.13.0: 'soup' is now required. If you can't pass in a BeautifulSoup object here, or you get this warning and it seems mysterious to you, please contact the Beautiful Soup developer team for possible un-deprecation.", - DeprecationWarning, - stacklevel=2, - ) - from bs4 import BeautifulSoup - - # TODO: Why is the parser 'html.parser' here? Using - # html5lib doesn't cause an infinite loop and is more - # accurate. Best to get rid of this entire section, I think. - self.soup = BeautifulSoup( - "", "html.parser", store_line_numbers=store_line_numbers, **kwargs - ) - # TODO: What are **kwargs exactly? Should they be passed in - # here in addition to/instead of being passed to the BeautifulSoup - # constructor? - super(TreeBuilderForHtml5lib, self).__init__(namespaceHTMLElements) - - # This will be set later to a real html5lib HTMLParser object, - # which we can use to track the current line number. - self.parser = None - self.store_line_numbers = store_line_numbers - - def documentClass(self) -> "Element": - self.soup.reset() - return Element(self.soup, self.soup, None) - - def insertDoctype(self, token: Dict[str, Any]) -> None: - name: str = cast(str, token["name"]) - publicId: Optional[str] = cast(Optional[str], token["publicId"]) - systemId: Optional[str] = cast(Optional[str], token["systemId"]) - - doctype = Doctype.for_name_and_ids(name, publicId, systemId) - self.soup.object_was_parsed(doctype) - - def elementClass(self, name: str, namespace: str) -> "Element": - sourceline: Optional[int] = None - sourcepos: Optional[int] = None - if self.parser is not None and self.store_line_numbers: - # This represents the point immediately after the end of the - # tag. We don't know when the tag started, but we do know - # where it ended -- the character just before this one. - sourceline, sourcepos = self.parser.tokenizer.stream.position() - assert sourcepos is not None - sourcepos = sourcepos - 1 - tag = self.soup.new_tag( - name, namespace, sourceline=sourceline, sourcepos=sourcepos - ) - - return Element(tag, self.soup, namespace) - - def commentClass(self, data: str) -> "TextNode": - return TextNode(Comment(data), self.soup) - - def fragmentClass(self) -> "Element": - """This is only used by html5lib HTMLParser.parseFragment(), - which is never used by Beautiful Soup, only by the html5lib - unit tests. Since we don't currently hook into those tests, - the implementation is left blank. - """ - raise NotImplementedError() - - def getFragment(self) -> "Element": - """This is only used by the html5lib unit tests. Since we - don't currently hook into those tests, the implementation is - left blank. - """ - raise NotImplementedError() - - def appendChild(self, node: "Element") -> None: - # TODO: This code is not covered by the BS4 tests, and - # apparently not triggered by the html5lib test suite either. - # But it doesn't seem test-specific and there are calls to it - # (or a method with the same name) all over html5lib, so I'm - # leaving the implementation in place rather than replacing it - # with NotImplementedError() - self.soup.append(node.element) - - def getDocument(self) -> "BeautifulSoup": - return self.soup - - def testSerializer(self, element: "Element") -> str: - """This is only used by the html5lib unit tests. Since we - don't currently hook into those tests, the implementation is - left blank. - """ - raise NotImplementedError() - - -class AttrList(object): - """Represents a Tag's attributes in a way compatible with html5lib.""" - - element: Tag - attrs: _AttributeValues - - def __init__(self, element: Tag): - self.element = element - self.attrs = dict(self.element.attrs) - - def __iter__(self) -> Iterable[Tuple[str, _AttributeValue]]: - return list(self.attrs.items()).__iter__() - - def __setitem__(self, name: str, value: _AttributeValue) -> None: - # If this attribute is a multi-valued attribute for this element, - # turn its value into a list. - list_attr = self.element.cdata_list_attributes or {} - if name in list_attr.get("*", []) or ( - self.element.name in list_attr - and name in list_attr.get(self.element.name, []) - ): - # A node that is being cloned may have already undergone - # this procedure. Check for this and skip it. - if not isinstance(value, list): - assert isinstance(value, str) - value = self.element.attribute_value_list_class( - nonwhitespace_re.findall(value) - ) - self.element[name] = value - - def items(self) -> Iterable[Tuple[str, _AttributeValue]]: - return list(self.attrs.items()) - - def keys(self) -> Iterable[str]: - return list(self.attrs.keys()) - - def __len__(self) -> int: - return len(self.attrs) - - def __getitem__(self, name: str) -> _AttributeValue: - return self.attrs[name] - - def __contains__(self, name: str) -> bool: - return name in list(self.attrs.keys()) - - -class BeautifulSoupNode(treebuilder_base.Node): - element: PageElement - soup: "BeautifulSoup" - namespace: Optional[_NamespaceURL] - - @property - def nodeType(self) -> int: - """Return the html5lib constant corresponding to the type of - the underlying DOM object. - - NOTE: This property is only accessed by the html5lib test - suite, not by Beautiful Soup proper. - """ - raise NotImplementedError() - - # TODO-TYPING: typeshed stubs are incorrect about this; - # cloneNode returns a new Node, not None. - def cloneNode(self) -> treebuilder_base.Node: - raise NotImplementedError() - - -class Element(BeautifulSoupNode): - element: Tag - namespace: Optional[_NamespaceURL] - - def __init__( - self, element: Tag, soup: "BeautifulSoup", namespace: Optional[_NamespaceURL] - ): - treebuilder_base.Node.__init__(self, element.name) - self.element = element - self.soup = soup - self.namespace = namespace - - def appendChild(self, node: "BeautifulSoupNode") -> None: - string_child: Optional[NavigableString] = None - child: PageElement - if type(node.element) is NavigableString: - string_child = child = node.element - else: - child = node.element - node.parent = self - - if ( - child is not None - and child.parent is not None - and not isinstance(child, str) - ): - node.element.extract() - - if ( - string_child is not None - and self.element.contents - and type(self.element.contents[-1]) is NavigableString - ): - # We are appending a string onto another string. - # TODO This has O(n^2) performance, for input like - # "aaa..." - old_element = self.element.contents[-1] - new_element = self.soup.new_string(old_element + string_child) - old_element.replace_with(new_element) - self.soup._most_recent_element = new_element - else: - if isinstance(node, str): - # Create a brand new NavigableString from this string. - child = self.soup.new_string(node) - - # Tell Beautiful Soup to act as if it parsed this element - # immediately after the parent's last descendant. (Or - # immediately after the parent, if it has no children.) - if self.element.contents: - most_recent_element = self.element._last_descendant(False) - elif self.element.next_element is not None: - # Something from further ahead in the parse tree is - # being inserted into this earlier element. This is - # very annoying because it means an expensive search - # for the last element in the tree. - most_recent_element = self.soup._last_descendant() - else: - most_recent_element = self.element - - self.soup.object_was_parsed( - child, parent=self.element, most_recent_element=most_recent_element - ) - - def getAttributes(self) -> AttrList: - if isinstance(self.element, Comment): - return {} - return AttrList(self.element) - - # An HTML5lib attribute name may either be a single string, - # or a tuple (namespace, name). - _Html5libAttributeName: TypeAlias = Union[str, Tuple[str, str]] - # Now we can define the type this method accepts as a dictionary - # mapping those attribute names to single string values. - _Html5libAttributes: TypeAlias = Dict[_Html5libAttributeName, str] - - def setAttributes(self, attributes: Optional[_Html5libAttributes]) -> None: - if attributes is not None and len(attributes) > 0: - # Replace any namespaced attributes with - # NamespacedAttribute objects. - for name, value in list(attributes.items()): - if isinstance(name, tuple): - new_name = NamespacedAttribute(*name) - del attributes[name] - attributes[new_name] = value - - # We can now cast attributes to the type of Dict - # used by Beautiful Soup. - normalized_attributes = cast(_AttributeValues, attributes) - - # Values for tags like 'class' came in as single strings; - # replace them with lists of strings as appropriate. - self.soup.builder._replace_cdata_list_attribute_values( - self.name, normalized_attributes - ) - - # Then set the attributes on the Tag associated with this - # BeautifulSoupNode. - for name, value_or_values in list(normalized_attributes.items()): - self.element[name] = value_or_values - - # The attributes may contain variables that need substitution. - # Call set_up_substitutions manually. - # - # The Tag constructor called this method when the Tag was created, - # but we just set/changed the attributes, so call it again. - self.soup.builder.set_up_substitutions(self.element) - - attributes = property(getAttributes, setAttributes) - - def insertText( - self, data: str, insertBefore: Optional["BeautifulSoupNode"] = None - ) -> None: - text = TextNode(self.soup.new_string(data), self.soup) - if insertBefore: - self.insertBefore(text, insertBefore) - else: - self.appendChild(text) - - def insertBefore( - self, node: "BeautifulSoupNode", refNode: "BeautifulSoupNode" - ) -> None: - index = self.element.index(refNode.element) - if ( - type(node.element) is NavigableString - and self.element.contents - and type(self.element.contents[index - 1]) is NavigableString - ): - # (See comments in appendChild) - old_node = self.element.contents[index - 1] - assert type(old_node) is NavigableString - new_str = self.soup.new_string(old_node + node.element) - old_node.replace_with(new_str) - else: - self.element.insert(index, node.element) - node.parent = self - - def removeChild(self, node: "Element") -> None: - node.element.extract() - - def reparentChildren(self, new_parent: "Element") -> None: - """Move all of this tag's children into another tag.""" - # print("MOVE", self.element.contents) - # print("FROM", self.element) - # print("TO", new_parent.element) - - element = self.element - new_parent_element = new_parent.element - # Determine what this tag's next_element will be once all the children - # are removed. - final_next_element = element.next_sibling - - new_parents_last_descendant = new_parent_element._last_descendant(False, False) - if len(new_parent_element.contents) > 0: - # The new parent already contains children. We will be - # appending this tag's children to the end. - - # We can make this assertion since we know new_parent has - # children. - assert new_parents_last_descendant is not None - new_parents_last_child = new_parent_element.contents[-1] - new_parents_last_descendant_next_element = ( - new_parents_last_descendant.next_element - ) - else: - # The new parent contains no children. - new_parents_last_child = None - new_parents_last_descendant_next_element = new_parent_element.next_element - - to_append = element.contents - if len(to_append) > 0: - # Set the first child's previous_element and previous_sibling - # to elements within the new parent - first_child = to_append[0] - if new_parents_last_descendant is not None: - first_child.previous_element = new_parents_last_descendant - else: - first_child.previous_element = new_parent_element - first_child.previous_sibling = new_parents_last_child - if new_parents_last_descendant is not None: - new_parents_last_descendant.next_element = first_child - else: - new_parent_element.next_element = first_child - if new_parents_last_child is not None: - new_parents_last_child.next_sibling = first_child - - # Find the very last element being moved. It is now the - # parent's last descendant. It has no .next_sibling and - # its .next_element is whatever the previous last - # descendant had. - last_childs_last_descendant = to_append[-1]._last_descendant( - is_initialized=False, accept_self=True - ) - - # Since we passed accept_self=True into _last_descendant, - # there's no possibility that the result is None. - assert last_childs_last_descendant is not None - last_childs_last_descendant.next_element = ( - new_parents_last_descendant_next_element - ) - if new_parents_last_descendant_next_element is not None: - # TODO-COVERAGE: This code has no test coverage and - # I'm not sure how to get html5lib to go through this - # path, but it's just the other side of the previous - # line. - new_parents_last_descendant_next_element.previous_element = ( - last_childs_last_descendant - ) - last_childs_last_descendant.next_sibling = None - - for child in to_append: - child.parent = new_parent_element - new_parent_element.contents.append(child) - - # Now that this element has no children, change its .next_element. - element.contents = [] - element.next_element = final_next_element - - # print("DONE WITH MOVE") - # print("FROM", self.element) - # print("TO", new_parent_element) - - # TODO-TYPING: typeshed stubs are incorrect about this; - # hasContent returns a boolean, not None. - def hasContent(self) -> bool: - return len(self.element.contents) > 0 - - # TODO-TYPING: typeshed stubs are incorrect about this; - # cloneNode returns a new Node, not None. - def cloneNode(self) -> treebuilder_base.Node: - tag = self.soup.new_tag(self.element.name, self.namespace) - node = Element(tag, self.soup, self.namespace) - for key, value in self.attributes: - node.attributes[key] = value - return node - - def getNameTuple(self) -> Tuple[Optional[_NamespaceURL], str]: - if self.namespace is None: - return namespaces["html"], self.name - else: - return self.namespace, self.name - - nameTuple = property(getNameTuple) - - -class TextNode(BeautifulSoupNode): - element: NavigableString - - def __init__(self, element: NavigableString, soup: "BeautifulSoup"): - treebuilder_base.Node.__init__(self, None) - self.element = element - self.soup = soup diff --git a/.venv/Lib/site-packages/bs4/builder/_htmlparser.py b/.venv/Lib/site-packages/bs4/builder/_htmlparser.py deleted file mode 100644 index 417f7dc..0000000 --- a/.venv/Lib/site-packages/bs4/builder/_htmlparser.py +++ /dev/null @@ -1,474 +0,0 @@ -# encoding: utf-8 -"""Use the HTMLParser library to parse HTML files that aren't too bad.""" -from __future__ import annotations - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -__all__ = [ - "HTMLParserTreeBuilder", -] - -from html.parser import HTMLParser - -from typing import ( - Any, - Callable, - cast, - Dict, - Iterable, - List, - Optional, - TYPE_CHECKING, - Tuple, - Type, - Union, -) - -from bs4.element import ( - AttributeDict, - CData, - Comment, - Declaration, - Doctype, - ProcessingInstruction, -) -from bs4.dammit import EntitySubstitution, UnicodeDammit - -from bs4.builder import ( - DetectsXMLParsedAsHTML, - HTML, - HTMLTreeBuilder, - STRICT, -) - -from bs4.exceptions import ParserRejectedMarkup - -if TYPE_CHECKING: - from bs4 import BeautifulSoup - from bs4.element import NavigableString - from bs4._typing import ( - _Encoding, - _Encodings, - _RawMarkup, - ) - -HTMLPARSER = "html.parser" - -_DuplicateAttributeHandler = Callable[[Dict[str, str], str, str], None] - - -class BeautifulSoupHTMLParser(HTMLParser, DetectsXMLParsedAsHTML): - #: Constant to handle duplicate attributes by ignoring later values - #: and keeping the earlier ones. - REPLACE: str = "replace" - - #: Constant to handle duplicate attributes by replacing earlier values - #: with later ones. - IGNORE: str = "ignore" - - """A subclass of the Python standard library's HTMLParser class, which - listens for HTMLParser events and translates them into calls - to Beautiful Soup's tree construction API. - - :param on_duplicate_attribute: A strategy for what to do if a - tag includes the same attribute more than once. Accepted - values are: REPLACE (replace earlier values with later - ones, the default), IGNORE (keep the earliest value - encountered), or a callable. A callable must take three - arguments: the dictionary of attributes already processed, - the name of the duplicate attribute, and the most recent value - encountered. - """ - - def __init__( - self, - soup: BeautifulSoup, - *args: Any, - on_duplicate_attribute: Union[str, _DuplicateAttributeHandler] = REPLACE, - **kwargs: Any, - ): - self.soup = soup - self.on_duplicate_attribute = on_duplicate_attribute - self.attribute_dict_class = soup.builder.attribute_dict_class - HTMLParser.__init__(self, *args, **kwargs) - - # Keep a list of empty-element tags that were encountered - # without an explicit closing tag. If we encounter a closing tag - # of this type, we'll associate it with one of those entries. - # - # This isn't a stack because we don't care about the - # order. It's a list of closing tags we've already handled and - # will ignore, assuming they ever show up. - self.already_closed_empty_element = [] - - self._initialize_xml_detector() - - on_duplicate_attribute: Union[str, _DuplicateAttributeHandler] - already_closed_empty_element: List[str] - soup: BeautifulSoup - - def error(self, message: str) -> None: - # NOTE: This method is required so long as Python 3.9 is - # supported. The corresponding code is removed from HTMLParser - # in 3.5, but not removed from ParserBase until 3.10. - # https://github.com/python/cpython/issues/76025 - # - # The original implementation turned the error into a warning, - # but in every case I discovered, this made HTMLParser - # immediately crash with an error message that was less - # helpful than the warning. The new implementation makes it - # more clear that html.parser just can't parse this - # markup. The 3.10 implementation does the same, though it - # raises AssertionError rather than calling a method. (We - # catch this error and wrap it in a ParserRejectedMarkup.) - raise ParserRejectedMarkup(message) - - def handle_startendtag( - self, name: str, attrs: List[Tuple[str, Optional[str]]] - ) -> None: - """Handle an incoming empty-element tag. - - html.parser only calls this method when the markup looks like - . - """ - # `handle_empty_element` tells handle_starttag not to close the tag - # just because its name matches a known empty-element tag. We - # know that this is an empty-element tag, and we want to call - # handle_endtag ourselves. - self.handle_starttag(name, attrs, handle_empty_element=False) - self.handle_endtag(name) - - def handle_starttag( - self, - name: str, - attrs: List[Tuple[str, Optional[str]]], - handle_empty_element: bool = True, - ) -> None: - """Handle an opening tag, e.g. '' - - :param handle_empty_element: True if this tag is known to be - an empty-element tag (i.e. there is not expected to be any - closing tag). - """ - # TODO: handle namespaces here? - attr_dict: AttributeDict = self.attribute_dict_class() - for key, value in attrs: - # Change None attribute values to the empty string - # for consistency with the other tree builders. - if value is None: - value = "" - if key in attr_dict: - # A single attribute shows up multiple times in this - # tag. How to handle it depends on the - # on_duplicate_attribute setting. - on_dupe = self.on_duplicate_attribute - if on_dupe == self.IGNORE: - pass - elif on_dupe in (None, self.REPLACE): - attr_dict[key] = value - else: - on_dupe = cast(_DuplicateAttributeHandler, on_dupe) - on_dupe(attr_dict, key, value) - else: - attr_dict[key] = value - # print("START", name) - sourceline: Optional[int] - sourcepos: Optional[int] - if self.soup.builder.store_line_numbers: - sourceline, sourcepos = self.getpos() - else: - sourceline = sourcepos = None - tag = self.soup.handle_starttag( - name, None, None, attr_dict, sourceline=sourceline, sourcepos=sourcepos - ) - if tag and tag.is_empty_element and handle_empty_element: - # Unlike other parsers, html.parser doesn't send separate end tag - # events for empty-element tags. (It's handled in - # handle_startendtag, but only if the original markup looked like - # .) - # - # So we need to call handle_endtag() ourselves. Since we - # know the start event is identical to the end event, we - # don't want handle_endtag() to cross off any previous end - # events for tags of this name. - self.handle_endtag(name, check_already_closed=False) - - # But we might encounter an explicit closing tag for this tag - # later on. If so, we want to ignore it. - self.already_closed_empty_element.append(name) - - if self._root_tag_name is None: - self._root_tag_encountered(name) - - def handle_endtag(self, name: str, check_already_closed: bool = True) -> None: - """Handle a closing tag, e.g. '' - - :param name: A tag name. - :param check_already_closed: True if this tag is expected to - be the closing portion of an empty-element tag, - e.g. ''. - """ - # print("END", name) - if check_already_closed and name in self.already_closed_empty_element: - # This is a redundant end tag for an empty-element tag. - # We've already called handle_endtag() for it, so just - # check it off the list. - # print("ALREADY CLOSED", name) - self.already_closed_empty_element.remove(name) - else: - self.soup.handle_endtag(name) - - def handle_data(self, data: str) -> None: - """Handle some textual data that shows up between tags.""" - self.soup.handle_data(data) - - def handle_charref(self, name: str) -> None: - """Handle a numeric character reference by converting it to the - corresponding Unicode character and treating it as textual - data. - - :param name: Character number, possibly in hexadecimal. - """ - # TODO: This was originally a workaround for a bug in - # HTMLParser. (http://bugs.python.org/issue13633) The bug has - # been fixed, but removing this code still makes some - # Beautiful Soup tests fail. This needs investigation. - if name.startswith("x"): - real_name = int(name.lstrip("x"), 16) - elif name.startswith("X"): - real_name = int(name.lstrip("X"), 16) - else: - real_name = int(name) - - data = None - if real_name < 256: - # HTML numeric entities are supposed to reference Unicode - # code points, but sometimes they reference code points in - # some other encoding (ahem, Windows-1252). E.g. “ - # instead of É for LEFT DOUBLE QUOTATION MARK. This - # code tries to detect this situation and compensate. - for encoding in (self.soup.original_encoding, "windows-1252"): - if not encoding: - continue - try: - data = bytearray([real_name]).decode(encoding) - except UnicodeDecodeError: - pass - if not data: - try: - data = chr(real_name) - except (ValueError, OverflowError): - pass - data = data or "\N{REPLACEMENT CHARACTER}" - self.handle_data(data) - - def handle_entityref(self, name: str) -> None: - """Handle a named entity reference by converting it to the - corresponding Unicode character(s) and treating it as textual - data. - - :param name: Name of the entity reference. - """ - character = EntitySubstitution.HTML_ENTITY_TO_CHARACTER.get(name) - if character is not None: - data = character - else: - # If this were XML, it would be ambiguous whether "&foo" - # was an character entity reference with a missing - # semicolon or the literal string "&foo". Since this is - # HTML, we have a complete list of all character entity references, - # and this one wasn't found, so assume it's the literal string "&foo". - data = "&%s" % name - self.handle_data(data) - - def handle_comment(self, data: str) -> None: - """Handle an HTML comment. - - :param data: The text of the comment. - """ - self.soup.endData() - self.soup.handle_data(data) - self.soup.endData(Comment) - - def handle_decl(self, data: str) -> None: - """Handle a DOCTYPE declaration. - - :param data: The text of the declaration. - """ - self.soup.endData() - data = data[len("DOCTYPE ") :] - self.soup.handle_data(data) - self.soup.endData(Doctype) - - def unknown_decl(self, data: str) -> None: - """Handle a declaration of unknown type -- probably a CDATA block. - - :param data: The text of the declaration. - """ - cls: Type[NavigableString] - if data.upper().startswith("CDATA["): - cls = CData - data = data[len("CDATA[") :] - else: - cls = Declaration - self.soup.endData() - self.soup.handle_data(data) - self.soup.endData(cls) - - def handle_pi(self, data: str) -> None: - """Handle a processing instruction. - - :param data: The text of the instruction. - """ - self.soup.endData() - self.soup.handle_data(data) - self._document_might_be_xml(data) - self.soup.endData(ProcessingInstruction) - - -class HTMLParserTreeBuilder(HTMLTreeBuilder): - """A Beautiful soup `bs4.builder.TreeBuilder` that uses the - :py:class:`html.parser.HTMLParser` parser, found in the Python - standard library. - - """ - - is_xml: bool = False - picklable: bool = True - NAME: str = HTMLPARSER - features: Iterable[str] = [NAME, HTML, STRICT] - parser_args: Tuple[Iterable[Any], Dict[str, Any]] - - #: The html.parser knows which line number and position in the - #: original file is the source of an element. - TRACKS_LINE_NUMBERS: bool = True - - def __init__( - self, - parser_args: Optional[Iterable[Any]] = None, - parser_kwargs: Optional[Dict[str, Any]] = None, - **kwargs: Any, - ): - """Constructor. - - :param parser_args: Positional arguments to pass into - the BeautifulSoupHTMLParser constructor, once it's - invoked. - :param parser_kwargs: Keyword arguments to pass into - the BeautifulSoupHTMLParser constructor, once it's - invoked. - :param kwargs: Keyword arguments for the superclass constructor. - """ - # Some keyword arguments will be pulled out of kwargs and placed - # into parser_kwargs. - extra_parser_kwargs = dict() - for arg in ("on_duplicate_attribute",): - if arg in kwargs: - value = kwargs.pop(arg) - extra_parser_kwargs[arg] = value - super(HTMLParserTreeBuilder, self).__init__(**kwargs) - parser_args = parser_args or [] - parser_kwargs = parser_kwargs or {} - parser_kwargs.update(extra_parser_kwargs) - parser_kwargs["convert_charrefs"] = False - self.parser_args = (parser_args, parser_kwargs) - - def prepare_markup( - self, - markup: _RawMarkup, - user_specified_encoding: Optional[_Encoding] = None, - document_declared_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - ) -> Iterable[Tuple[str, Optional[_Encoding], Optional[_Encoding], bool]]: - """Run any preliminary steps necessary to make incoming markup - acceptable to the parser. - - :param markup: Some markup -- probably a bytestring. - :param user_specified_encoding: The user asked to try this encoding. - :param document_declared_encoding: The markup itself claims to be - in this encoding. - :param exclude_encodings: The user asked _not_ to try any of - these encodings. - - :yield: A series of 4-tuples: (markup, encoding, declared encoding, - has undergone character replacement) - - Each 4-tuple represents a strategy for parsing the document. - This TreeBuilder uses Unicode, Dammit to convert the markup - into Unicode, so the ``markup`` element of the tuple will - always be a string. - """ - if isinstance(markup, str): - # Parse Unicode as-is. - yield (markup, None, None, False) - return - - # Ask UnicodeDammit to sniff the most likely encoding. - - known_definite_encodings: List[_Encoding] = [] - if user_specified_encoding: - # This was provided by the end-user; treat it as a known - # definite encoding per the algorithm laid out in the - # HTML5 spec. (See the EncodingDetector class for - # details.) - known_definite_encodings.append(user_specified_encoding) - - user_encodings: List[_Encoding] = [] - if document_declared_encoding: - # This was found in the document; treat it as a slightly - # lower-priority user encoding. - user_encodings.append(document_declared_encoding) - - dammit = UnicodeDammit( - markup, - known_definite_encodings=known_definite_encodings, - user_encodings=user_encodings, - is_html=True, - exclude_encodings=exclude_encodings, - ) - - if dammit.unicode_markup is None: - # In every case I've seen, Unicode, Dammit is able to - # convert the markup into Unicode, even if it needs to use - # REPLACEMENT CHARACTER. But there is a code path that - # could result in unicode_markup being None, and - # HTMLParser can only parse Unicode, so here we handle - # that code path. - raise ParserRejectedMarkup( - "Could not convert input to Unicode, and html.parser will not accept bytestrings." - ) - else: - yield ( - dammit.unicode_markup, - dammit.original_encoding, - dammit.declared_html_encoding, - dammit.contains_replacement_characters, - ) - - def feed(self, markup: _RawMarkup) -> None: - args, kwargs = self.parser_args - - # HTMLParser.feed will only handle str, but - # BeautifulSoup.markup is allowed to be _RawMarkup, because - # it's set by the yield value of - # TreeBuilder.prepare_markup. Fortunately, - # HTMLParserTreeBuilder.prepare_markup always yields a str - # (UnicodeDammit.unicode_markup). - assert isinstance(markup, str) - - # We know BeautifulSoup calls TreeBuilder.initialize_soup - # before calling feed(), so we can assume self.soup - # is set. - assert self.soup is not None - parser = BeautifulSoupHTMLParser(self.soup, *args, **kwargs) - - try: - parser.feed(markup) - parser.close() - except AssertionError as e: - # html.parser raises AssertionError in rare cases to - # indicate a fatal problem with the markup, especially - # when there's an error in the doctype declaration. - raise ParserRejectedMarkup(e) - parser.already_closed_empty_element = [] diff --git a/.venv/Lib/site-packages/bs4/builder/_lxml.py b/.venv/Lib/site-packages/bs4/builder/_lxml.py deleted file mode 100644 index 82a55a4..0000000 --- a/.venv/Lib/site-packages/bs4/builder/_lxml.py +++ /dev/null @@ -1,491 +0,0 @@ -# encoding: utf-8 -from __future__ import annotations - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -__all__ = [ - "LXMLTreeBuilderForXML", - "LXMLTreeBuilder", -] - - -from typing import ( - Any, - Dict, - Iterable, - List, - Optional, - Set, - Tuple, - Type, - TYPE_CHECKING, - Union, -) -from typing_extensions import TypeAlias - -from io import BytesIO -from io import StringIO -from lxml import etree -from bs4.element import ( - AttributeDict, - XMLAttributeDict, - Comment, - Doctype, - NamespacedAttribute, - ProcessingInstruction, - XMLProcessingInstruction, -) -from bs4.builder import ( - DetectsXMLParsedAsHTML, - FAST, - HTML, - HTMLTreeBuilder, - PERMISSIVE, - TreeBuilder, - XML, -) -from bs4.dammit import EncodingDetector -from bs4.exceptions import ParserRejectedMarkup - -if TYPE_CHECKING: - from bs4._typing import ( - _Encoding, - _Encodings, - _NamespacePrefix, - _NamespaceURL, - _NamespaceMapping, - _InvertedNamespaceMapping, - _RawMarkup, - ) - from bs4 import BeautifulSoup - -LXML: str = "lxml" - - -def _invert(d: dict[Any, Any]) -> dict[Any, Any]: - "Invert a dictionary." - return dict((v, k) for k, v in list(d.items())) - - -_LXMLParser: TypeAlias = Union[etree.XMLParser, etree.HTMLParser] -_ParserOrParserClass: TypeAlias = Union[ - _LXMLParser, Type[etree.XMLParser], Type[etree.HTMLParser] -] - - -class LXMLTreeBuilderForXML(TreeBuilder): - DEFAULT_PARSER_CLASS: Type[etree.XMLParser] = etree.XMLParser - - is_xml: bool = True - - processing_instruction_class: Type[ProcessingInstruction] - - NAME: str = "lxml-xml" - ALTERNATE_NAMES: Iterable[str] = ["xml"] - - # Well, it's permissive by XML parser standards. - features: Iterable[str] = [NAME, LXML, XML, FAST, PERMISSIVE] - - CHUNK_SIZE: int = 512 - - # This namespace mapping is specified in the XML Namespace - # standard. - DEFAULT_NSMAPS: _NamespaceMapping = dict(xml="http://www.w3.org/XML/1998/namespace") - - DEFAULT_NSMAPS_INVERTED: _InvertedNamespaceMapping = _invert(DEFAULT_NSMAPS) - - nsmaps: List[Optional[_InvertedNamespaceMapping]] - empty_element_tags: Set[str] - parser: Any - _default_parser: Optional[etree.XMLParser] - - # NOTE: If we parsed Element objects and looked at .sourceline, - # we'd be able to see the line numbers from the original document. - # But instead we build an XMLParser or HTMLParser object to serve - # as the target of parse messages, and those messages don't include - # line numbers. - # See: https://bugs.launchpad.net/lxml/+bug/1846906 - - def initialize_soup(self, soup: BeautifulSoup) -> None: - """Let the BeautifulSoup object know about the standard namespace - mapping. - - :param soup: A `BeautifulSoup`. - """ - # Beyond this point, self.soup is set, so we can assume (and - # assert) it's not None whenever necessary. - super(LXMLTreeBuilderForXML, self).initialize_soup(soup) - self._register_namespaces(self.DEFAULT_NSMAPS) - - def _register_namespaces(self, mapping: Dict[str, str]) -> None: - """Let the BeautifulSoup object know about namespaces encountered - while parsing the document. - - This might be useful later on when creating CSS selectors. - - This will track (almost) all namespaces, even ones that were - only in scope for part of the document. If two namespaces have - the same prefix, only the first one encountered will be - tracked. Un-prefixed namespaces are not tracked. - - :param mapping: A dictionary mapping namespace prefixes to URIs. - """ - assert self.soup is not None - for key, value in list(mapping.items()): - # This is 'if key' and not 'if key is not None' because we - # don't track un-prefixed namespaces. Soupselect will - # treat an un-prefixed namespace as the default, which - # causes confusion in some cases. - if key and key not in self.soup._namespaces: - # Let the BeautifulSoup object know about a new namespace. - # If there are multiple namespaces defined with the same - # prefix, the first one in the document takes precedence. - self.soup._namespaces[key] = value - - def default_parser(self, encoding: Optional[_Encoding]) -> _ParserOrParserClass: - """Find the default parser for the given encoding. - - :return: Either a parser object or a class, which - will be instantiated with default arguments. - """ - if self._default_parser is not None: - return self._default_parser - return self.DEFAULT_PARSER_CLASS(target=self, recover=True, encoding=encoding) - - def parser_for(self, encoding: Optional[_Encoding]) -> _LXMLParser: - """Instantiate an appropriate parser for the given encoding. - - :param encoding: A string. - :return: A parser object such as an `etree.XMLParser`. - """ - # Use the default parser. - parser = self.default_parser(encoding) - - if callable(parser): - # Instantiate the parser with default arguments - parser = parser(target=self, recover=True, encoding=encoding) - return parser - - def __init__( - self, - parser: Optional[etree.XMLParser] = None, - empty_element_tags: Optional[Set[str]] = None, - **kwargs: Any, - ): - # TODO: Issue a warning if parser is present but not a - # callable, since that means there's no way to create new - # parsers for different encodings. - self._default_parser = parser - self.soup = None - self.nsmaps = [self.DEFAULT_NSMAPS_INVERTED] - self.active_namespace_prefixes = [dict(self.DEFAULT_NSMAPS)] - if self.is_xml: - self.processing_instruction_class = XMLProcessingInstruction - else: - self.processing_instruction_class = ProcessingInstruction - - if "attribute_dict_class" not in kwargs: - kwargs["attribute_dict_class"] = XMLAttributeDict - super(LXMLTreeBuilderForXML, self).__init__(**kwargs) - - def _getNsTag(self, tag: str) -> Tuple[Optional[str], str]: - # Split the namespace URL out of a fully-qualified lxml tag - # name. Copied from lxml's src/lxml/sax.py. - if tag[0] == "{": - namespace, name = tag[1:].split("}", 1) - return (namespace, name) - else: - return (None, tag) - - def prepare_markup( - self, - markup: _RawMarkup, - user_specified_encoding: Optional[_Encoding] = None, - document_declared_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - ) -> Iterable[ - Tuple[Union[str, bytes], Optional[_Encoding], Optional[_Encoding], bool] - ]: - """Run any preliminary steps necessary to make incoming markup - acceptable to the parser. - - lxml really wants to get a bytestring and convert it to - Unicode itself. So instead of using UnicodeDammit to convert - the bytestring to Unicode using different encodings, this - implementation uses EncodingDetector to iterate over the - encodings, and tell lxml to try to parse the document as each - one in turn. - - :param markup: Some markup -- hopefully a bytestring. - :param user_specified_encoding: The user asked to try this encoding. - :param document_declared_encoding: The markup itself claims to be - in this encoding. - :param exclude_encodings: The user asked _not_ to try any of - these encodings. - - :yield: A series of 4-tuples: (markup, encoding, declared encoding, - has undergone character replacement) - - Each 4-tuple represents a strategy for converting the - document to Unicode and parsing it. Each strategy will be tried - in turn. - """ - if not self.is_xml: - # We're in HTML mode, so if we're given XML, that's worth - # noting. - DetectsXMLParsedAsHTML.warn_if_markup_looks_like_xml(markup, stacklevel=3) - - if isinstance(markup, str): - # We were given Unicode. Maybe lxml can parse Unicode on - # this system? - - # TODO: This is a workaround for - # https://bugs.launchpad.net/lxml/+bug/1948551. - # We can remove it once the upstream issue is fixed. - if len(markup) > 0 and markup[0] == "\N{BYTE ORDER MARK}": - markup = markup[1:] - yield markup, None, document_declared_encoding, False - - if isinstance(markup, str): - # No, apparently not. Convert the Unicode to UTF-8 and - # tell lxml to parse it as UTF-8. - yield (markup.encode("utf8"), "utf8", document_declared_encoding, False) - - # Since the document was Unicode in the first place, there - # is no need to try any more strategies; we know this will - # work. - return - - known_definite_encodings: List[_Encoding] = [] - if user_specified_encoding: - # This was provided by the end-user; treat it as a known - # definite encoding per the algorithm laid out in the - # HTML5 spec. (See the EncodingDetector class for - # details.) - known_definite_encodings.append(user_specified_encoding) - - user_encodings: List[_Encoding] = [] - if document_declared_encoding: - # This was found in the document; treat it as a slightly - # lower-priority user encoding. - user_encodings.append(document_declared_encoding) - - detector = EncodingDetector( - markup, - known_definite_encodings=known_definite_encodings, - user_encodings=user_encodings, - is_html=not self.is_xml, - exclude_encodings=exclude_encodings, - ) - for encoding in detector.encodings: - yield (detector.markup, encoding, document_declared_encoding, False) - - def feed(self, markup: _RawMarkup) -> None: - io: Union[BytesIO, StringIO] - if isinstance(markup, bytes): - io = BytesIO(markup) - elif isinstance(markup, str): - io = StringIO(markup) - - # initialize_soup is called before feed, so we know this - # is not None. - assert self.soup is not None - - # Call feed() at least once, even if the markup is empty, - # or the parser won't be initialized. - data = io.read(self.CHUNK_SIZE) - try: - self.parser = self.parser_for(self.soup.original_encoding) - self.parser.feed(data) - while len(data) != 0: - # Now call feed() on the rest of the data, chunk by chunk. - data = io.read(self.CHUNK_SIZE) - if len(data) != 0: - self.parser.feed(data) - self.parser.close() - except (UnicodeDecodeError, LookupError, etree.ParserError) as e: - raise ParserRejectedMarkup(e) - - def close(self) -> None: - self.nsmaps = [self.DEFAULT_NSMAPS_INVERTED] - - def start( - self, - tag: str | bytes, - attrs: Dict[str | bytes, str | bytes], - nsmap: _NamespaceMapping = {}, - ) -> None: - # This is called by lxml code as a result of calling - # BeautifulSoup.feed(), and we know self.soup is set by the time feed() - # is called. - assert self.soup is not None - assert isinstance(tag, str) - - # We need to recreate the attribute dict for three - # reasons. First, for type checking, so we can assert there - # are no bytestrings in the keys or values. Second, because we - # need a mutable dict--lxml might send us an immutable - # dictproxy. Third, so we can handle namespaced attribute - # names by converting the keys to NamespacedAttributes. - new_attrs: Dict[Union[str, NamespacedAttribute], str] = ( - self.attribute_dict_class() - ) - for k, v in attrs.items(): - assert isinstance(k, str) - assert isinstance(v, str) - new_attrs[k] = v - - nsprefix: Optional[_NamespacePrefix] = None - namespace: Optional[_NamespaceURL] = None - # Invert each namespace map as it comes in. - if len(nsmap) == 0 and len(self.nsmaps) > 1: - # There are no new namespaces for this tag, but - # non-default namespaces are in play, so we need a - # separate tag stack to know when they end. - self.nsmaps.append(None) - elif len(nsmap) > 0: - # A new namespace mapping has come into play. - - # First, Let the BeautifulSoup object know about it. - self._register_namespaces(nsmap) - - # Then, add it to our running list of inverted namespace - # mappings. - self.nsmaps.append(_invert(nsmap)) - - # The currently active namespace prefixes have - # changed. Calculate the new mapping so it can be stored - # with all Tag objects created while these prefixes are in - # scope. - current_mapping = dict(self.active_namespace_prefixes[-1]) - current_mapping.update(nsmap) - - # We should not track un-prefixed namespaces as we can only hold one - # and it will be recognized as the default namespace by soupsieve, - # which may be confusing in some situations. - if "" in current_mapping: - del current_mapping[""] - self.active_namespace_prefixes.append(current_mapping) - - # Also treat the namespace mapping as a set of attributes on the - # tag, so we can recreate it later. - for prefix, namespace in list(nsmap.items()): - attribute = NamespacedAttribute( - "xmlns", prefix, "http://www.w3.org/2000/xmlns/" - ) - new_attrs[attribute] = namespace - - # Namespaces are in play. Find any attributes that came in - # from lxml with namespaces attached to their names, and - # turn then into NamespacedAttribute objects. - final_attrs: AttributeDict = self.attribute_dict_class() - for attr, value in list(new_attrs.items()): - namespace, attr = self._getNsTag(attr) - if namespace is None: - final_attrs[attr] = value - else: - nsprefix = self._prefix_for_namespace(namespace) - attr = NamespacedAttribute(nsprefix, attr, namespace) - final_attrs[attr] = value - - namespace, tag = self._getNsTag(tag) - nsprefix = self._prefix_for_namespace(namespace) - self.soup.handle_starttag( - tag, - namespace, - nsprefix, - final_attrs, - namespaces=self.active_namespace_prefixes[-1], - ) - - def _prefix_for_namespace( - self, namespace: Optional[_NamespaceURL] - ) -> Optional[_NamespacePrefix]: - """Find the currently active prefix for the given namespace.""" - if namespace is None: - return None - for inverted_nsmap in reversed(self.nsmaps): - if inverted_nsmap is not None and namespace in inverted_nsmap: - return inverted_nsmap[namespace] - return None - - def end(self, name: str | bytes) -> None: - assert self.soup is not None - assert isinstance(name, str) - self.soup.endData() - namespace, name = self._getNsTag(name) - nsprefix = None - if namespace is not None: - for inverted_nsmap in reversed(self.nsmaps): - if inverted_nsmap is not None and namespace in inverted_nsmap: - nsprefix = inverted_nsmap[namespace] - break - self.soup.handle_endtag(name, nsprefix) - if len(self.nsmaps) > 1: - # This tag, or one of its parents, introduced a namespace - # mapping, so pop it off the stack. - out_of_scope_nsmap = self.nsmaps.pop() - - if out_of_scope_nsmap is not None: - # This tag introduced a namespace mapping which is no - # longer in scope. Recalculate the currently active - # namespace prefixes. - self.active_namespace_prefixes.pop() - - def pi(self, target: str, data: str) -> None: - assert self.soup is not None - self.soup.endData() - data = target + " " + data - self.soup.handle_data(data) - self.soup.endData(self.processing_instruction_class) - - def data(self, data: str | bytes) -> None: - assert self.soup is not None - assert isinstance(data, str) - self.soup.handle_data(data) - - def doctype(self, name: str, pubid: str, system: str) -> None: - assert self.soup is not None - self.soup.endData() - doctype_string = Doctype._string_for_name_and_ids(name, pubid, system) - self.soup.handle_data(doctype_string) - self.soup.endData(containerClass=Doctype) - - def comment(self, text: str | bytes) -> None: - "Handle comments as Comment objects." - assert self.soup is not None - assert isinstance(text, str) - self.soup.endData() - self.soup.handle_data(text) - self.soup.endData(Comment) - - def test_fragment_to_document(self, fragment: str) -> str: - """See `TreeBuilder`.""" - return '\n%s' % fragment - - -class LXMLTreeBuilder(HTMLTreeBuilder, LXMLTreeBuilderForXML): - NAME: str = LXML - ALTERNATE_NAMES: Iterable[str] = ["lxml-html"] - - features: Iterable[str] = list(ALTERNATE_NAMES) + [NAME, HTML, FAST, PERMISSIVE] - is_xml: bool = False - - def default_parser(self, encoding: Optional[_Encoding]) -> _ParserOrParserClass: - return etree.HTMLParser - - def feed(self, markup: _RawMarkup) -> None: - # We know self.soup is set by the time feed() is called. - assert self.soup is not None - encoding = self.soup.original_encoding - try: - self.parser = self.parser_for(encoding) - self.parser.feed(markup) - self.parser.close() - except (UnicodeDecodeError, LookupError, etree.ParserError) as e: - raise ParserRejectedMarkup(e) - - def test_fragment_to_document(self, fragment: str) -> str: - """See `TreeBuilder`.""" - return "%s" % fragment diff --git a/.venv/Lib/site-packages/bs4/css.py b/.venv/Lib/site-packages/bs4/css.py deleted file mode 100644 index c20850f..0000000 --- a/.venv/Lib/site-packages/bs4/css.py +++ /dev/null @@ -1,338 +0,0 @@ -"""Integration code for CSS selectors using `Soup Sieve `_ (pypi: ``soupsieve``). - -Acquire a `CSS` object through the `element.Tag.css` attribute of -the starting point of your CSS selector, or (if you want to run a -selector against the entire document) of the `BeautifulSoup` object -itself. - -The main advantage of doing this instead of using ``soupsieve`` -functions is that you don't need to keep passing the `element.Tag` to be -selected against, since the `CSS` object is permanently scoped to that -`element.Tag`. - -""" - -from __future__ import annotations - -from types import ModuleType -from typing import ( - Any, - cast, - Iterable, - Iterator, - Optional, - TYPE_CHECKING, -) -import warnings -from bs4._typing import _NamespaceMapping - -if TYPE_CHECKING: - from soupsieve import SoupSieve - from bs4 import element - from bs4.element import ResultSet, Tag - -soupsieve: Optional[ModuleType] -try: - import soupsieve -except ImportError: - soupsieve = None - warnings.warn( - "The soupsieve package is not installed. CSS selectors cannot be used." - ) - - -class CSS(object): - """A proxy object against the ``soupsieve`` library, to simplify its - CSS selector API. - - You don't need to instantiate this class yourself; instead, use - `element.Tag.css`. - - :param tag: All CSS selectors run by this object will use this as - their starting point. - - :param api: An optional drop-in replacement for the ``soupsieve`` module, - intended for use in unit tests. - """ - - def __init__(self, tag: element.Tag, api: Optional[ModuleType] = None): - if api is None: - api = soupsieve - if api is None: - raise NotImplementedError( - "Cannot execute CSS selectors because the soupsieve package is not installed." - ) - self.api = api - self.tag = tag - - def escape(self, ident: str) -> str: - """Escape a CSS identifier. - - This is a simple wrapper around `soupsieve.escape() `_. See the - documentation for that function for more information. - """ - if soupsieve is None: - raise NotImplementedError( - "Cannot escape CSS identifiers because the soupsieve package is not installed." - ) - return cast(str, self.api.escape(ident)) - - def _ns( - self, ns: Optional[_NamespaceMapping], select: str - ) -> Optional[_NamespaceMapping]: - """Normalize a dictionary of namespaces.""" - if not isinstance(select, self.api.SoupSieve) and ns is None: - # If the selector is a precompiled pattern, it already has - # a namespace context compiled in, which cannot be - # replaced. - ns = self.tag._namespaces - return ns - - def _rs(self, results: Iterable[Tag]) -> ResultSet[Tag]: - """Normalize a list of results to a py:class:`ResultSet`. - - A py:class:`ResultSet` is more consistent with the rest of - Beautiful Soup's API, and :py:meth:`ResultSet.__getattr__` has - a helpful error message if you try to treat a list of results - as a single result (a common mistake). - """ - # Import here to avoid circular import - from bs4 import ResultSet - - return ResultSet(None, results) - - def compile( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - flags: int = 0, - **kwargs: Any, - ) -> SoupSieve: - """Pre-compile a selector and return the compiled object. - - :param selector: A CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will use the prefixes it encountered while - parsing the document. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.compile() `_ method. - - :param kwargs: Keyword arguments to be passed into Soup Sieve's - `soupsieve.compile() `_ method. - - :return: A precompiled selector object. - :rtype: soupsieve.SoupSieve - """ - return self.api.compile(select, self._ns(namespaces, select), flags, **kwargs) - - def select_one( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - flags: int = 0, - **kwargs: Any, - ) -> element.Tag | None: - """Perform a CSS selection operation on the current Tag and return the - first result, if any. - - This uses the Soup Sieve library. For more information, see - that library's documentation for the `soupsieve.select_one() `_ method. - - :param selector: A CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will use the prefixes it encountered while - parsing the document. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.select_one() `_ method. - - :param kwargs: Keyword arguments to be passed into Soup Sieve's - `soupsieve.select_one() `_ method. - """ - return self.api.select_one( - select, self.tag, self._ns(namespaces, select), flags, **kwargs - ) - - def select( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - limit: int = 0, - flags: int = 0, - **kwargs: Any, - ) -> ResultSet[element.Tag]: - """Perform a CSS selection operation on the current `element.Tag`. - - This uses the Soup Sieve library. For more information, see - that library's documentation for the `soupsieve.select() `_ method. - - :param selector: A CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will pass in the prefixes it encountered while - parsing the document. - - :param limit: After finding this number of results, stop looking. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.select() `_ method. - - :param kwargs: Keyword arguments to be passed into Soup Sieve's - `soupsieve.select() `_ method. - """ - if limit is None: - limit = 0 - - return self._rs( - self.api.select( - select, self.tag, self._ns(namespaces, select), limit, flags, **kwargs - ) - ) - - def iselect( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - limit: int = 0, - flags: int = 0, - **kwargs: Any, - ) -> Iterator[element.Tag]: - """Perform a CSS selection operation on the current `element.Tag`. - - This uses the Soup Sieve library. For more information, see - that library's documentation for the `soupsieve.iselect() - `_ - method. It is the same as select(), but it returns a generator - instead of a list. - - :param selector: A string containing a CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will pass in the prefixes it encountered while - parsing the document. - - :param limit: After finding this number of results, stop looking. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.iselect() `_ method. - - :param kwargs: Keyword arguments to be passed into Soup Sieve's - `soupsieve.iselect() `_ method. - """ - return self.api.iselect( - select, self.tag, self._ns(namespaces, select), limit, flags, **kwargs - ) - - def closest( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - flags: int = 0, - **kwargs: Any, - ) -> Optional[element.Tag]: - """Find the `element.Tag` closest to this one that matches the given selector. - - This uses the Soup Sieve library. For more information, see - that library's documentation for the `soupsieve.closest() - `_ - method. - - :param selector: A string containing a CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will pass in the prefixes it encountered while - parsing the document. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.closest() `_ method. - - :param kwargs: Keyword arguments to be passed into Soup Sieve's - `soupsieve.closest() `_ method. - - """ - return self.api.closest( - select, self.tag, self._ns(namespaces, select), flags, **kwargs - ) - - def match( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - flags: int = 0, - **kwargs: Any, - ) -> bool: - """Check whether or not this `element.Tag` matches the given CSS selector. - - This uses the Soup Sieve library. For more information, see - that library's documentation for the `soupsieve.match() - `_ - method. - - :param: a CSS selector. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will pass in the prefixes it encountered while - parsing the document. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.match() - `_ - method. - - :param kwargs: Keyword arguments to be passed into SoupSieve's - `soupsieve.match() - `_ - method. - """ - return cast( - bool, - self.api.match( - select, self.tag, self._ns(namespaces, select), flags, **kwargs - ), - ) - - def filter( - self, - select: str, - namespaces: Optional[_NamespaceMapping] = None, - flags: int = 0, - **kwargs: Any, - ) -> ResultSet[element.Tag]: - """Filter this `element.Tag`'s direct children based on the given CSS selector. - - This uses the Soup Sieve library. It works the same way as - passing a `element.Tag` into that library's `soupsieve.filter() - `_ - method. For more information, see the documentation for - `soupsieve.filter() - `_. - - :param namespaces: A dictionary mapping namespace prefixes - used in the CSS selector to namespace URIs. By default, - Beautiful Soup will pass in the prefixes it encountered while - parsing the document. - - :param flags: Flags to be passed into Soup Sieve's - `soupsieve.filter() - `_ - method. - - :param kwargs: Keyword arguments to be passed into SoupSieve's - `soupsieve.filter() - `_ - method. - """ - return self._rs( - self.api.filter( - select, self.tag, self._ns(namespaces, select), flags, **kwargs - ) - ) diff --git a/.venv/Lib/site-packages/bs4/dammit.py b/.venv/Lib/site-packages/bs4/dammit.py deleted file mode 100644 index c9f4244..0000000 --- a/.venv/Lib/site-packages/bs4/dammit.py +++ /dev/null @@ -1,1408 +0,0 @@ -# -*- coding: utf-8 -*- -"""Beautiful Soup bonus library: Unicode, Dammit - -This library converts a bytestream to Unicode through any means -necessary. It is heavily based on code from Mark Pilgrim's `Universal -Feed Parser `_, now maintained -by Kurt McKee. It does not rewrite the body of an XML or HTML document -to reflect a new encoding; that's the job of `TreeBuilder`. - -""" - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -from html.entities import codepoint2name -from collections import defaultdict -import codecs -from html.entities import html5 -import re -from logging import Logger, getLogger -from types import ModuleType -from typing import ( - Dict, - Iterator, - List, - Optional, - Pattern, - Set, - Tuple, - Type, - Union, - cast, -) -from typing_extensions import Literal -from bs4._typing import ( - _Encoding, - _Encodings, -) -import warnings - -# Import a library to autodetect character encodings. We'll support -# any of a number of libraries that all support the same API: -# -# * cchardet -# * chardet -# * charset-normalizer -chardet_module: Optional[ModuleType] = None -try: - # PyPI package: cchardet - import cchardet - - chardet_module = cchardet -except ImportError: - try: - # Debian package: python-chardet - # PyPI package: chardet - import chardet - - chardet_module = chardet - except ImportError: - try: - # PyPI package: charset-normalizer - import charset_normalizer - - chardet_module = charset_normalizer - except ImportError: - # No chardet available. - pass - - -def _chardet_dammit(s: bytes) -> Optional[str]: - """Try as hard as possible to detect the encoding of a bytestring.""" - if chardet_module is None or isinstance(s, str): - return None - module = chardet_module - return module.detect(s)["encoding"] - - -# Build bytestring and Unicode versions of regular expressions for finding -# a declared encoding inside an XML or HTML document. -xml_encoding: str = "^\\s*<\\?.*encoding=['\"](.*?)['\"].*\\?>" #: :meta private: -html_meta: str = ( - "<\\s*meta[^>]+charset\\s*=\\s*[\"']?([^>]*?)[ /;'\">]" #: :meta private: -) - -# TODO-TYPING: The Pattern type here could use more refinement, but it's tricky. -encoding_res: Dict[Type, Dict[str, Pattern]] = dict() -encoding_res[bytes] = { - "html": re.compile(html_meta.encode("ascii"), re.I), - "xml": re.compile(xml_encoding.encode("ascii"), re.I), -} -encoding_res[str] = { - "html": re.compile(html_meta, re.I), - "xml": re.compile(xml_encoding, re.I), -} - - -class EntitySubstitution(object): - """The ability to substitute XML or HTML entities for certain characters.""" - - #: A map of named HTML entities to the corresponding Unicode string. - #: - #: :meta hide-value: - HTML_ENTITY_TO_CHARACTER: Dict[str, str] - - #: A map of Unicode strings to the corresponding named HTML entities; - #: the inverse of HTML_ENTITY_TO_CHARACTER. - #: - #: :meta hide-value: - CHARACTER_TO_HTML_ENTITY: Dict[str, str] - - #: A regular expression that matches any character (or, in rare - #: cases, pair of characters) that can be replaced with a named - #: HTML entity. - #: - #: :meta hide-value: - CHARACTER_TO_HTML_ENTITY_RE: Pattern[str] - - #: A very similar regular expression to - #: CHARACTER_TO_HTML_ENTITY_RE, but which also matches unescaped - #: ampersands. This is used by the 'html' formatted to provide - #: backwards-compatibility, even though the HTML5 spec allows most - #: ampersands to go unescaped. - #: - #: :meta hide-value: - CHARACTER_TO_HTML_ENTITY_WITH_AMPERSAND_RE: Pattern[str] - - @classmethod - def _populate_class_variables(cls) -> None: - """Initialize variables used by this class to manage the plethora of - HTML5 named entities. - - This function sets the following class variables: - - CHARACTER_TO_HTML_ENTITY - A mapping of Unicode strings like "⦨" to - entity names like "angmsdaa". When a single Unicode string has - multiple entity names, we try to choose the most commonly-used - name. - - HTML_ENTITY_TO_CHARACTER: A mapping of entity names like "angmsdaa" to - Unicode strings like "⦨". - - CHARACTER_TO_HTML_ENTITY_RE: A regular expression matching (almost) any - Unicode string that corresponds to an HTML5 named entity. - - CHARACTER_TO_HTML_ENTITY_WITH_AMPERSAND_RE: A very similar - regular expression to CHARACTER_TO_HTML_ENTITY_RE, but which - also matches unescaped ampersands. This is used by the 'html' - formatted to provide backwards-compatibility, even though the HTML5 - spec allows most ampersands to go unescaped. - """ - unicode_to_name = {} - name_to_unicode = {} - - short_entities = set() - long_entities_by_first_character = defaultdict(set) - - for name_with_semicolon, character in sorted(html5.items()): - # "It is intentional, for legacy compatibility, that many - # code points have multiple character reference names. For - # example, some appear both with and without the trailing - # semicolon, or with different capitalizations." - # - https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references - # - # The parsers are in charge of handling (or not) character - # references with no trailing semicolon, so we remove the - # semicolon whenever it appears. - if name_with_semicolon.endswith(";"): - name = name_with_semicolon[:-1] - else: - name = name_with_semicolon - - # When parsing HTML, we want to recognize any known named - # entity and convert it to a sequence of Unicode - # characters. - if name not in name_to_unicode: - name_to_unicode[name] = character - - # When _generating_ HTML, we want to recognize special - # character sequences that _could_ be converted to named - # entities. - unicode_to_name[character] = name - - # We also need to build a regular expression that lets us - # _find_ those characters in output strings so we can - # replace them. - # - # This is tricky, for two reasons. - - if len(character) == 1 and ord(character) < 128 and character not in "<>": - # First, it would be annoying to turn single ASCII - # characters like | into named entities like - # |. The exceptions are <>, which we _must_ - # turn into named entities to produce valid HTML. - continue - - if len(character) > 1 and all(ord(x) < 128 for x in character): - # We also do not want to turn _combinations_ of ASCII - # characters like 'fj' into named entities like 'fj', - # though that's more debateable. - continue - - # Second, some named entities have a Unicode value that's - # a subset of the Unicode value for some _other_ named - # entity. As an example, \u2267' is ≧, - # but '\u2267\u0338' is ≧̸. Our regular - # expression needs to match the first two characters of - # "\u2267\u0338foo", but only the first character of - # "\u2267foo". - # - # In this step, we build two sets of characters that - # _eventually_ need to go into the regular expression. But - # we won't know exactly what the regular expression needs - # to look like until we've gone through the entire list of - # named entities. - if len(character) == 1 and character != "&": - short_entities.add(character) - else: - long_entities_by_first_character[character[0]].add(character) - - # Now that we've been through the entire list of entities, we - # can create a regular expression that matches any of them. - particles = set() - for short in short_entities: - long_versions = long_entities_by_first_character[short] - if not long_versions: - particles.add(short) - else: - ignore = "".join([x[1] for x in long_versions]) - # This finds, e.g. \u2267 but only if it is _not_ - # followed by \u0338. - particles.add("%s(?![%s])" % (short, ignore)) - - for long_entities in list(long_entities_by_first_character.values()): - for long_entity in long_entities: - particles.add(long_entity) - - re_definition = "(%s)" % "|".join(particles) - - particles.add("&") - re_definition_with_ampersand = "(%s)" % "|".join(particles) - - # If an entity shows up in both html5 and codepoint2name, it's - # likely that HTML5 gives it several different names, such as - # 'rsquo' and 'rsquor'. When converting Unicode characters to - # named entities, the codepoint2name name should take - # precedence where possible, since that's the more easily - # recognizable one. - for codepoint, name in list(codepoint2name.items()): - character = chr(codepoint) - unicode_to_name[character] = name - - cls.CHARACTER_TO_HTML_ENTITY = unicode_to_name - cls.HTML_ENTITY_TO_CHARACTER = name_to_unicode - cls.CHARACTER_TO_HTML_ENTITY_RE = re.compile(re_definition) - cls.CHARACTER_TO_HTML_ENTITY_WITH_AMPERSAND_RE = re.compile( - re_definition_with_ampersand - ) - - #: A map of Unicode strings to the corresponding named XML entities. - #: - #: :meta hide-value: - CHARACTER_TO_XML_ENTITY: Dict[str, str] = { - "'": "apos", - '"': "quot", - "&": "amp", - "<": "lt", - ">": "gt", - } - - # Matches any named or numeric HTML entity. - ANY_ENTITY_RE = re.compile("&(#\\d+|#x[0-9a-fA-F]+|\\w+);", re.I) - - #: A regular expression matching an angle bracket or an ampersand that - #: is not part of an XML or HTML entity. - #: - #: :meta hide-value: - BARE_AMPERSAND_OR_BRACKET: Pattern[str] = re.compile( - "([<>]|" "&(?!#\\d+;|#x[0-9a-fA-F]+;|\\w+;)" ")" - ) - - #: A regular expression matching an angle bracket or an ampersand. - #: - #: :meta hide-value: - AMPERSAND_OR_BRACKET: Pattern[str] = re.compile("([<>&])") - - @classmethod - def _substitute_html_entity(cls, matchobj: re.Match) -> str: - """Used with a regular expression to substitute the - appropriate HTML entity for a special character string.""" - original_entity = matchobj.group(0) - entity = cls.CHARACTER_TO_HTML_ENTITY.get(original_entity) - if entity is None: - return "&%s;" % original_entity - return "&%s;" % entity - - @classmethod - def _substitute_xml_entity(cls, matchobj: re.Match) -> str: - """Used with a regular expression to substitute the - appropriate XML entity for a special character string.""" - entity = cls.CHARACTER_TO_XML_ENTITY[matchobj.group(0)] - return "&%s;" % entity - - @classmethod - def _escape_entity_name(cls, matchobj: re.Match) -> str: - return "&%s;" % matchobj.group(1) - - @classmethod - def _escape_unrecognized_entity_name(cls, matchobj: re.Match) -> str: - possible_entity = matchobj.group(1) - if possible_entity in cls.HTML_ENTITY_TO_CHARACTER: - return "&%s;" % possible_entity - return "&%s;" % possible_entity - - @classmethod - def quoted_attribute_value(cls, value: str) -> str: - """Make a value into a quoted XML attribute, possibly escaping it. - - Most strings will be quoted using double quotes. - - Bob's Bar -> "Bob's Bar" - - If a string contains double quotes, it will be quoted using - single quotes. - - Welcome to "my bar" -> 'Welcome to "my bar"' - - If a string contains both single and double quotes, the - double quotes will be escaped, and the string will be quoted - using double quotes. - - Welcome to "Bob's Bar" -> Welcome to "Bob's bar" - - :param value: The XML attribute value to quote - :return: The quoted value - """ - quote_with = '"' - if '"' in value: - if "'" in value: - # The string contains both single and double - # quotes. Turn the double quotes into - # entities. We quote the double quotes rather than - # the single quotes because the entity name is - # """ whether this is HTML or XML. If we - # quoted the single quotes, we'd have to decide - # between ' and &squot;. - replace_with = """ - value = value.replace('"', replace_with) - else: - # There are double quotes but no single quotes. - # We can use single quotes to quote the attribute. - quote_with = "'" - return quote_with + value + quote_with - - @classmethod - def substitute_xml(cls, value: str, make_quoted_attribute: bool = False) -> str: - """Replace special XML characters with named XML entities. - - The less-than sign will become <, the greater-than sign - will become >, and any ampersands will become &. If you - want ampersands that seem to be part of an entity definition - to be left alone, use `substitute_xml_containing_entities` - instead. - - :param value: A string to be substituted. - - :param make_quoted_attribute: If True, then the string will be - quoted, as befits an attribute value. - - :return: A version of ``value`` with special characters replaced - with named entities. - """ - # Escape angle brackets and ampersands. - value = cls.AMPERSAND_OR_BRACKET.sub(cls._substitute_xml_entity, value) - - if make_quoted_attribute: - value = cls.quoted_attribute_value(value) - return value - - @classmethod - def substitute_xml_containing_entities( - cls, value: str, make_quoted_attribute: bool = False - ) -> str: - """Substitute XML entities for special XML characters. - - :param value: A string to be substituted. The less-than sign will - become <, the greater-than sign will become >, and any - ampersands that are not part of an entity defition will - become &. - - :param make_quoted_attribute: If True, then the string will be - quoted, as befits an attribute value. - """ - # Escape angle brackets, and ampersands that aren't part of - # entities. - value = cls.BARE_AMPERSAND_OR_BRACKET.sub(cls._substitute_xml_entity, value) - - if make_quoted_attribute: - value = cls.quoted_attribute_value(value) - return value - - @classmethod - def substitute_html(cls, s: str) -> str: - """Replace certain Unicode characters with named HTML entities. - - This differs from ``data.encode(encoding, 'xmlcharrefreplace')`` - in that the goal is to make the result more readable (to those - with ASCII displays) rather than to recover from - errors. There's absolutely nothing wrong with a UTF-8 string - containg a LATIN SMALL LETTER E WITH ACUTE, but replacing that - character with "é" will make it more readable to some - people. - - :param s: The string to be modified. - :return: The string with some Unicode characters replaced with - HTML entities. - """ - # Convert any appropriate characters to HTML entities. - return cls.CHARACTER_TO_HTML_ENTITY_WITH_AMPERSAND_RE.sub( - cls._substitute_html_entity, s - ) - - @classmethod - def substitute_html5(cls, s: str) -> str: - """Replace certain Unicode characters with named HTML entities - using HTML5 rules. - - Specifically, this method is much less aggressive about - escaping ampersands than substitute_html. Only ambiguous - ampersands are escaped, per the HTML5 standard: - - "An ambiguous ampersand is a U+0026 AMPERSAND character (&) - that is followed by one or more ASCII alphanumerics, followed - by a U+003B SEMICOLON character (;), where these characters do - not match any of the names given in the named character - references section." - - Unlike substitute_html5_raw, this method assumes HTML entities - were converted to Unicode characters on the way in, as - Beautiful Soup does. By the time Beautiful Soup does its work, - the only ambiguous ampersands that need to be escaped are the - ones that were escaped in the original markup when mentioning - HTML entities. - - :param s: The string to be modified. - :return: The string with some Unicode characters replaced with - HTML entities. - """ - # First, escape any HTML entities found in the markup. - s = cls.ANY_ENTITY_RE.sub(cls._escape_entity_name, s) - - # Next, convert any appropriate characters to unescaped HTML entities. - s = cls.CHARACTER_TO_HTML_ENTITY_RE.sub(cls._substitute_html_entity, s) - - return s - - @classmethod - def substitute_html5_raw(cls, s: str) -> str: - """Replace certain Unicode characters with named HTML entities - using HTML5 rules. - - substitute_html5_raw is similar to substitute_html5 but it is - designed for standalone use (whereas substitute_html5 is - designed for use with Beautiful Soup). - - :param s: The string to be modified. - :return: The string with some Unicode characters replaced with - HTML entities. - """ - # First, escape the ampersand for anything that looks like an - # entity but isn't in the list of recognized entities. All other - # ampersands can be left alone. - s = cls.ANY_ENTITY_RE.sub(cls._escape_unrecognized_entity_name, s) - - # Then, convert a range of Unicode characters to unescaped - # HTML entities. - s = cls.CHARACTER_TO_HTML_ENTITY_RE.sub(cls._substitute_html_entity, s) - - return s - - -EntitySubstitution._populate_class_variables() - - -class EncodingDetector: - """This class is capable of guessing a number of possible encodings - for a bytestring. - - Order of precedence: - - 1. Encodings you specifically tell EncodingDetector to try first - (the ``known_definite_encodings`` argument to the constructor). - - 2. An encoding determined by sniffing the document's byte-order mark. - - 3. Encodings you specifically tell EncodingDetector to try if - byte-order mark sniffing fails (the ``user_encodings`` argument to the - constructor). - - 4. An encoding declared within the bytestring itself, either in an - XML declaration (if the bytestring is to be interpreted as an XML - document), or in a tag (if the bytestring is to be - interpreted as an HTML document.) - - 5. An encoding detected through textual analysis by chardet, - cchardet, or a similar external library. - - 6. UTF-8. - - 7. Windows-1252. - - :param markup: Some markup in an unknown encoding. - - :param known_definite_encodings: When determining the encoding - of ``markup``, these encodings will be tried first, in - order. In HTML terms, this corresponds to the "known - definite encoding" step defined in `section 13.2.3.1 of the HTML standard `_. - - :param user_encodings: These encodings will be tried after the - ``known_definite_encodings`` have been tried and failed, and - after an attempt to sniff the encoding by looking at a - byte order mark has failed. In HTML terms, this - corresponds to the step "user has explicitly instructed - the user agent to override the document's character - encoding", defined in `section 13.2.3.2 of the HTML standard `_. - - :param override_encodings: A **deprecated** alias for - ``known_definite_encodings``. Any encodings here will be tried - immediately after the encodings in - ``known_definite_encodings``. - - :param is_html: If True, this markup is considered to be - HTML. Otherwise it's assumed to be XML. - - :param exclude_encodings: These encodings will not be tried, - even if they otherwise would be. - - """ - - def __init__( - self, - markup: bytes, - known_definite_encodings: Optional[_Encodings] = None, - is_html: Optional[bool] = False, - exclude_encodings: Optional[_Encodings] = None, - user_encodings: Optional[_Encodings] = None, - override_encodings: Optional[_Encodings] = None, - ): - self.known_definite_encodings = list(known_definite_encodings or []) - if override_encodings: - warnings.warn( - "The 'override_encodings' argument was deprecated in 4.10.0. Use 'known_definite_encodings' instead.", - DeprecationWarning, - stacklevel=3, - ) - self.known_definite_encodings += override_encodings - self.user_encodings = user_encodings or [] - exclude_encodings = exclude_encodings or [] - self.exclude_encodings = set([x.lower() for x in exclude_encodings]) - self.chardet_encoding = None - self.is_html = False if is_html is None else is_html - self.declared_encoding: Optional[str] = None - - # First order of business: strip a byte-order mark. - self.markup, self.sniffed_encoding = self.strip_byte_order_mark(markup) - - known_definite_encodings: _Encodings - user_encodings: _Encodings - exclude_encodings: _Encodings - chardet_encoding: Optional[_Encoding] - is_html: bool - declared_encoding: Optional[_Encoding] - markup: bytes - sniffed_encoding: Optional[_Encoding] - - def _usable(self, encoding: Optional[_Encoding], tried: Set[_Encoding]) -> bool: - """Should we even bother to try this encoding? - - :param encoding: Name of an encoding. - :param tried: Encodings that have already been tried. This - will be modified as a side effect. - """ - if encoding is None: - return False - encoding = encoding.lower() - if encoding in self.exclude_encodings: - return False - if encoding not in tried: - tried.add(encoding) - return True - return False - - @property - def encodings(self) -> Iterator[_Encoding]: - """Yield a number of encodings that might work for this markup. - - :yield: A sequence of strings. Each is the name of an encoding - that *might* work to convert a bytestring into Unicode. - """ - tried: Set[_Encoding] = set() - - # First, try the known definite encodings - for e in self.known_definite_encodings: - if self._usable(e, tried): - yield e - - # Did the document originally start with a byte-order mark - # that indicated its encoding? - if self.sniffed_encoding is not None and self._usable( - self.sniffed_encoding, tried - ): - yield self.sniffed_encoding - - # Sniffing the byte-order mark did nothing; try the user - # encodings. - for e in self.user_encodings: - if self._usable(e, tried): - yield e - - # Look within the document for an XML or HTML encoding - # declaration. - if self.declared_encoding is None: - self.declared_encoding = self.find_declared_encoding( - self.markup, self.is_html - ) - if self.declared_encoding is not None and self._usable( - self.declared_encoding, tried - ): - yield self.declared_encoding - - # Use third-party character set detection to guess at the - # encoding. - if self.chardet_encoding is None: - self.chardet_encoding = _chardet_dammit(self.markup) - if self.chardet_encoding is not None and self._usable( - self.chardet_encoding, tried - ): - yield self.chardet_encoding - - # As a last-ditch effort, try utf-8 and windows-1252. - for e in ("utf-8", "windows-1252"): - if self._usable(e, tried): - yield e - - @classmethod - def strip_byte_order_mark(cls, data: bytes) -> Tuple[bytes, Optional[_Encoding]]: - """If a byte-order mark is present, strip it and return the encoding it implies. - - :param data: A bytestring that may or may not begin with a - byte-order mark. - - :return: A 2-tuple (data stripped of byte-order mark, encoding implied by byte-order mark) - """ - encoding = None - if isinstance(data, str): - # Unicode data cannot have a byte-order mark. - return data, encoding - if ( - (len(data) >= 4) - and (data[:2] == b"\xfe\xff") - and (data[2:4] != b"\x00\x00") - ): - encoding = "utf-16be" - data = data[2:] - elif ( - (len(data) >= 4) - and (data[:2] == b"\xff\xfe") - and (data[2:4] != b"\x00\x00") - ): - encoding = "utf-16le" - data = data[2:] - elif data[:3] == b"\xef\xbb\xbf": - encoding = "utf-8" - data = data[3:] - elif data[:4] == b"\x00\x00\xfe\xff": - encoding = "utf-32be" - data = data[4:] - elif data[:4] == b"\xff\xfe\x00\x00": - encoding = "utf-32le" - data = data[4:] - return data, encoding - - @classmethod - def find_declared_encoding( - cls, - markup: Union[bytes, str], - is_html: bool = False, - search_entire_document: bool = False, - ) -> Optional[_Encoding]: - """Given a document, tries to find an encoding declared within the - text of the document itself. - - An XML encoding is declared at the beginning of the document. - - An HTML encoding is declared in a tag, hopefully near the - beginning of the document. - - :param markup: Some markup. - :param is_html: If True, this markup is considered to be HTML. Otherwise - it's assumed to be XML. - :param search_entire_document: Since an encoding is supposed - to declared near the beginning of the document, most of - the time it's only necessary to search a few kilobytes of - data. Set this to True to force this method to search the - entire document. - :return: The declared encoding, if one is found. - """ - if search_entire_document: - xml_endpos = html_endpos = len(markup) - else: - xml_endpos = 1024 - html_endpos = max(2048, int(len(markup) * 0.05)) - - if isinstance(markup, bytes): - res = encoding_res[bytes] - else: - res = encoding_res[str] - - xml_re = res["xml"] - html_re = res["html"] - declared_encoding: Optional[_Encoding] = None - declared_encoding_match = xml_re.search(markup, endpos=xml_endpos) - if not declared_encoding_match and is_html: - declared_encoding_match = html_re.search(markup, endpos=html_endpos) - if declared_encoding_match is not None: - declared_encoding = declared_encoding_match.groups()[0] - if declared_encoding: - if isinstance(declared_encoding, bytes): - declared_encoding = declared_encoding.decode("ascii", "replace") - return declared_encoding.lower() - return None - - -class UnicodeDammit: - """A class for detecting the encoding of a bytestring containing an - HTML or XML document, and decoding it to Unicode. If the source - encoding is windows-1252, `UnicodeDammit` can also replace - Microsoft smart quotes with their HTML or XML equivalents. - - :param markup: HTML or XML markup in an unknown encoding. - - :param known_definite_encodings: When determining the encoding - of ``markup``, these encodings will be tried first, in - order. In HTML terms, this corresponds to the "known - definite encoding" step defined in `section 13.2.3.1 of the HTML standard `_. - - :param user_encodings: These encodings will be tried after the - ``known_definite_encodings`` have been tried and failed, and - after an attempt to sniff the encoding by looking at a - byte order mark has failed. In HTML terms, this - corresponds to the step "user has explicitly instructed - the user agent to override the document's character - encoding", defined in `section 13.2.3.2 of the HTML standard `_. - - :param override_encodings: A **deprecated** alias for - ``known_definite_encodings``. Any encodings here will be tried - immediately after the encodings in - ``known_definite_encodings``. - - :param smart_quotes_to: By default, Microsoft smart quotes will, - like all other characters, be converted to Unicode - characters. Setting this to ``ascii`` will convert them to ASCII - quotes instead. Setting it to ``xml`` will convert them to XML - entity references, and setting it to ``html`` will convert them - to HTML entity references. - - :param is_html: If True, ``markup`` is treated as an HTML - document. Otherwise it's treated as an XML document. - - :param exclude_encodings: These encodings will not be considered, - even if the sniffing code thinks they might make sense. - - """ - - def __init__( - self, - markup: bytes, - known_definite_encodings: Optional[_Encodings] = [], - smart_quotes_to: Optional[Literal["ascii", "xml", "html"]] = None, - is_html: bool = False, - exclude_encodings: Optional[_Encodings] = [], - user_encodings: Optional[_Encodings] = None, - override_encodings: Optional[_Encodings] = None, - ): - self.smart_quotes_to = smart_quotes_to - self.tried_encodings = [] - self.contains_replacement_characters = False - self.is_html = is_html - self.log = getLogger(__name__) - self.detector = EncodingDetector( - markup, - known_definite_encodings, - is_html, - exclude_encodings, - user_encodings, - override_encodings, - ) - - # Short-circuit if the data is in Unicode to begin with. - if isinstance(markup, str) or markup == b"": - self.markup = markup - self.unicode_markup = str(markup) - self.original_encoding = None - return - - # The encoding detector may have stripped a byte-order mark. - # Use the stripped markup from this point on. - self.markup = self.detector.markup - - u = None - for encoding in self.detector.encodings: - markup = self.detector.markup - u = self._convert_from(encoding) - if u is not None: - break - - if not u: - # None of the encodings worked. As an absolute last resort, - # try them again with character replacement. - - for encoding in self.detector.encodings: - if encoding != "ascii": - u = self._convert_from(encoding, "replace") - if u is not None: - self.log.warning( - "Some characters could not be decoded, and were " - "replaced with REPLACEMENT CHARACTER." - ) - - self.contains_replacement_characters = True - break - - # If none of that worked, we could at this point force it to - # ASCII, but that would destroy so much data that I think - # giving up is better. - # - # Note that this is extremely unlikely, probably impossible, - # because the "replace" strategy is so powerful. Even running - # the Python binary through Unicode, Dammit gives you Unicode, - # albeit Unicode riddled with REPLACEMENT CHARACTER. - if u is None: - self.original_encoding = None - self.unicode_markup = None - else: - self.unicode_markup = u - - #: The original markup, before it was converted to Unicode. - #: This is not necessarily the same as what was passed in to the - #: constructor, since any byte-order mark will be stripped. - markup: bytes - - #: The Unicode version of the markup, following conversion. This - #: is set to None if there was simply no way to convert the - #: bytestring to Unicode (as with binary data). - unicode_markup: Optional[str] - - #: This is True if `UnicodeDammit.unicode_markup` contains - #: U+FFFD REPLACEMENT_CHARACTER characters which were not present - #: in `UnicodeDammit.markup`. These mark character sequences that - #: could not be represented in Unicode. - contains_replacement_characters: bool - - #: Unicode, Dammit's best guess as to the original character - #: encoding of `UnicodeDammit.markup`. - original_encoding: Optional[_Encoding] - - #: The strategy used to handle Microsoft smart quotes. - smart_quotes_to: Optional[str] - - #: The (encoding, error handling strategy) 2-tuples that were used to - #: try and convert the markup to Unicode. - tried_encodings: List[Tuple[_Encoding, str]] - - log: Logger #: :meta private: - - def _sub_ms_char(self, match: re.Match) -> bytes: - """Changes a MS smart quote character to an XML or HTML - entity, or an ASCII character. - - TODO: Since this is only used to convert smart quotes, it - could be simplified, and MS_CHARS_TO_ASCII made much less - parochial. - """ - orig: bytes = match.group(1) - sub: bytes - if self.smart_quotes_to == "ascii": - if orig in self.MS_CHARS_TO_ASCII: - sub = self.MS_CHARS_TO_ASCII[orig].encode() - else: - # Shouldn't happen; substitute the character - # with itself. - sub = orig - else: - if orig in self.MS_CHARS: - substitutions = self.MS_CHARS[orig] - if type(substitutions) is tuple: - if self.smart_quotes_to == "xml": - sub = b"&#x" + substitutions[1].encode() + b";" - else: - sub = b"&" + substitutions[0].encode() + b";" - else: - substitutions = cast(str, substitutions) - sub = substitutions.encode() - else: - # Shouldn't happen; substitute the character - # for itself. - sub = orig - return sub - - #: This dictionary maps commonly seen values for "charset" in HTML - #: meta tags to the corresponding Python codec names. It only covers - #: values that aren't in Python's aliases and can't be determined - #: by the heuristics in `find_codec`. - #: - #: :meta hide-value: - CHARSET_ALIASES: Dict[str, _Encoding] = { - "macintosh": "mac-roman", - "x-sjis": "shift-jis", - } - - #: A list of encodings that tend to contain Microsoft smart quotes. - #: - #: :meta hide-value: - ENCODINGS_WITH_SMART_QUOTES: _Encodings = [ - "windows-1252", - "iso-8859-1", - "iso-8859-2", - ] - - def _convert_from( - self, proposed: _Encoding, errors: str = "strict" - ) -> Optional[str]: - """Attempt to convert the markup to the proposed encoding. - - :param proposed: The name of a character encoding. - :param errors: An error handling strategy, used when calling `str`. - :return: The converted markup, or `None` if the proposed - encoding/error handling strategy didn't work. - """ - lookup_result = self.find_codec(proposed) - if lookup_result is None or (lookup_result, errors) in self.tried_encodings: - return None - proposed = lookup_result - self.tried_encodings.append((proposed, errors)) - markup = self.markup - # Convert smart quotes to HTML if coming from an encoding - # that might have them. - if ( - self.smart_quotes_to is not None - and proposed in self.ENCODINGS_WITH_SMART_QUOTES - ): - smart_quotes_re = b"([\x80-\x9f])" - smart_quotes_compiled = re.compile(smart_quotes_re) - markup = smart_quotes_compiled.sub(self._sub_ms_char, markup) - - try: - # print("Trying to convert document to %s (errors=%s)" % ( - # proposed, errors)) - u = self._to_unicode(markup, proposed, errors) - self.unicode_markup = u - self.original_encoding = proposed - except Exception: - # print("That didn't work!") - # print(e) - return None - # print("Correct encoding: %s" % proposed) - return self.unicode_markup - - def _to_unicode( - self, data: bytes, encoding: _Encoding, errors: str = "strict" - ) -> str: - """Given a bytestring and its encoding, decodes the string into Unicode. - - :param encoding: The name of an encoding. - :param errors: An error handling strategy, used when calling `str`. - """ - return str(data, encoding, errors) - - @property - def declared_html_encoding(self) -> Optional[_Encoding]: - """If the markup is an HTML document, returns the encoding, if any, - declared *inside* the document. - """ - if not self.is_html: - return None - return self.detector.declared_encoding - - def find_codec(self, charset: _Encoding) -> Optional[str]: - """Look up the Python codec corresponding to a given character set. - - :param charset: The name of a character set. - :return: The name of a Python codec. - """ - value = ( - self._codec(self.CHARSET_ALIASES.get(charset, charset)) - or (charset and self._codec(charset.replace("-", ""))) - or (charset and self._codec(charset.replace("-", "_"))) - or (charset and charset.lower()) - or charset - ) - if value: - return value.lower() - return None - - def _codec(self, charset: _Encoding) -> Optional[str]: - if not charset: - return charset - codec = None - try: - codecs.lookup(charset) - codec = charset - except (LookupError, ValueError): - pass - return codec - - #: A partial mapping of ISO-Latin-1 to HTML entities/XML numeric entities. - #: - #: :meta hide-value: - MS_CHARS: Dict[bytes, Union[str, Tuple[str, str]]] = { - b"\x80": ("euro", "20AC"), - b"\x81": " ", - b"\x82": ("sbquo", "201A"), - b"\x83": ("fnof", "192"), - b"\x84": ("bdquo", "201E"), - b"\x85": ("hellip", "2026"), - b"\x86": ("dagger", "2020"), - b"\x87": ("Dagger", "2021"), - b"\x88": ("circ", "2C6"), - b"\x89": ("permil", "2030"), - b"\x8a": ("Scaron", "160"), - b"\x8b": ("lsaquo", "2039"), - b"\x8c": ("OElig", "152"), - b"\x8d": "?", - b"\x8e": ("#x17D", "17D"), - b"\x8f": "?", - b"\x90": "?", - b"\x91": ("lsquo", "2018"), - b"\x92": ("rsquo", "2019"), - b"\x93": ("ldquo", "201C"), - b"\x94": ("rdquo", "201D"), - b"\x95": ("bull", "2022"), - b"\x96": ("ndash", "2013"), - b"\x97": ("mdash", "2014"), - b"\x98": ("tilde", "2DC"), - b"\x99": ("trade", "2122"), - b"\x9a": ("scaron", "161"), - b"\x9b": ("rsaquo", "203A"), - b"\x9c": ("oelig", "153"), - b"\x9d": "?", - b"\x9e": ("#x17E", "17E"), - b"\x9f": ("Yuml", ""), - } - - #: A parochial partial mapping of ISO-Latin-1 to ASCII. Contains - #: horrors like stripping diacritical marks to turn á into a, but also - #: contains non-horrors like turning “ into ". - #: - #: Seriously, don't use this for anything other than removing smart - #: quotes. - #: - #: :meta private: - MS_CHARS_TO_ASCII: Dict[bytes, str] = { - b"\x80": "EUR", - b"\x81": " ", - b"\x82": ",", - b"\x83": "f", - b"\x84": ",,", - b"\x85": "...", - b"\x86": "+", - b"\x87": "++", - b"\x88": "^", - b"\x89": "%", - b"\x8a": "S", - b"\x8b": "<", - b"\x8c": "OE", - b"\x8d": "?", - b"\x8e": "Z", - b"\x8f": "?", - b"\x90": "?", - b"\x91": "'", - b"\x92": "'", - b"\x93": '"', - b"\x94": '"', - b"\x95": "*", - b"\x96": "-", - b"\x97": "--", - b"\x98": "~", - b"\x99": "(TM)", - b"\x9a": "s", - b"\x9b": ">", - b"\x9c": "oe", - b"\x9d": "?", - b"\x9e": "z", - b"\x9f": "Y", - b"\xa0": " ", - b"\xa1": "!", - b"\xa2": "c", - b"\xa3": "GBP", - b"\xa4": "$", # This approximation is especially parochial--this is the - # generic currency symbol. - b"\xa5": "YEN", - b"\xa6": "|", - b"\xa7": "S", - b"\xa8": "..", - b"\xa9": "", - b"\xaa": "(th)", - b"\xab": "<<", - b"\xac": "!", - b"\xad": " ", - b"\xae": "(R)", - b"\xaf": "-", - b"\xb0": "o", - b"\xb1": "+-", - b"\xb2": "2", - b"\xb3": "3", - b"\xb4": "'", - b"\xb5": "u", - b"\xb6": "P", - b"\xb7": "*", - b"\xb8": ",", - b"\xb9": "1", - b"\xba": "(th)", - b"\xbb": ">>", - b"\xbc": "1/4", - b"\xbd": "1/2", - b"\xbe": "3/4", - b"\xbf": "?", - b"\xc0": "A", - b"\xc1": "A", - b"\xc2": "A", - b"\xc3": "A", - b"\xc4": "A", - b"\xc5": "A", - b"\xc6": "AE", - b"\xc7": "C", - b"\xc8": "E", - b"\xc9": "E", - b"\xca": "E", - b"\xcb": "E", - b"\xcc": "I", - b"\xcd": "I", - b"\xce": "I", - b"\xcf": "I", - b"\xd0": "D", - b"\xd1": "N", - b"\xd2": "O", - b"\xd3": "O", - b"\xd4": "O", - b"\xd5": "O", - b"\xd6": "O", - b"\xd7": "*", - b"\xd8": "O", - b"\xd9": "U", - b"\xda": "U", - b"\xdb": "U", - b"\xdc": "U", - b"\xdd": "Y", - b"\xde": "b", - b"\xdf": "B", - b"\xe0": "a", - b"\xe1": "a", - b"\xe2": "a", - b"\xe3": "a", - b"\xe4": "a", - b"\xe5": "a", - b"\xe6": "ae", - b"\xe7": "c", - b"\xe8": "e", - b"\xe9": "e", - b"\xea": "e", - b"\xeb": "e", - b"\xec": "i", - b"\xed": "i", - b"\xee": "i", - b"\xef": "i", - b"\xf0": "o", - b"\xf1": "n", - b"\xf2": "o", - b"\xf3": "o", - b"\xf4": "o", - b"\xf5": "o", - b"\xf6": "o", - b"\xf7": "/", - b"\xf8": "o", - b"\xf9": "u", - b"\xfa": "u", - b"\xfb": "u", - b"\xfc": "u", - b"\xfd": "y", - b"\xfe": "b", - b"\xff": "y", - } - - #: A map used when removing rogue Windows-1252/ISO-8859-1 - #: characters in otherwise UTF-8 documents. - #: - #: Note that \\x81, \\x8d, \\x8f, \\x90, and \\x9d are undefined in - #: Windows-1252. - #: - #: :meta hide-value: - WINDOWS_1252_TO_UTF8: Dict[int, bytes] = { - 0x80: b"\xe2\x82\xac", # € - 0x82: b"\xe2\x80\x9a", # ‚ - 0x83: b"\xc6\x92", # Æ’ - 0x84: b"\xe2\x80\x9e", # „ - 0x85: b"\xe2\x80\xa6", # … - 0x86: b"\xe2\x80\xa0", # † - 0x87: b"\xe2\x80\xa1", # ‡ - 0x88: b"\xcb\x86", # ˆ - 0x89: b"\xe2\x80\xb0", # ‰ - 0x8A: b"\xc5\xa0", # Å  - 0x8B: b"\xe2\x80\xb9", # ‹ - 0x8C: b"\xc5\x92", # Å’ - 0x8E: b"\xc5\xbd", # Ž - 0x91: b"\xe2\x80\x98", # ‘ - 0x92: b"\xe2\x80\x99", # ’ - 0x93: b"\xe2\x80\x9c", # “ - 0x94: b"\xe2\x80\x9d", # †- 0x95: b"\xe2\x80\xa2", # • - 0x96: b"\xe2\x80\x93", # – - 0x97: b"\xe2\x80\x94", # — - 0x98: b"\xcb\x9c", # Ëœ - 0x99: b"\xe2\x84\xa2", # â„¢ - 0x9A: b"\xc5\xa1", # Å¡ - 0x9B: b"\xe2\x80\xba", # › - 0x9C: b"\xc5\x93", # Å“ - 0x9E: b"\xc5\xbe", # ž - 0x9F: b"\xc5\xb8", # Ÿ - 0xA0: b"\xc2\xa0", # - 0xA1: b"\xc2\xa1", # ¡ - 0xA2: b"\xc2\xa2", # ¢ - 0xA3: b"\xc2\xa3", # £ - 0xA4: b"\xc2\xa4", # ¤ - 0xA5: b"\xc2\xa5", # Â¥ - 0xA6: b"\xc2\xa6", # ¦ - 0xA7: b"\xc2\xa7", # § - 0xA8: b"\xc2\xa8", # ¨ - 0xA9: b"\xc2\xa9", # © - 0xAA: b"\xc2\xaa", # ª - 0xAB: b"\xc2\xab", # « - 0xAC: b"\xc2\xac", # ¬ - 0xAD: b"\xc2\xad", # ­ - 0xAE: b"\xc2\xae", # ® - 0xAF: b"\xc2\xaf", # ¯ - 0xB0: b"\xc2\xb0", # ° - 0xB1: b"\xc2\xb1", # ± - 0xB2: b"\xc2\xb2", # ² - 0xB3: b"\xc2\xb3", # ³ - 0xB4: b"\xc2\xb4", # ´ - 0xB5: b"\xc2\xb5", # µ - 0xB6: b"\xc2\xb6", # ¶ - 0xB7: b"\xc2\xb7", # · - 0xB8: b"\xc2\xb8", # ¸ - 0xB9: b"\xc2\xb9", # ¹ - 0xBA: b"\xc2\xba", # º - 0xBB: b"\xc2\xbb", # » - 0xBC: b"\xc2\xbc", # ¼ - 0xBD: b"\xc2\xbd", # ½ - 0xBE: b"\xc2\xbe", # ¾ - 0xBF: b"\xc2\xbf", # ¿ - 0xC0: b"\xc3\x80", # À - 0xC1: b"\xc3\x81", # à - 0xC2: b"\xc3\x82", #  - 0xC3: b"\xc3\x83", # à - 0xC4: b"\xc3\x84", # Ä - 0xC5: b"\xc3\x85", # Ã… - 0xC6: b"\xc3\x86", # Æ - 0xC7: b"\xc3\x87", # Ç - 0xC8: b"\xc3\x88", # È - 0xC9: b"\xc3\x89", # É - 0xCA: b"\xc3\x8a", # Ê - 0xCB: b"\xc3\x8b", # Ë - 0xCC: b"\xc3\x8c", # ÃŒ - 0xCD: b"\xc3\x8d", # à - 0xCE: b"\xc3\x8e", # ÃŽ - 0xCF: b"\xc3\x8f", # à - 0xD0: b"\xc3\x90", # à - 0xD1: b"\xc3\x91", # Ñ - 0xD2: b"\xc3\x92", # Ã’ - 0xD3: b"\xc3\x93", # Ó - 0xD4: b"\xc3\x94", # Ô - 0xD5: b"\xc3\x95", # Õ - 0xD6: b"\xc3\x96", # Ö - 0xD7: b"\xc3\x97", # × - 0xD8: b"\xc3\x98", # Ø - 0xD9: b"\xc3\x99", # Ù - 0xDA: b"\xc3\x9a", # Ú - 0xDB: b"\xc3\x9b", # Û - 0xDC: b"\xc3\x9c", # Ü - 0xDD: b"\xc3\x9d", # à - 0xDE: b"\xc3\x9e", # Þ - 0xDF: b"\xc3\x9f", # ß - 0xE0: b"\xc3\xa0", # à - 0xE1: b"\xa1", # á - 0xE2: b"\xc3\xa2", # â - 0xE3: b"\xc3\xa3", # ã - 0xE4: b"\xc3\xa4", # ä - 0xE5: b"\xc3\xa5", # Ã¥ - 0xE6: b"\xc3\xa6", # æ - 0xE7: b"\xc3\xa7", # ç - 0xE8: b"\xc3\xa8", # è - 0xE9: b"\xc3\xa9", # é - 0xEA: b"\xc3\xaa", # ê - 0xEB: b"\xc3\xab", # ë - 0xEC: b"\xc3\xac", # ì - 0xED: b"\xc3\xad", # í - 0xEE: b"\xc3\xae", # î - 0xEF: b"\xc3\xaf", # ï - 0xF0: b"\xc3\xb0", # ð - 0xF1: b"\xc3\xb1", # ñ - 0xF2: b"\xc3\xb2", # ò - 0xF3: b"\xc3\xb3", # ó - 0xF4: b"\xc3\xb4", # ô - 0xF5: b"\xc3\xb5", # õ - 0xF6: b"\xc3\xb6", # ö - 0xF7: b"\xc3\xb7", # ÷ - 0xF8: b"\xc3\xb8", # ø - 0xF9: b"\xc3\xb9", # ù - 0xFA: b"\xc3\xba", # ú - 0xFB: b"\xc3\xbb", # û - 0xFC: b"\xc3\xbc", # ü - 0xFD: b"\xc3\xbd", # ý - 0xFE: b"\xc3\xbe", # þ - } - - #: :meta private: - MULTIBYTE_MARKERS_AND_SIZES: List[Tuple[int, int, int]] = [ - (0xC2, 0xDF, 2), # 2-byte characters start with a byte C2-DF - (0xE0, 0xEF, 3), # 3-byte characters start with E0-EF - (0xF0, 0xF4, 4), # 4-byte characters start with F0-F4 - ] - - #: :meta private: - FIRST_MULTIBYTE_MARKER: int = MULTIBYTE_MARKERS_AND_SIZES[0][0] - - #: :meta private: - LAST_MULTIBYTE_MARKER: int = MULTIBYTE_MARKERS_AND_SIZES[-1][1] - - @classmethod - def detwingle( - cls, - in_bytes: bytes, - main_encoding: _Encoding = "utf8", - embedded_encoding: _Encoding = "windows-1252", - ) -> bytes: - """Fix characters from one encoding embedded in some other encoding. - - Currently the only situation supported is Windows-1252 (or its - subset ISO-8859-1), embedded in UTF-8. - - :param in_bytes: A bytestring that you suspect contains - characters from multiple encodings. Note that this *must* - be a bytestring. If you've already converted the document - to Unicode, you're too late. - :param main_encoding: The primary encoding of ``in_bytes``. - :param embedded_encoding: The encoding that was used to embed characters - in the main document. - :return: A bytestring similar to ``in_bytes``, in which - ``embedded_encoding`` characters have been converted to - their ``main_encoding`` equivalents. - """ - if embedded_encoding.replace("_", "-").lower() not in ( - "windows-1252", - "windows_1252", - ): - raise NotImplementedError( - "Windows-1252 and ISO-8859-1 are the only currently supported " - "embedded encodings." - ) - - if main_encoding.lower() not in ("utf8", "utf-8"): - raise NotImplementedError( - "UTF-8 is the only currently supported main encoding." - ) - - byte_chunks = [] - - chunk_start = 0 - pos = 0 - while pos < len(in_bytes): - byte = in_bytes[pos] - if byte >= cls.FIRST_MULTIBYTE_MARKER and byte <= cls.LAST_MULTIBYTE_MARKER: - # This is the start of a UTF-8 multibyte character. Skip - # to the end. - for start, end, size in cls.MULTIBYTE_MARKERS_AND_SIZES: - if byte >= start and byte <= end: - pos += size - break - elif byte >= 0x80 and byte in cls.WINDOWS_1252_TO_UTF8: - # We found a Windows-1252 character! - # Save the string up to this point as a chunk. - byte_chunks.append(in_bytes[chunk_start:pos]) - - # Now translate the Windows-1252 character into UTF-8 - # and add it as another, one-byte chunk. - byte_chunks.append(cls.WINDOWS_1252_TO_UTF8[byte]) - pos += 1 - chunk_start = pos - else: - # Go on to the next character. - pos += 1 - if chunk_start == 0: - # The string is unchanged. - return in_bytes - else: - # Store the final chunk. - byte_chunks.append(in_bytes[chunk_start:]) - return b"".join(byte_chunks) diff --git a/.venv/Lib/site-packages/bs4/diagnose.py b/.venv/Lib/site-packages/bs4/diagnose.py deleted file mode 100644 index e0fbbc4..0000000 --- a/.venv/Lib/site-packages/bs4/diagnose.py +++ /dev/null @@ -1,268 +0,0 @@ -"""Diagnostic functions, mainly for use when doing tech support.""" - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -import cProfile -from io import BytesIO -from html.parser import HTMLParser -import bs4 -from bs4 import BeautifulSoup, __version__ -from bs4.builder import builder_registry -from typing import ( - Any, - IO, - List, - Optional, - Tuple, - TYPE_CHECKING, -) - -if TYPE_CHECKING: - from bs4._typing import _IncomingMarkup - -import pstats -import random -import tempfile -import time -import traceback -import sys - - -def diagnose(data: "_IncomingMarkup") -> None: - """Diagnostic suite for isolating common problems. - - :param data: Some markup that needs to be explained. - :return: None; diagnostics are printed to standard output. - """ - print(("Diagnostic running on Beautiful Soup %s" % __version__)) - print(("Python version %s" % sys.version)) - - basic_parsers = ["html.parser", "html5lib", "lxml"] - for name in basic_parsers: - for builder in builder_registry.builders: - if name in builder.features: - break - else: - basic_parsers.remove(name) - print( - ("I noticed that %s is not installed. Installing it may help." % name) - ) - - if "lxml" in basic_parsers: - basic_parsers.append("lxml-xml") - try: - from lxml import etree - - print(("Found lxml version %s" % ".".join(map(str, etree.LXML_VERSION)))) - except ImportError: - print("lxml is not installed or couldn't be imported.") - - if "html5lib" in basic_parsers: - try: - import html5lib - - print(("Found html5lib version %s" % html5lib.__version__)) - except ImportError: - print("html5lib is not installed or couldn't be imported.") - - if hasattr(data, "read"): - data = data.read() - - for parser in basic_parsers: - print(("Trying to parse your markup with %s" % parser)) - success = False - try: - soup = BeautifulSoup(data, features=parser) - success = True - except Exception: - print(("%s could not parse the markup." % parser)) - traceback.print_exc() - if success: - print(("Here's what %s did with the markup:" % parser)) - print((soup.prettify())) - - print(("-" * 80)) - - -def lxml_trace(data: "_IncomingMarkup", html: bool = True, **kwargs: Any) -> None: - """Print out the lxml events that occur during parsing. - - This lets you see how lxml parses a document when no Beautiful - Soup code is running. You can use this to determine whether - an lxml-specific problem is in Beautiful Soup's lxml tree builders - or in lxml itself. - - :param data: Some markup. - :param html: If True, markup will be parsed with lxml's HTML parser. - if False, lxml's XML parser will be used. - """ - from lxml import etree - - recover = kwargs.pop("recover", True) - if isinstance(data, str): - data = data.encode("utf8") - if not isinstance(data, IO): - reader = BytesIO(data) - for event, element in etree.iterparse(reader, html=html, recover=recover, **kwargs): - print(("%s, %4s, %s" % (event, element.tag, element.text))) - - -class AnnouncingParser(HTMLParser): - """Subclass of HTMLParser that announces parse events, without doing - anything else. - - You can use this to get a picture of how html.parser sees a given - document. The easiest way to do this is to call `htmlparser_trace`. - """ - - def _p(self, s: str) -> None: - print(s) - - def handle_starttag( - self, - name: str, - attrs: List[Tuple[str, Optional[str]]], - handle_empty_element: bool = True, - ) -> None: - self._p(f"{name} {attrs} START") - - def handle_endtag(self, name: str, check_already_closed: bool = True) -> None: - self._p("%s END" % name) - - def handle_data(self, data: str) -> None: - self._p("%s DATA" % data) - - def handle_charref(self, name: str) -> None: - self._p("%s CHARREF" % name) - - def handle_entityref(self, name: str) -> None: - self._p("%s ENTITYREF" % name) - - def handle_comment(self, data: str) -> None: - self._p("%s COMMENT" % data) - - def handle_decl(self, data: str) -> None: - self._p("%s DECL" % data) - - def unknown_decl(self, data: str) -> None: - self._p("%s UNKNOWN-DECL" % data) - - def handle_pi(self, data: str) -> None: - self._p("%s PI" % data) - - -def htmlparser_trace(data: str) -> None: - """Print out the HTMLParser events that occur during parsing. - - This lets you see how HTMLParser parses a document when no - Beautiful Soup code is running. - - :param data: Some markup. - """ - parser = AnnouncingParser() - parser.feed(data) - - -_vowels: str = "aeiou" -_consonants: str = "bcdfghjklmnpqrstvwxyz" - - -def rword(length: int = 5) -> str: - """Generate a random word-like string. - - :meta private: - """ - s = "" - for i in range(length): - if i % 2 == 0: - t = _consonants - else: - t = _vowels - s += random.choice(t) - return s - - -def rsentence(length: int = 4) -> str: - """Generate a random sentence-like string. - - :meta private: - """ - return " ".join(rword(random.randint(4, 9)) for i in range(length)) - - -def rdoc(num_elements: int = 1000) -> str: - """Randomly generate an invalid HTML document. - - :meta private: - """ - tag_names = ["p", "div", "span", "i", "b", "script", "table"] - elements = [] - for i in range(num_elements): - choice = random.randint(0, 3) - if choice == 0: - # New tag. - tag_name = random.choice(tag_names) - elements.append("<%s>" % tag_name) - elif choice == 1: - elements.append(rsentence(random.randint(1, 4))) - elif choice == 2: - # Close a tag. - tag_name = random.choice(tag_names) - elements.append("" % tag_name) - return "" + "\n".join(elements) + "" - - -def benchmark_parsers(num_elements: int = 100000) -> None: - """Very basic head-to-head performance benchmark.""" - print(("Comparative parser benchmark on Beautiful Soup %s" % __version__)) - data = rdoc(num_elements) - print(("Generated a large invalid HTML document (%d bytes)." % len(data))) - - for parser_name in ["lxml", ["lxml", "html"], "html5lib", "html.parser"]: - success = False - try: - a = time.time() - BeautifulSoup(data, parser_name) - b = time.time() - success = True - except Exception: - print(("%s could not parse the markup." % parser_name)) - traceback.print_exc() - if success: - print(("BS4+%s parsed the markup in %.2fs." % (parser_name, b - a))) - - from lxml import etree - - a = time.time() - etree.HTML(data) - b = time.time() - print(("Raw lxml parsed the markup in %.2fs." % (b - a))) - - import html5lib - - parser = html5lib.HTMLParser() - a = time.time() - parser.parse(data) - b = time.time() - print(("Raw html5lib parsed the markup in %.2fs." % (b - a))) - - -def profile(num_elements: int = 100000, parser: str = "lxml") -> None: - """Use Python's profiler on a randomly generated document.""" - filehandle = tempfile.NamedTemporaryFile() - filename = filehandle.name - - data = rdoc(num_elements) - vars = dict(bs4=bs4, data=data, parser=parser) - cProfile.runctx("bs4.BeautifulSoup(data, parser)", vars, vars, filename) - - stats = pstats.Stats(filename) - # stats.strip_dirs() - stats.sort_stats("cumulative") - stats.print_stats("_html5lib|bs4", 50) - - -# If this file is run as a script, standard input is diagnosed. -if __name__ == "__main__": - diagnose(sys.stdin.read()) diff --git a/.venv/Lib/site-packages/bs4/element.py b/.venv/Lib/site-packages/bs4/element.py deleted file mode 100644 index caafbdb..0000000 --- a/.venv/Lib/site-packages/bs4/element.py +++ /dev/null @@ -1,2894 +0,0 @@ -from __future__ import annotations - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -import re -import warnings - -from bs4.css import CSS -from bs4._deprecation import ( - _deprecated, - _deprecated_alias, - _deprecated_function_alias, -) -from bs4.formatter import ( - Formatter, - HTMLFormatter, - XMLFormatter, -) -from bs4._warnings import AttributeResemblesVariableWarning - -from typing import ( - Any, - Callable, - Dict, - Generic, - Iterable, - Iterator, - List, - Mapping, - Optional, - Pattern, - Set, - TYPE_CHECKING, - Tuple, - Type, - TypeVar, - Union, - cast, -) -from typing_extensions import ( - Self, - TypeAlias, -) - -if TYPE_CHECKING: - from bs4 import BeautifulSoup - from bs4.builder import TreeBuilder - from bs4.filter import ElementFilter - from bs4.formatter import ( - _EntitySubstitutionFunction, - _FormatterOrName, - ) - from bs4._typing import ( - _AtMostOneElement, - _AttributeValue, - _AttributeValues, - _Encoding, - _InsertableElement, - _OneElement, - _QueryResults, - _RawOrProcessedAttributeValues, - _StrainableElement, - _StrainableAttribute, - _StrainableAttributes, - _StrainableString, - ) - -_OneOrMoreStringTypes: TypeAlias = Union[ - Type["NavigableString"], Iterable[Type["NavigableString"]] -] - -_FindMethodName: TypeAlias = Optional[Union["_StrainableElement", "ElementFilter"]] - -# Deprecated module-level attributes. -# See https://peps.python.org/pep-0562/ -_deprecated_names = dict( - whitespace_re="The {name} attribute was deprecated in version 4.7.0. If you need it, make your own copy." -) -#: :meta private: -_deprecated_whitespace_re: Pattern[str] = re.compile(r"\s+") - - -def __getattr__(name: str) -> Any: - if name in _deprecated_names: - message = _deprecated_names[name] - warnings.warn(message.format(name=name), DeprecationWarning, stacklevel=2) - - return globals()[f"_deprecated_{name}"] - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") - - -#: Documents output by Beautiful Soup will be encoded with -#: this encoding unless you specify otherwise. -DEFAULT_OUTPUT_ENCODING: str = "utf-8" - -#: A regular expression that can be used to split on whitespace. -nonwhitespace_re: Pattern[str] = re.compile(r"\S+") - -#: These encodings are recognized by Python (so `Tag.encode` -#: could theoretically support them) but XML and HTML don't recognize -#: them (so they should not show up in an XML or HTML document as that -#: document's encoding). -#: -#: If an XML document is encoded in one of these encodings, no encoding -#: will be mentioned in the XML declaration. If an HTML document is -#: encoded in one of these encodings, and the HTML document has a -#: tag that mentions an encoding, the encoding will be given as -#: the empty string. -#: -#: Source: -#: Python documentation, `Python Specific Encodings `_ -PYTHON_SPECIFIC_ENCODINGS: Set[_Encoding] = set( - [ - "idna", - "mbcs", - "oem", - "palmos", - "punycode", - "raw_unicode_escape", - "undefined", - "unicode_escape", - "raw-unicode-escape", - "unicode-escape", - "string-escape", - "string_escape", - ] -) - - -class NamespacedAttribute(str): - """A namespaced attribute (e.g. the 'xml:lang' in 'xml:lang="en"') - which remembers the namespace prefix ('xml') and the name ('lang') - that were used to create it. - """ - - prefix: Optional[str] - name: Optional[str] - namespace: Optional[str] - - def __new__( - cls, - prefix: Optional[str], - name: Optional[str] = None, - namespace: Optional[str] = None, - ) -> Self: - if not name: - # This is the default namespace. Its name "has no value" - # per https://www.w3.org/TR/xml-names/#defaulting - name = None - - if not name: - obj = str.__new__(cls, prefix) - elif not prefix: - # Not really namespaced. - obj = str.__new__(cls, name) - else: - obj = str.__new__(cls, prefix + ":" + name) - obj.prefix = prefix - obj.name = name - obj.namespace = namespace - return obj - - -class AttributeValueWithCharsetSubstitution(str): - """An abstract class standing in for a character encoding specified - inside an HTML ```` tag. - - Subclasses exist for each place such a character encoding might be - found: either inside the ``charset`` attribute - (`CharsetMetaAttributeValue`) or inside the ``content`` attribute - (`ContentMetaAttributeValue`) - - This allows Beautiful Soup to replace that part of the HTML file - with a different encoding when ouputting a tree as a string. - """ - - # The original, un-encoded value of the ``content`` attribute. - #: :meta private: - original_value: str - - def substitute_encoding(self, eventual_encoding: str) -> str: - """Do whatever's necessary in this implementation-specific - portion an HTML document to substitute in a specific encoding. - """ - raise NotImplementedError() - - -class CharsetMetaAttributeValue(AttributeValueWithCharsetSubstitution): - """A generic stand-in for the value of a ```` tag's ``charset`` - attribute. - - When Beautiful Soup parses the markup ````, the - value of the ``charset`` attribute will become one of these objects. - - If the document is later encoded to an encoding other than UTF-8, its - ```` tag will mention the new encoding instead of ``utf8``. - """ - - def __new__(cls, original_value: str) -> Self: - # We don't need to use the original value for anything, but - # it might be useful for the user to know. - obj = str.__new__(cls, original_value) - obj.original_value = original_value - return obj - - def substitute_encoding(self, eventual_encoding: _Encoding = "utf-8") -> str: - """When an HTML document is being encoded to a given encoding, the - value of a ```` tag's ``charset`` becomes the name of - the encoding. - """ - if eventual_encoding in PYTHON_SPECIFIC_ENCODINGS: - return "" - return eventual_encoding - - -class AttributeValueList(List[str]): - """Class for the list used to hold the values of attributes which - have multiple values (such as HTML's 'class'). It's just a regular - list, but you can subclass it and pass it in to the TreeBuilder - constructor as attribute_value_list_class, to have your subclass - instantiated instead. - """ - - -class AttributeDict(Dict[Any,Any]): - """Superclass for the dictionary used to hold a tag's - attributes. You can use this, but it's just a regular dict with no - special logic. - """ - - -class XMLAttributeDict(AttributeDict): - """A dictionary for holding a Tag's attributes, which processes - incoming values for consistency with the HTML spec. - """ - - def __setitem__(self, key: str, value: Any) -> None: - """Set an attribute value, possibly modifying it to comply with - the XML spec. - - This just means converting common non-string values to - strings: XML attributes may have "any literal string as a - value." - """ - if value is None: - value = "" - if isinstance(value, bool): - # XML does not define any rules for boolean attributes. - # Preserve the old Beautiful Soup behavior (a bool that - # gets converted to a string on output) rather than - # guessing what the value should be. - pass - elif isinstance(value, (int, float)): - # It's dangerous to convert _every_ attribute value into a - # plain string, since an attribute value may be a more - # sophisticated string-like object - # (e.g. CharsetMetaAttributeValue). But we can definitely - # convert numeric values and booleans, which are the most common. - value = str(value) - - super().__setitem__(key, value) - - -class HTMLAttributeDict(AttributeDict): - """A dictionary for holding a Tag's attributes, which processes - incoming values for consistency with the HTML spec, which says - 'Attribute values are a mixture of text and character - references...' - - Basically, this means converting common non-string values into - strings, like XMLAttributeDict, though HTML also has some rules - around boolean attributes that XML doesn't have. - """ - - def __setitem__(self, key: str, value: Any) -> None: - """Set an attribute value, possibly modifying it to comply - with the HTML spec, - """ - if value in (False, None): - # 'The values "true" and "false" are not allowed on - # boolean attributes. To represent a false value, the - # attribute has to be omitted altogether.' - if key in self: - del self[key] - return - if isinstance(value, bool): - # 'If the [boolean] attribute is present, its value must - # either be the empty string or a value that is an ASCII - # case-insensitive match for the attribute's canonical - # name, with no leading or trailing whitespace.' - # - # [fixme] It's not clear to me whether "canonical name" - # means fully-qualified name, unqualified name, or - # (probably not) name with namespace prefix. For now I'm - # going with unqualified name. - if isinstance(key, NamespacedAttribute): - value = key.name - else: - value = key - elif isinstance(value, (int, float)): - # See note in XMLAttributeDict for the reasoning why we - # only do this to numbers. - value = str(value) - super().__setitem__(key, value) - - -class ContentMetaAttributeValue(AttributeValueWithCharsetSubstitution): - """A generic stand-in for the value of a ```` tag's ``content`` - attribute. - - When Beautiful Soup parses the markup: - ```` - - The value of the ``content`` attribute will become one of these objects. - - If the document is later encoded to an encoding other than UTF-8, its - ```` tag will mention the new encoding instead of ``utf8``. - """ - - #: Match the 'charset' argument inside the 'content' attribute - #: of a tag. - #: :meta private: - CHARSET_RE: Pattern[str] = re.compile(r"((^|;)\s*charset=)([^;]*)", re.M) - - def __new__(cls, original_value: str) -> Self: - cls.CHARSET_RE.search(original_value) - obj = str.__new__(cls, original_value) - obj.original_value = original_value - return obj - - def substitute_encoding(self, eventual_encoding: _Encoding = "utf-8") -> str: - """When an HTML document is being encoded to a given encoding, the - value of the ``charset=`` in a ```` tag's ``content`` becomes - the name of the encoding. - """ - if eventual_encoding in PYTHON_SPECIFIC_ENCODINGS: - return self.CHARSET_RE.sub("", self.original_value) - - def rewrite(match: re.Match[str]) -> str: - return match.group(1) + eventual_encoding - - return self.CHARSET_RE.sub(rewrite, self.original_value) - - -class PageElement(object): - """An abstract class representing a single element in the parse tree. - - `NavigableString`, `Tag`, etc. are all subclasses of - `PageElement`. For this reason you'll see a lot of methods that - return `PageElement`, but you'll never see an actual `PageElement` - object. For the most part you can think of `PageElement` as - meaning "a `Tag` or a `NavigableString`." - """ - - #: In general, we can't tell just by looking at an element whether - #: it's contained in an XML document or an HTML document. But for - #: `Tag` objects (q.v.) we can store this information at parse time. - #: :meta private: - known_xml: Optional[bool] = None - - #: Whether or not this element has been decomposed from the tree - #: it was created in. - _decomposed: bool - - parent: Optional[Tag] - next_element: _AtMostOneElement - previous_element: _AtMostOneElement - next_sibling: _AtMostOneElement - previous_sibling: _AtMostOneElement - - #: Whether or not this element is hidden from generated output. - #: Only the `BeautifulSoup` object itself is hidden. - hidden: bool = False - - def setup( - self, - parent: Optional[Tag] = None, - previous_element: _AtMostOneElement = None, - next_element: _AtMostOneElement = None, - previous_sibling: _AtMostOneElement = None, - next_sibling: _AtMostOneElement = None, - ) -> None: - """Sets up the initial relations between this element and - other elements. - - :param parent: The parent of this element. - - :param previous_element: The element parsed immediately before - this one. - - :param next_element: The element parsed immediately after - this one. - - :param previous_sibling: The most recently encountered element - on the same level of the parse tree as this one. - - :param previous_sibling: The next element to be encountered - on the same level of the parse tree as this one. - """ - self.parent = parent - - self.previous_element = previous_element - if self.previous_element is not None: - self.previous_element.next_element = self - - self.next_element = next_element - if self.next_element is not None: - self.next_element.previous_element = self - - self.next_sibling = next_sibling - if self.next_sibling is not None: - self.next_sibling.previous_sibling = self - - if ( - previous_sibling is None - and self.parent is not None - and self.parent.contents - ): - previous_sibling = self.parent.contents[-1] - - self.previous_sibling = previous_sibling - if self.previous_sibling is not None: - self.previous_sibling.next_sibling = self - - def format_string(self, s: str, formatter: Optional[_FormatterOrName]) -> str: - """Format the given string using the given formatter. - - :param s: A string. - :param formatter: A Formatter object, or a string naming one of the standard formatters. - """ - if formatter is None: - return s - if not isinstance(formatter, Formatter): - formatter = self.formatter_for_name(formatter) - output = formatter.substitute(s) - return output - - def formatter_for_name( - self, formatter_name: Union[_FormatterOrName, _EntitySubstitutionFunction] - ) -> Formatter: - """Look up or create a Formatter for the given identifier, - if necessary. - - :param formatter: Can be a `Formatter` object (used as-is), a - function (used as the entity substitution hook for an - `bs4.formatter.XMLFormatter` or - `bs4.formatter.HTMLFormatter`), or a string (used to look - up an `bs4.formatter.XMLFormatter` or - `bs4.formatter.HTMLFormatter` in the appropriate registry. - - """ - if isinstance(formatter_name, Formatter): - return formatter_name - c: type[Formatter] - registry: Mapping[Optional[str], Formatter] - if self._is_xml: - c = XMLFormatter - registry = XMLFormatter.REGISTRY - else: - c = HTMLFormatter - registry = HTMLFormatter.REGISTRY - if callable(formatter_name): - return c(entity_substitution=formatter_name) - return registry[formatter_name] - - @property - def _is_xml(self) -> bool: - """Is this element part of an XML tree or an HTML tree? - - This is used in formatter_for_name, when deciding whether an - XMLFormatter or HTMLFormatter is more appropriate. It can be - inefficient, but it should be called very rarely. - """ - if self.known_xml is not None: - # Most of the time we will have determined this when the - # document is parsed. - return self.known_xml - - # Otherwise, it's likely that this element was created by - # direct invocation of the constructor from within the user's - # Python code. - if self.parent is None: - # This is the top-level object. It should have .known_xml set - # from tree creation. If not, take a guess--BS is usually - # used on HTML markup. - return getattr(self, "is_xml", False) - return self.parent._is_xml - - nextSibling = _deprecated_alias("nextSibling", "next_sibling", "4.0.0") - previousSibling = _deprecated_alias("previousSibling", "previous_sibling", "4.0.0") - - def __deepcopy__(self, memo: Dict[Any, Any], recursive: bool = False) -> Self: - raise NotImplementedError() - - def __copy__(self) -> Self: - """A copy of a PageElement can only be a deep copy, because - only one PageElement can occupy a given place in a parse tree. - """ - return self.__deepcopy__({}) - - default: Iterable[type[NavigableString]] = tuple() #: :meta private: - - def _all_strings( - self, strip: bool = False, types: Iterable[type[NavigableString]] = default - ) -> Iterator[str]: - """Yield all strings of certain classes, possibly stripping them. - - This is implemented differently in `Tag` and `NavigableString`. - """ - raise NotImplementedError() - - @property - def stripped_strings(self) -> Iterator[str]: - """Yield all interesting strings in this PageElement, stripping them - first. - - See `Tag` for information on which strings are considered - interesting in a given context. - """ - for string in self._all_strings(True): - yield string - - def get_text( - self, - separator: str = "", - strip: bool = False, - types: Iterable[Type[NavigableString]] = default, - ) -> str: - """Get all child strings of this PageElement, concatenated using the - given separator. - - :param separator: Strings will be concatenated using this separator. - - :param strip: If True, strings will be stripped before being - concatenated. - - :param types: A tuple of NavigableString subclasses. Any - strings of a subclass not found in this list will be - ignored. Although there are exceptions, the default - behavior in most cases is to consider only NavigableString - and CData objects. That means no comments, processing - instructions, etc. - - :return: A string. - """ - return separator.join([s for s in self._all_strings(strip, types=types)]) - - getText = get_text - text = property(get_text) - - def replace_with(self, *args: PageElement) -> Self: - """Replace this `PageElement` with one or more other `PageElement`, - objects, keeping the rest of the tree the same. - - :return: This `PageElement`, no longer part of the tree. - """ - if self.parent is None: - raise ValueError( - "Cannot replace one element with another when the " - "element to be replaced is not part of a tree." - ) - if len(args) == 1 and args[0] is self: - # Replacing an element with itself is a no-op. - return self - if any(x is self.parent for x in args): - raise ValueError("Cannot replace a Tag with its parent.") - old_parent = self.parent - my_index = self.parent.index(self) - self.extract(_self_index=my_index) - for idx, replace_with in enumerate(args, start=my_index): - old_parent.insert(idx, replace_with) - return self - - replaceWith = _deprecated_function_alias("replaceWith", "replace_with", "4.0.0") - - def wrap(self, wrap_inside: Tag) -> Tag: - """Wrap this `PageElement` inside a `Tag`. - - :return: ``wrap_inside``, occupying the position in the tree that used - to be occupied by this object, and with this object now inside it. - """ - me = self.replace_with(wrap_inside) - wrap_inside.append(me) - return wrap_inside - - def extract(self, _self_index: Optional[int] = None) -> Self: - """Destructively rips this element out of the tree. - - :param _self_index: The location of this element in its parent's - .contents, if known. Passing this in allows for a performance - optimization. - - :return: this `PageElement`, no longer part of the tree. - """ - if self.parent is not None: - if _self_index is None: - _self_index = self.parent.index(self) - del self.parent.contents[_self_index] - - # Find the two elements that would be next to each other if - # this element (and any children) hadn't been parsed. Connect - # the two. - last_child = self._last_descendant() - - # last_child can't be None because we passed accept_self=True - # into _last_descendant. Worst case, last_child will be - # self. Making this cast removes several mypy complaints later - # on as we manipulate last_child. - last_child = cast(PageElement, last_child) - next_element = last_child.next_element - - if self.previous_element is not None: - if self.previous_element is not next_element: - self.previous_element.next_element = next_element - if next_element is not None and next_element is not self.previous_element: - next_element.previous_element = self.previous_element - self.previous_element = None - last_child.next_element = None - - self.parent = None - if ( - self.previous_sibling is not None - and self.previous_sibling is not self.next_sibling - ): - self.previous_sibling.next_sibling = self.next_sibling - if ( - self.next_sibling is not None - and self.next_sibling is not self.previous_sibling - ): - self.next_sibling.previous_sibling = self.previous_sibling - self.previous_sibling = self.next_sibling = None - return self - - def decompose(self) -> None: - """Recursively destroys this `PageElement` and its children. - - The element will be removed from the tree and wiped out; so - will everything beneath it. - - The behavior of a decomposed `PageElement` is undefined and you - should never use one for anything, but if you need to *check* - whether an element has been decomposed, you can use the - `PageElement.decomposed` property. - """ - self.extract() - e: _AtMostOneElement = self - next_up: _AtMostOneElement = None - while e is not None: - next_up = e.next_element - e.__dict__.clear() - if isinstance(e, Tag): - e.contents = [] - e._decomposed = True - e = next_up - - def _last_descendant( - self, is_initialized: bool = True, accept_self: bool = True - ) -> _AtMostOneElement: - """Finds the last element beneath this object to be parsed. - - Special note to help you figure things out if your type - checking is tripped up by the fact that this method returns - _AtMostOneElement instead of PageElement: the only time - this method returns None is if `accept_self` is False and the - `PageElement` has no children--either it's a NavigableString - or an empty Tag. - - :param is_initialized: Has `PageElement.setup` been called on - this `PageElement` yet? - - :param accept_self: Is ``self`` an acceptable answer to the - question? - """ - if is_initialized and self.next_sibling is not None: - last_child = self.next_sibling.previous_element - else: - last_child = self - while isinstance(last_child, Tag) and last_child.contents: - last_child = last_child.contents[-1] - if not accept_self and last_child is self: - last_child = None - return last_child - - _lastRecursiveChild = _deprecated_alias( - "_lastRecursiveChild", "_last_descendant", "4.0.0" - ) - - def insert_before(self, *args: _InsertableElement) -> List[PageElement]: - """Makes the given element(s) the immediate predecessor of this one. - - All the elements will have the same `PageElement.parent` as - this one, and the given elements will occur immediately before - this one. - - :param args: One or more PageElements. - - :return The list of PageElements that were inserted. - """ - parent = self.parent - if parent is None: - raise ValueError("Element has no parent, so 'before' has no meaning.") - if any(x is self for x in args): - raise ValueError("Can't insert an element before itself.") - results: List[PageElement] = [] - for predecessor in args: - # Extract first so that the index won't be screwed up if they - # are siblings. - if isinstance(predecessor, PageElement): - predecessor.extract() - index = parent.index(self) - results.extend(parent.insert(index, predecessor)) - - return results - - def insert_after(self, *args: _InsertableElement) -> List[PageElement]: - """Makes the given element(s) the immediate successor of this one. - - The elements will have the same `PageElement.parent` as this - one, and the given elements will occur immediately after this - one. - - :param args: One or more PageElements. - - :return The list of PageElements that were inserted. - """ - # Do all error checking before modifying the tree. - parent = self.parent - if parent is None: - raise ValueError("Element has no parent, so 'after' has no meaning.") - if any(x is self for x in args): - raise ValueError("Can't insert an element after itself.") - - offset = 0 - results: List[PageElement] = [] - for successor in args: - # Extract first so that the index won't be screwed up if they - # are siblings. - if isinstance(successor, PageElement): - successor.extract() - index = parent.index(self) - results.extend(parent.insert(index + 1 + offset, successor)) - offset += 1 - - return results - - def find_next( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - """Find the first PageElement that matches the given criteria and - appears later in the document than this PageElement. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a NavigableString with specific text. - :kwargs: Additional filters on attribute values. - """ - return self._find_one(self.find_all_next, name, attrs, string, **kwargs) - - findNext = _deprecated_function_alias("findNext", "find_next", "4.0.0") - - def find_all_next( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - limit: Optional[int] = None, - _stacklevel: int = 2, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Find all `PageElement` objects that match the given criteria and - appear later in the document than this `PageElement`. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a NavigableString with specific text. - :param limit: Stop looking after finding this many results. - :param _stacklevel: Used internally to improve warning messages. - :kwargs: Additional filters on attribute values. - """ - return self._find_all( - name, - attrs, - string, - limit, - self.next_elements, - _stacklevel=_stacklevel + 1, - **kwargs, - ) - - findAllNext = _deprecated_function_alias("findAllNext", "find_all_next", "4.0.0") - - def find_next_sibling( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - """Find the closest sibling to this PageElement that matches the - given criteria and appears later in the document. - - All find_* methods take a common set of arguments. See the - online documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a `NavigableString` with specific text. - :kwargs: Additional filters on attribute values. - """ - return self._find_one(self.find_next_siblings, name, attrs, string, **kwargs) - - findNextSibling = _deprecated_function_alias( - "findNextSibling", "find_next_sibling", "4.0.0" - ) - - def find_next_siblings( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - limit: Optional[int] = None, - _stacklevel: int = 2, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Find all siblings of this `PageElement` that match the given criteria - and appear later in the document. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a `NavigableString` with specific text. - :param limit: Stop looking after finding this many results. - :param _stacklevel: Used internally to improve warning messages. - :kwargs: Additional filters on attribute values. - """ - return self._find_all( - name, - attrs, - string, - limit, - self.next_siblings, - _stacklevel=_stacklevel + 1, - **kwargs, - ) - - findNextSiblings = _deprecated_function_alias( - "findNextSiblings", "find_next_siblings", "4.0.0" - ) - fetchNextSiblings = _deprecated_function_alias( - "fetchNextSiblings", "find_next_siblings", "3.0.0" - ) - - def find_previous( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - """Look backwards in the document from this `PageElement` and find the - first `PageElement` that matches the given criteria. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a `NavigableString` with specific text. - :kwargs: Additional filters on attribute values. - """ - return self._find_one(self.find_all_previous, name, attrs, string, **kwargs) - - findPrevious = _deprecated_function_alias("findPrevious", "find_previous", "3.0.0") - - def find_all_previous( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - limit: Optional[int] = None, - _stacklevel: int = 2, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Look backwards in the document from this `PageElement` and find all - `PageElement` that match the given criteria. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a `NavigableString` with specific text. - :param limit: Stop looking after finding this many results. - :param _stacklevel: Used internally to improve warning messages. - :kwargs: Additional filters on attribute values. - """ - return self._find_all( - name, - attrs, - string, - limit, - self.previous_elements, - _stacklevel=_stacklevel + 1, - **kwargs, - ) - - findAllPrevious = _deprecated_function_alias( - "findAllPrevious", "find_all_previous", "4.0.0" - ) - fetchAllPrevious = _deprecated_function_alias( - "fetchAllPrevious", "find_all_previous", "3.0.0" - ) - - def find_previous_sibling( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - """Returns the closest sibling to this `PageElement` that matches the - given criteria and appears earlier in the document. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a `NavigableString` with specific text. - :kwargs: Additional filters on attribute values. - """ - return self._find_one( - self.find_previous_siblings, name, attrs, string, **kwargs - ) - - findPreviousSibling = _deprecated_function_alias( - "findPreviousSibling", "find_previous_sibling", "4.0.0" - ) - - def find_previous_siblings( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - string: Optional[_StrainableString] = None, - limit: Optional[int] = None, - _stacklevel: int = 2, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Returns all siblings to this PageElement that match the - given criteria and appear earlier in the document. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param string: A filter for a NavigableString with specific text. - :param limit: Stop looking after finding this many results. - :param _stacklevel: Used internally to improve warning messages. - :kwargs: Additional filters on attribute values. - """ - return self._find_all( - name, - attrs, - string, - limit, - self.previous_siblings, - _stacklevel=_stacklevel + 1, - **kwargs, - ) - - findPreviousSiblings = _deprecated_function_alias( - "findPreviousSiblings", "find_previous_siblings", "4.0.0" - ) - fetchPreviousSiblings = _deprecated_function_alias( - "fetchPreviousSiblings", "find_previous_siblings", "3.0.0" - ) - - def find_parent( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - """Find the closest parent of this PageElement that matches the given - criteria. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param self: Whether the PageElement itself should be considered - as one of its 'parents'. - :kwargs: Additional filters on attribute values. - """ - # NOTE: We can't use _find_one because findParents takes a different - # set of arguments. - r = None - results = self.find_parents( - name, attrs, 1, _stacklevel=3, **kwargs - ) - if results: - r = results[0] - return r - - findParent = _deprecated_function_alias("findParent", "find_parent", "4.0.0") - - def find_parents( - self, - name: _FindMethodName = None, - attrs: _StrainableAttributes = {}, - limit: Optional[int] = None, - _stacklevel: int = 2, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Find all parents of this `PageElement` that match the given criteria. - - All find_* methods take a common set of arguments. See the online - documentation for detailed explanations. - - :param name: A filter on tag name. - :param attrs: Additional filters on attribute values. - :param limit: Stop looking after finding this many results. - :param _stacklevel: Used internally to improve warning messages. - :kwargs: Additional filters on attribute values. - """ - iterator = self.parents - return self._find_all( - name, attrs, None, limit, iterator, _stacklevel=_stacklevel + 1, **kwargs - ) - - findParents = _deprecated_function_alias("findParents", "find_parents", "4.0.0") - fetchParents = _deprecated_function_alias("fetchParents", "find_parents", "3.0.0") - - @property - def next(self) -> _AtMostOneElement: - """The `PageElement`, if any, that was parsed just after this one.""" - return self.next_element - - @property - def previous(self) -> _AtMostOneElement: - """The `PageElement`, if any, that was parsed just before this one.""" - return self.previous_element - - # These methods do the real heavy lifting. - - def _find_one( - self, - # TODO-TYPING: "There is no syntax to indicate optional or - # keyword arguments; such function types are rarely used - # as callback types." - So, not sure how to get more - # specific here. - method: Callable, - name: _FindMethodName, - attrs: _StrainableAttributes, - string: Optional[_StrainableString], - **kwargs: _StrainableAttribute, - ) -> _AtMostOneElement: - r: _AtMostOneElement = None - results: _QueryResults = method(name, attrs, string, 1, _stacklevel=4, **kwargs) - if results: - r = results[0] - return r - - def _find_all( - self, - name: _FindMethodName, - attrs: _StrainableAttributes, - string: Optional[_StrainableString], - limit: Optional[int], - generator: Iterator[PageElement], - _stacklevel: int = 3, - **kwargs: _StrainableAttribute, - ) -> _QueryResults: - """Iterates over a generator looking for things that match.""" - - if string is None and "text" in kwargs: - string = kwargs.pop("text") - warnings.warn( - "The 'text' argument to find()-type methods is deprecated. Use 'string' instead.", - DeprecationWarning, - stacklevel=_stacklevel, - ) - - if "_class" in kwargs: - warnings.warn( - AttributeResemblesVariableWarning.MESSAGE - % dict( - original="_class", - autocorrect="class_", - ), - AttributeResemblesVariableWarning, - stacklevel=_stacklevel, - ) - - from bs4.filter import ElementFilter - - if isinstance(name, ElementFilter): - matcher = name - else: - matcher = SoupStrainer(name, attrs, string, **kwargs) - - result: Iterable[_OneElement] - if string is None and not limit and not attrs and not kwargs: - if name is True or name is None: - # Optimization to find all tags. - result = (element for element in generator if isinstance(element, Tag)) - return ResultSet(matcher, result) - elif isinstance(name, str): - # Optimization to find all tags with a given name. - if name.count(":") == 1: - # This is a name with a prefix. If this is a namespace-aware document, - # we need to match the local name against tag.name. If not, - # we need to match the fully-qualified name against tag.name. - prefix, local_name = name.split(":", 1) - else: - prefix = None - local_name = name - result = [] - for element in generator: - if not isinstance(element, Tag): - continue - if element.name == name or ( - element.name == local_name - and (prefix is None or element.prefix == prefix) - ): - result.append(element) - return ResultSet(matcher, result) - return matcher.find_all(generator, limit) - - # These generators can be used to navigate starting from both - # NavigableStrings and Tags. - @property - def next_elements(self) -> Iterator[PageElement]: - """All PageElements that were parsed after this one.""" - i = self.next_element - while i is not None: - successor = i.next_element - yield i - i = successor - - @property - def self_and_next_elements(self) -> Iterator[PageElement]: - """This PageElement, then all PageElements that were parsed after it.""" - return self._self_and(self.next_elements) - - @property - def next_siblings(self) -> Iterator[PageElement]: - """All PageElements that are siblings of this one but were parsed - later. - """ - i = self.next_sibling - while i is not None: - successor = i.next_sibling - yield i - i = successor - - @property - def self_and_next_siblings(self) -> Iterator[PageElement]: - """This PageElement, then all of its siblings.""" - return self._self_and(self.next_siblings) - - @property - def previous_elements(self) -> Iterator[PageElement]: - """All PageElements that were parsed before this one. - - :yield: A sequence of PageElements. - """ - i = self.previous_element - while i is not None: - successor = i.previous_element - yield i - i = successor - - @property - def self_and_previous_elements(self) -> Iterator[PageElement]: - """This PageElement, then all elements that were parsed - earlier.""" - return self._self_and(self.previous_elements) - - @property - def previous_siblings(self) -> Iterator[PageElement]: - """All PageElements that are siblings of this one but were parsed - earlier. - - :yield: A sequence of PageElements. - """ - i = self.previous_sibling - while i is not None: - successor = i.previous_sibling - yield i - i = successor - - @property - def self_and_previous_siblings(self) -> Iterator[PageElement]: - """This PageElement, then all of its siblings that were parsed - earlier.""" - return self._self_and(self.previous_siblings) - - @property - def parents(self) -> Iterator[Tag]: - """All elements that are parents of this PageElement. - - :yield: A sequence of Tags, ending with a BeautifulSoup object. - """ - i = self.parent - while i is not None: - successor = i.parent - yield i - i = successor - - @property - def self_and_parents(self) -> Iterator[PageElement]: - """This element, then all of its parents. - - :yield: A sequence of PageElements, ending with a BeautifulSoup object. - """ - return self._self_and(self.parents) - - def _self_and(self, other_generator:Iterator[PageElement]) -> Iterator[PageElement]: - """Modify a generator by yielding this element, then everything - yielded by the other generator. - """ - if not self.hidden: - yield self - for i in other_generator: - yield i - - @property - def decomposed(self) -> bool: - """Check whether a PageElement has been decomposed.""" - return getattr(self, "_decomposed", False) or False - - @_deprecated("next_elements", "4.0.0") - def nextGenerator(self) -> Iterator[PageElement]: - ":meta private:" - return self.next_elements - - @_deprecated("next_siblings", "4.0.0") - def nextSiblingGenerator(self) -> Iterator[PageElement]: - ":meta private:" - return self.next_siblings - - @_deprecated("previous_elements", "4.0.0") - def previousGenerator(self) -> Iterator[PageElement]: - ":meta private:" - return self.previous_elements - - @_deprecated("previous_siblings", "4.0.0") - def previousSiblingGenerator(self) -> Iterator[PageElement]: - ":meta private:" - return self.previous_siblings - - @_deprecated("parents", "4.0.0") - def parentGenerator(self) -> Iterator[PageElement]: - ":meta private:" - return self.parents - - -class NavigableString(str, PageElement): - """A Python string that is part of a parse tree. - - When Beautiful Soup parses the markup ``penguin``, it will - create a `NavigableString` for the string "penguin". - """ - - #: A string prepended to the body of the 'real' string - #: when formatting it as part of a document, such as the '' - #: in an HTML comment. - SUFFIX: str = "" - - def __new__(cls, value: Union[str, bytes]) -> Self: - """Create a new NavigableString. - - When unpickling a NavigableString, this method is called with - the string in DEFAULT_OUTPUT_ENCODING. That encoding needs to be - passed in to the superclass's __new__ or the superclass won't know - how to handle non-ASCII characters. - """ - if isinstance(value, str): - u = str.__new__(cls, value) - else: - u = str.__new__(cls, value, DEFAULT_OUTPUT_ENCODING) - u.hidden = False - u.setup() - return u - - def __deepcopy__(self, memo: Dict[Any, Any], recursive: bool = False) -> Self: - """A copy of a NavigableString has the same contents and class - as the original, but it is not connected to the parse tree. - - :param recursive: This parameter is ignored; it's only defined - so that NavigableString.__deepcopy__ implements the same - signature as Tag.__deepcopy__. - """ - return type(self)(self) - - def __getnewargs__(self) -> Tuple[str]: - return (str(self),) - - # TODO-TYPING This should be SupportsIndex|slice but SupportsIndex - # is introduced in 3.8. - def __getitem__(self, key: Union[int|slice]) -> str: - """Raise an exception """ - if isinstance(key, str): - raise TypeError("string indices must be integers, not '{0}'. Are you treating a NavigableString like a Tag?".format(key.__class__.__name__)) - return super(NavigableString, self).__getitem__(key) - - @property - def string(self) -> str: - """Convenience property defined to match `Tag.string`. - - :return: This property always returns the `NavigableString` it was - called on. - - :meta private: - """ - return self - - def output_ready(self, formatter: _FormatterOrName = "minimal") -> str: - """Run the string through the provided formatter, making it - ready for output as part of an HTML or XML document. - - :param formatter: A `Formatter` object, or a string naming one - of the standard formatters. - """ - output = self.format_string(self, formatter) - return self.PREFIX + output + self.SUFFIX - - @property - def name(self) -> None: - """Since a NavigableString is not a Tag, it has no .name. - - This property is implemented so that code like this doesn't crash - when run on a mixture of Tag and NavigableString objects: - [x.name for x in tag.children] - - :meta private: - """ - return None - - @name.setter - def name(self, name: str) -> None: - """Prevent NavigableString.name from ever being set. - - :meta private: - """ - raise AttributeError("A NavigableString cannot be given a name.") - - def _all_strings( - self, strip: bool = False, types: _OneOrMoreStringTypes = PageElement.default - ) -> Iterator[str]: - """Yield all strings of certain classes, possibly stripping them. - - This makes it easy for NavigableString to implement methods - like get_text() as conveniences, creating a consistent - text-extraction API across all PageElements. - - :param strip: If True, all strings will be stripped before being - yielded. - - :param types: A tuple of NavigableString subclasses. If this - NavigableString isn't one of those subclasses, the - sequence will be empty. By default, the subclasses - considered are NavigableString and CData objects. That - means no comments, processing instructions, etc. - - :yield: A sequence that either contains this string, or is empty. - """ - if types is self.default: - # This is kept in Tag because it's full of subclasses of - # this class, which aren't defined until later in the file. - types = Tag.MAIN_CONTENT_STRING_TYPES - - # Do nothing if the caller is looking for specific types of - # string, and we're of a different type. - # - # We check specific types instead of using isinstance(self, - # types) because all of these classes subclass - # NavigableString. Anyone who's using this feature probably - # wants generic NavigableStrings but not other stuff. - my_type = type(self) - if types is not None: - if isinstance(types, type): - # Looking for a single type. - if my_type is not types: - return - elif my_type not in types: - # Looking for one of a list of types. - return - - value = self - if strip: - final_value = value.strip() - else: - final_value = self - if len(final_value) > 0: - yield final_value - - @property - def strings(self) -> Iterator[str]: - """Yield this string, but only if it is interesting. - - This is defined the way it is for compatibility with - `Tag.strings`. See `Tag` for information on which strings are - interesting in a given context. - - :yield: A sequence that either contains this string, or is empty. - """ - return self._all_strings() - - -class PreformattedString(NavigableString): - """A `NavigableString` not subject to the normal formatting rules. - - This is an abstract class used for special kinds of strings such - as comments (`Comment`) and CDATA blocks (`CData`). - """ - - PREFIX: str = "" - SUFFIX: str = "" - - def output_ready(self, formatter: Optional[_FormatterOrName] = None) -> str: - """Make this string ready for output by adding any subclass-specific - prefix or suffix. - - :param formatter: A `Formatter` object, or a string naming one - of the standard formatters. The string will be passed into the - `Formatter`, but only to trigger any side effects: the return - value is ignored. - - :return: The string, with any subclass-specific prefix and - suffix added on. - """ - if formatter is not None: - self.format_string(self, formatter) - return self.PREFIX + self + self.SUFFIX - - -class CData(PreformattedString): - """A `CDATA section `_.""" - - PREFIX: str = "" - - -class ProcessingInstruction(PreformattedString): - """A SGML processing instruction.""" - - PREFIX: str = "" - - -class XMLProcessingInstruction(ProcessingInstruction): - """An `XML processing instruction `_.""" - - PREFIX: str = "" - - -class Comment(PreformattedString): - """An `HTML comment `_ or `XML comment `_.""" - - PREFIX: str = "" - - -class Declaration(PreformattedString): - """An `XML declaration `_.""" - - PREFIX: str = "" - - -class Doctype(PreformattedString): - """A `document type declaration `_.""" - - @classmethod - def for_name_and_ids( - cls, name: str, pub_id: Optional[str], system_id: Optional[str] - ) -> Doctype: - """Generate an appropriate document type declaration for a given - public ID and system ID. - - :param name: The name of the document's root element, e.g. 'html'. - :param pub_id: The Formal Public Identifier for this document type, - e.g. '-//W3C//DTD XHTML 1.1//EN' - :param system_id: The system identifier for this document type, - e.g. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' - """ - return Doctype(cls._string_for_name_and_ids(name, pub_id, system_id)) - - @classmethod - def _string_for_name_and_ids( - self, name: str, pub_id: Optional[str], system_id: Optional[str] - ) -> str: - """Generate a string to be used as the basis of a Doctype object. - - This is a separate method from for_name_and_ids() because the lxml - TreeBuilder needs to call it. - """ - value = name or "" - if pub_id is not None: - value += ' PUBLIC "%s"' % pub_id - if system_id is not None: - value += ' "%s"' % system_id - elif system_id is not None: - value += ' SYSTEM "%s"' % system_id - return value - - PREFIX: str = "\n" - - -class Stylesheet(NavigableString): - """A `NavigableString` representing the contents of a `") - assert isinstance(soup.style.string, Stylesheet) - assert isinstance(soup.script.string, Script) - - soup = self.soup("") - assert isinstance(soup.style.string, Stylesheet) - # The contents of the style tag resemble an HTML comment, but - # it's not treated as a comment. - assert soup.style.string == "" - assert isinstance(soup.style.string, Stylesheet) - - def test_pickle_and_unpickle_identity(self): - # Pickling a tree, then unpickling it, yields a tree identical - # to the original. - tree = self.soup("foo") - dumped = pickle.dumps(tree, pickle.HIGHEST_PROTOCOL) - loaded = pickle.loads(dumped) - assert loaded.__class__ == BeautifulSoup - assert loaded.decode() == tree.decode() - - def test_pickle_and_unpickle_bad_markup(self): - markup = """ - - -blabla - - -""" - soup = self.soup(markup) - pickled = pickle.dumps(soup, pickle.HIGHEST_PROTOCOL) - soup = pickle.loads(pickled) - assert soup.builder.is_xml is False - - def assertDoctypeHandled(self, doctype_fragment: str) -> None: - """Assert that a given doctype string is handled correctly.""" - doctype_str, soup = self._document_with_doctype(doctype_fragment) - - # Make sure a Doctype object was created. - doctype = soup.contents[0] - assert doctype.__class__ == Doctype - assert doctype == doctype_fragment - assert soup.encode("utf8")[: len(doctype_str)] == doctype_str - - # Make sure that the doctype was correctly associated with the - # parse tree and that the rest of the document parsed. - assert soup.p is not None - assert soup.p.contents[0] == "foo" - - def _document_with_doctype( - self, doctype_fragment: str, doctype_string: str = "DOCTYPE" - ) -> Tuple[bytes, BeautifulSoup]: - """Generate and parse a document with the given doctype.""" - doctype = "" % (doctype_string, doctype_fragment) - markup = doctype + "\n

foo

" - soup = self.soup(markup) - return doctype.encode("utf8"), soup - - def test_normal_doctypes(self): - """Make sure normal, everyday HTML doctypes are handled correctly.""" - self.assertDoctypeHandled("html") - self.assertDoctypeHandled( - 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' - ) - - def test_empty_doctype(self): - soup = self.soup("") - doctype = soup.contents[0] - assert "" == doctype.strip() - - def test_mixed_case_doctype(self): - # A lowercase or mixed-case doctype becomes a Doctype. - for doctype_fragment in ("doctype", "DocType"): - doctype_str, soup = self._document_with_doctype("html", doctype_fragment) - - # Make sure a Doctype object was created and that the DOCTYPE - # is uppercase. - doctype = soup.contents[0] - assert doctype.__class__ == Doctype - assert doctype == "html" - assert soup.encode("utf8")[: len(doctype_str)] == b"" - - # Make sure that the doctype was correctly associated with the - # parse tree and that the rest of the document parsed. - assert soup.p.contents[0] == "foo" - - def test_public_doctype_with_url(self): - doctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"' - self.assertDoctypeHandled(doctype) - - def test_system_doctype(self): - self.assertDoctypeHandled('foo SYSTEM "http://www.example.com/"') - - def test_namespaced_system_doctype(self): - # We can handle a namespaced doctype with a system ID. - self.assertDoctypeHandled('xsl:stylesheet SYSTEM "htmlent.dtd"') - - def test_namespaced_public_doctype(self): - # Test a namespaced doctype with a public id. - self.assertDoctypeHandled('xsl:stylesheet PUBLIC "htmlent.dtd"') - - def test_real_xhtml_document(self): - """A real XHTML document should come out more or less the same as it went in.""" - markup = b""" - - -Hello. -Goodbye. -""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - assert soup.encode("utf-8").replace(b"\n", b"") == markup.replace(b"\n", b"") - - # No warning was issued about parsing an XML document as HTML, - # because XHTML is both. - assert w == [] - - def test_namespaced_html(self): - # When a namespaced XML document is parsed as HTML it should - # be treated as HTML with weird tag names. - markup = b"""content""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - - assert 2 == len(soup.find_all("ns1:foo")) - - # n.b. no "you're parsing XML as HTML" warning was given - # because there was no XML declaration. - assert [] == w - - def test_detect_xml_parsed_as_html(self): - # A warning is issued when parsing an XML document as HTML, - # but basic stuff should still work. - markup = b"""string""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - assert soup.tag.string == "string" - [warning] = w - assert isinstance(warning.message, XMLParsedAsHTMLWarning) - assert str(warning.message) == XMLParsedAsHTMLWarning.MESSAGE - - # NOTE: the warning is not issued if the document appears to - # be XHTML (tested with test_real_xhtml_document in the - # superclass) or if there is no XML declaration (tested with - # test_namespaced_html in the superclass). - - def test_processing_instruction(self): - # We test both Unicode and bytestring to verify that - # process_markup correctly sets processing_instruction_class - # even when the markup is already Unicode and there is no - # need to process anything. - markup = """""" - soup = self.soup(markup) - assert markup == soup.decode() - - markup = b"""""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_deepcopy(self): - """Make sure you can copy the tree builder. - - This is important because the builder is part of a - BeautifulSoup object, and we want to be able to copy that. - """ - copy.deepcopy(self.default_builder) - - def test_p_tag_is_never_empty_element(self): - """A

tag is never designated as an empty-element tag. - - Even if the markup shows it as an empty-element tag, it - shouldn't be presented that way. - """ - soup = self.soup("

") - assert not soup.p.is_empty_element - assert str(soup.p) == "

" - - def test_unclosed_tags_get_closed(self): - """A tag that's not closed by the end of the document should be closed. - - This applies to all tags except empty-element tags. - """ - self.assert_soup("

", "

") - self.assert_soup("", "") - - self.assert_soup("
", "
") - - def test_br_is_always_empty_element_tag(self): - """A
tag is designated as an empty-element tag. - - Some parsers treat

as one
tag, some parsers as - two tags, but it should always be an empty-element tag. - """ - soup = self.soup("

") - assert soup.br.is_empty_element - assert str(soup.br) == "
" - - def test_nested_formatting_elements(self): - self.assert_soup("") - - def test_double_head(self): - html = """ - - -Ordinary HEAD element test - - - -Hello, world! - - -""" - soup = self.soup(html) - assert "text/javascript" == soup.find("script")["type"] - - def test_comment(self): - # Comments are represented as Comment objects. - markup = "

foobaz

" - self.assert_soup(markup) - - soup = self.soup(markup) - comment = soup.find(string="foobar") - assert comment.__class__ == Comment - - # The comment is properly integrated into the tree. - foo = soup.find(string="foo") - assert comment == foo.next_element - baz = soup.find(string="baz") - assert comment == baz.previous_element - - def test_preserved_whitespace_in_pre_and_textarea(self): - """Whitespace must be preserved in
 and \n"
-        self.assert_soup(pre_markup)
-        self.assert_soup(textarea_markup)
-
-        soup = self.soup(pre_markup)
-        assert soup.pre.prettify() == pre_markup
-
-        soup = self.soup(textarea_markup)
-        assert soup.textarea.prettify() == textarea_markup
-
-        soup = self.soup("")
-        assert soup.textarea.prettify() == "\n"
-
-    def test_nested_inline_elements(self):
-        """Inline elements can be nested indefinitely."""
-        b_tag = "Inside a B tag"
-        self.assert_soup(b_tag)
-
-        nested_b_tag = "

A nested tag

" - self.assert_soup(nested_b_tag) - - double_nested_b_tag = "

A doubly nested tag

" - self.assert_soup(double_nested_b_tag) - - def test_nested_block_level_elements(self): - """Block elements can be nested.""" - soup = self.soup("

Foo

") - blockquote = soup.blockquote - assert blockquote.p.b.string == "Foo" - assert blockquote.b.string == "Foo" - - def test_correctly_nested_tables(self): - """One table can go inside another one.""" - markup = ( - '' - "" - "" - ) - - self.assert_soup( - markup, - '
Here's another table:" - '' - "" - "
foo
Here\'s another table:' - '
foo
' - "
", - ) - - self.assert_soup( - "" - "" - "
Foo
Bar
Baz
" - ) - - def test_multivalued_attribute_with_whitespace(self): - # Whitespace separating the values of a multi-valued attribute - # should be ignored. - - markup = '
' - soup = self.soup(markup) - assert ["foo", "bar"] == soup.div["class"] - - # If you search by the literal name of the class it's like the whitespace - # wasn't there. - assert soup.div == soup.find("div", class_="foo bar") - - def test_deeply_nested_multivalued_attribute(self): - # html5lib can set the attributes of the same tag many times - # as it rearranges the tree. This has caused problems with - # multivalued attributes. - markup = '
' - soup = self.soup(markup) - assert ["css"] == soup.div.div["class"] - - def test_multivalued_attribute_on_html(self): - # html5lib uses a different API to set the attributes ot the - # tag. This has caused problems with multivalued - # attributes. - markup = '' - soup = self.soup(markup) - assert ["a", "b"] == soup.html["class"] - - def test_angle_brackets_in_attribute_values_are_escaped(self): - self.assert_soup('', '') - - def test_strings_resembling_character_entity_references(self): - # "&T" and "&p" look like incomplete character entities, but they are - # not. - self.assert_soup( - "

• AT&T is in the s&p 500

", - "

\u2022 AT&T is in the s&p 500

", - ) - - def test_apos_entity(self): - self.assert_soup( - "

Bob's Bar

", - "

Bob's Bar

", - ) - - def test_entities_in_foreign_document_encoding(self): - # “ and ” are invalid numeric entities referencing - # Windows-1252 characters. - references a character common - # to Windows-1252 and Unicode, and ☃ references a - # character only found in Unicode. - # - # All of these entities should be converted to Unicode - # characters. - markup = "

“Hello” -☃

" - soup = self.soup(markup) - assert "“Hello†-☃" == soup.p.string - - def test_entities_in_attributes_converted_to_unicode(self): - expect = '

' - self.assert_soup('

', expect) - self.assert_soup('

', expect) - self.assert_soup('

', expect) - self.assert_soup('

', expect) - - def test_entities_in_text_converted_to_unicode(self): - expect = "

pi\N{LATIN SMALL LETTER N WITH TILDE}ata

" - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - - def test_quot_entity_converted_to_quotation_mark(self): - self.assert_soup( - "

I said "good day!"

", '

I said "good day!"

' - ) - - def test_out_of_range_entity(self): - expect = "\N{REPLACEMENT CHARACTER}" - self.assert_soup("�", expect) - self.assert_soup("�", expect) - self.assert_soup("�", expect) - - def test_multipart_strings(self): - "Mostly to prevent a recurrence of a bug in the html5lib treebuilder." - soup = self.soup("

\nfoo

") - assert "p" == soup.h2.string.next_element.name - assert "p" == soup.p.name - self.assertConnectedness(soup) - - def test_invalid_html_entity(self): - # The html.parser treebuilder can't distinguish between an - # invalid HTML entity with a semicolon and an invalid HTML - # entity with no semicolon (see its subclass for the tested - # behavior). But the other treebuilders can. - markup = "

a &nosuchentity b

" - soup = self.soup(markup) - assert "

a &nosuchentity b

" == soup.p.decode() - - markup = "

a &nosuchentity; b

" - soup = self.soup(markup) - assert "

a &nosuchentity; b

" == soup.p.decode() - - def test_head_tag_between_head_and_body(self): - "Prevent recurrence of a bug in the html5lib treebuilder." - content = """ - - foo - -""" - soup = self.soup(content) - assert soup.html.body is not None - self.assertConnectedness(soup) - - def test_multiple_copies_of_a_tag(self): - "Prevent recurrence of a bug in the html5lib treebuilder." - content = """ - - - - - -""" - soup = self.soup(content) - self.assertConnectedness(soup.article) - - def test_basic_namespaces(self): - """Parsers don't need to *understand* namespaces, but at the - very least they should not choke on namespaces or lose - data.""" - - markup = b'4' - soup = self.soup(markup) - assert markup == soup.encode() - assert "http://www.w3.org/1999/xhtml" == soup.html["xmlns"] - assert "http://www.w3.org/1998/Math/MathML" == soup.html["xmlns:mathml"] - assert "http://www.w3.org/2000/svg" == soup.html["xmlns:svg"] - - def test_multivalued_attribute_value_becomes_list(self): - markup = b'' - soup = self.soup(markup) - assert ["foo", "bar"] == soup.a["class"] - - # - # Generally speaking, tests below this point are more tests of - # Beautiful Soup than tests of the tree builders. But parsers are - # weird, so we run these tests separately for every tree builder - # to detect any differences between them. - # - - def test_can_parse_unicode_document(self): - # A seemingly innocuous document... but it's in Unicode! And - # it contains characters that can't be represented in the - # encoding found in the declaration! The horror! - markup = 'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.body.string - - def test_soupstrainer(self): - """Parsers should be able to work with SoupStrainers.""" - strainer = SoupStrainer("b") - soup = self.soup("A bold statement", parse_only=strainer) - assert soup.decode() == "bold" - - def test_single_quote_attribute_values_become_double_quotes(self): - self.assert_soup("", '') - - def test_attribute_values_with_nested_quotes_are_left_alone(self): - text = """a""" - self.assert_soup(text) - - def test_attribute_values_with_double_nested_quotes_get_quoted(self): - text = """a""" - soup = self.soup(text) - soup.foo["attr"] = 'Brawls happen at "Bob\'s Bar"' - self.assert_soup( - soup.foo.decode(), - """a""", - ) - - def test_ampersand_in_attribute_value_gets_escaped(self): - self.assert_soup( - '', - '', - ) - - self.assert_soup( - 'foo', - 'foo', - ) - - def test_escaped_ampersand_in_attribute_value_is_left_alone(self): - self.assert_soup('') - - def test_entities_in_strings_converted_during_parsing(self): - # Both XML and HTML entities are converted to Unicode characters - # during parsing. - text = "

<<sacré bleu!>>

" - expected = ( - "

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

" - ) - self.assert_soup(text, expected) - - def test_smart_quotes_converted_on_the_way_in(self): - # Microsoft smart quotes are converted to Unicode characters during - # parsing. - quote = b"

\x91Foo\x92

" - soup = self.soup(quote, from_encoding="windows-1252") - assert ( - soup.p.string - == "\N{LEFT SINGLE QUOTATION MARK}Foo\N{RIGHT SINGLE QUOTATION MARK}" - ) - - def test_non_breaking_spaces_converted_on_the_way_in(self): - soup = self.soup("  ") - assert soup.a.string == "\N{NO-BREAK SPACE}" * 2 - - def test_entities_converted_on_the_way_out(self): - text = "

<<sacré bleu!>>

" - expected = "

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

".encode( - "utf-8" - ) - soup = self.soup(text) - assert soup.p.encode("utf-8") == expected - - def test_real_iso_8859_document(self): - # Smoke test of interrelated functionality, using an - # easy-to-understand document. - - # Here it is in Unicode. Note that it claims to be in ISO-8859-1. - unicode_html = '

Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!

' - - # That's because we're going to encode it into ISO-8859-1, - # and use that to test. - iso_latin_html = unicode_html.encode("iso-8859-1") - - # Parse the ISO-8859-1 HTML. - soup = self.soup(iso_latin_html) - - # Encode it to UTF-8. - result = soup.encode("utf-8") - - # What do we expect the result to look like? Well, it would - # look like unicode_html, except that the META tag would say - # UTF-8 instead of ISO-8859-1. - expected = unicode_html.replace("ISO-8859-1", "utf-8") - - # And, of course, it would be in UTF-8, not Unicode. - expected = expected.encode("utf-8") - - # Ta-da! - assert result == expected - - def test_real_shift_jis_document(self): - # Smoke test to make sure the parser can handle a document in - # Shift-JIS encoding, without choking. - shift_jis_html = ( - b"
"
-            b"\x82\xb1\x82\xea\x82\xcdShift-JIS\x82\xc5\x83R\x81[\x83f"
-            b"\x83B\x83\x93\x83O\x82\xb3\x82\xea\x82\xbd\x93\xfa\x96{\x8c"
-            b"\xea\x82\xcc\x83t\x83@\x83C\x83\x8b\x82\xc5\x82\xb7\x81B"
-            b"
" - ) - unicode_html = shift_jis_html.decode("shift-jis") - soup = self.soup(unicode_html) - - # Make sure the parse tree is correctly encoded to various - # encodings. - assert soup.encode("utf-8") == unicode_html.encode("utf-8") - assert soup.encode("euc_jp") == unicode_html.encode("euc_jp") - - def test_real_hebrew_document(self): - # A real-world test to make sure we can convert ISO-8859-9 (a - # Hebrew encoding) to UTF-8. - hebrew_document = b"Hebrew (ISO 8859-8) in Visual Directionality

Hebrew (ISO 8859-8) in Visual Directionality

\xed\xe5\xec\xf9" - soup = self.soup(hebrew_document, from_encoding="iso8859-8") - # Some tree builders call it iso8859-8, others call it iso-8859-9. - # That's not a difference we really care about. - assert soup.original_encoding in ("iso8859-8", "iso-8859-8") - assert soup.encode("utf-8") == ( - hebrew_document.decode("iso8859-8").encode("utf-8") - ) - - def test_meta_tag_reflects_current_encoding(self): - # Here's the tag saying that a document is - # encoded in Shift-JIS. - meta_tag = ( - '' - ) - - # Here's a document incorporating that meta tag. - shift_jis_html = ( - "\n%s\n" - '' - "Shift-JIS markup goes here." - ) % meta_tag - soup = self.soup(shift_jis_html) - - # Parse the document, and the charset is seemingly unaffected. - parsed_meta = soup.find("meta", {"http-equiv": "Content-type"}) - content = parsed_meta["content"] - assert "text/html; charset=x-sjis" == content - - # But that value is actually a ContentMetaAttributeValue object. - assert isinstance(content, ContentMetaAttributeValue) - - # And it will take on a value that reflects its current - # encoding. - assert "text/html; charset=utf8" == content.substitute_encoding("utf8") - - # No matter how the tag is encoded, its charset attribute - # will always be accurate. - assert b"charset=utf8" in parsed_meta.encode("utf8") - assert b"charset=shift-jis" in parsed_meta.encode("shift-jis") - - # For the rest of the story, see TestSubstitutions in - # test_tree.py. - - def test_html5_style_meta_tag_reflects_current_encoding(self): - # Here's the tag saying that a document is - # encoded in Shift-JIS. - meta_tag = '' - - # Here's a document incorporating that meta tag. - shift_jis_html = ( - "\n%s\n" - '' - "Shift-JIS markup goes here." - ) % meta_tag - soup = self.soup(shift_jis_html) - - # Parse the document, and the charset is seemingly unaffected. - parsed_meta = soup.find("meta", id="encoding") - charset = parsed_meta["charset"] - assert "x-sjis" == charset - - # But that value is actually a CharsetMetaAttributeValue object. - assert isinstance(charset, CharsetMetaAttributeValue) - - # And it will take on a value that reflects its current - # encoding. - assert "utf8" == charset.substitute_encoding("utf8") - - # No matter how the tag is encoded, its charset attribute - # will always be accurate. - assert b'charset="utf8"' in parsed_meta.encode("utf8") - assert b'charset="shift-jis"' in parsed_meta.encode("shift-jis") - - def test_python_specific_encodings_not_used_in_charset(self): - # You can encode an HTML document using a Python-specific - # encoding, but that encoding won't be mentioned _inside_ the - # resulting document. Instead, the document will appear to - # have no encoding. - for markup in [ - b'' b'' - ]: - soup = self.soup(markup) - for encoding in PYTHON_SPECIFIC_ENCODINGS: - if encoding in ( - "idna", - "mbcs", - "oem", - "undefined", - "string_escape", - "string-escape", - ): - # For one reason or another, these will raise an - # exception if we actually try to use them, so don't - # bother. - continue - encoded = soup.encode(encoding) - assert b'meta charset=""' in encoded - assert encoding.encode("ascii") not in encoded - - def test_tag_with_no_attributes_can_have_attributes_added(self): - data = self.soup("text") - data.a["foo"] = "bar" - assert 'text' == data.a.decode() - - def test_closing_tag_with_no_opening_tag(self): - # Without BeautifulSoup.open_tag_counter, the tag will - # cause _popToTag to be called over and over again as we look - # for a tag that wasn't there. The result is that 'text2' - # will show up outside the body of the document. - soup = self.soup("

text1

text2
") - assert "

text1

text2
" == soup.body.decode() - - def test_worst_case(self): - """Test the worst case (currently) for linking issues.""" - - soup = self.soup(BAD_DOCUMENT) - self.linkage_validator(soup) - - -class XMLTreeBuilderSmokeTest(TreeBuilderSmokeTest): - def test_pickle_and_unpickle_identity(self): - # Pickling a tree, then unpickling it, yields a tree identical - # to the original. - tree = self.soup("foo") - dumped = pickle.dumps(tree, 2) - loaded = pickle.loads(dumped) - assert loaded.__class__ == BeautifulSoup - assert loaded.decode() == tree.decode() - - def test_docstring_generated(self): - soup = self.soup("") - assert soup.encode() == b'\n' - - def test_xml_declaration(self): - markup = b"""\n""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_python_specific_encodings_not_used_in_xml_declaration(self): - # You can encode an XML document using a Python-specific - # encoding, but that encoding won't be mentioned _inside_ the - # resulting document. - markup = b"""\n""" - soup = self.soup(markup) - for encoding in PYTHON_SPECIFIC_ENCODINGS: - if encoding in ( - "idna", - "mbcs", - "oem", - "undefined", - "string_escape", - "string-escape", - ): - # For one reason or another, these will raise an - # exception if we actually try to use them, so don't - # bother. - continue - encoded = soup.encode(encoding) - assert b'' in encoded - assert encoding.encode("ascii") not in encoded - - def test_processing_instruction(self): - markup = b"""\n""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_real_xhtml_document(self): - """A real XHTML document should come out *exactly* the same as it went in.""" - markup = b""" - - -Hello. -Goodbye. -""" - soup = self.soup(markup) - assert soup.encode("utf-8") == markup - - def test_nested_namespaces(self): - doc = b""" - - - - - -""" - soup = self.soup(doc) - assert doc == soup.encode() - - def test_formatter_processes_script_tag_for_xml_documents(self): - doc = """ - -""" - soup = BeautifulSoup(doc, "lxml-xml") - # lxml would have stripped this while parsing, but we can add - # it later. - soup.script.string = 'console.log("< < hey > > ");' - encoded = soup.encode() - assert b"< < hey > >" in encoded - - def test_can_parse_unicode_document(self): - markup = 'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.root.string - - def test_can_parse_unicode_document_begining_with_bom(self): - markup = '\N{BYTE ORDER MARK}Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.root.string - - def test_popping_namespaced_tag(self): - markup = 'b2012-07-02T20:33:42Zcd' - soup = self.soup(markup) - assert str(soup.rss) == markup - - def test_docstring_includes_correct_encoding(self): - soup = self.soup("") - assert ( - soup.encode("latin1") == b'\n' - ) - - def test_large_xml_document(self): - """A large XML document should come out the same as it went in.""" - markup = ( - b'\n' - + b"0" * (2**12) - + b"" - ) - soup = self.soup(markup) - assert soup.encode("utf-8") == markup - - def test_tags_are_empty_element_if_and_only_if_they_are_empty(self): - self.assert_soup("

", "

") - self.assert_soup("

foo

") - - def test_namespaces_are_preserved(self): - markup = 'This tag is in the a namespaceThis tag is in the b namespace' - soup = self.soup(markup) - root = soup.root - assert "http://example.com/" == root["xmlns:a"] - assert "http://example.net/" == root["xmlns:b"] - - def test_closing_namespaced_tag(self): - markup = '

20010504

' - soup = self.soup(markup) - assert str(soup.p) == markup - - def test_namespaced_attributes(self): - markup = '' - soup = self.soup(markup) - assert str(soup.foo) == markup - - def test_namespaced_attributes_xml_namespace(self): - markup = 'bar' - soup = self.soup(markup) - assert str(soup.foo) == markup - - def test_find_by_prefixed_name(self): - doc = """ - - foo - bar - baz - -""" - soup = self.soup(doc) - - # There are three tags. - assert 3 == len(soup.find_all("tag")) - - # But two of them are ns1:tag and one of them is ns2:tag. - assert 2 == len(soup.find_all("ns1:tag")) - assert 1 == len(soup.find_all("ns2:tag")) - - assert 1, len(soup.find_all("ns2:tag", key="value")) - assert 3, len(soup.find_all(["ns1:tag", "ns2:tag"])) - - def test_copy_tag_preserves_namespace(self): - xml = """ -""" - - soup = self.soup(xml) - tag = soup.document - duplicate = copy.copy(tag) - - # The two tags have the same namespace prefix. - assert tag.prefix == duplicate.prefix - - def test_worst_case(self): - """Test the worst case (currently) for linking issues.""" - - soup = self.soup(BAD_DOCUMENT) - self.linkage_validator(soup) - - -class HTML5TreeBuilderSmokeTest(HTMLTreeBuilderSmokeTest): - """Smoke test for a tree builder that supports HTML5.""" - - def test_real_xhtml_document(self): - # Since XHTML is not HTML5, HTML5 parsers are not tested to handle - # XHTML documents in any particular way. - pass - - def test_html_tags_have_namespace(self): - markup = "" - soup = self.soup(markup) - assert "http://www.w3.org/1999/xhtml" == soup.a.namespace - - def test_svg_tags_have_namespace(self): - markup = "" - soup = self.soup(markup) - namespace = "http://www.w3.org/2000/svg" - assert namespace == soup.svg.namespace - assert namespace == soup.circle.namespace - - def test_mathml_tags_have_namespace(self): - markup = "5" - soup = self.soup(markup) - namespace = "http://www.w3.org/1998/Math/MathML" - assert namespace == soup.math.namespace - assert namespace == soup.msqrt.namespace - - def test_xml_declaration_becomes_comment(self): - markup = '' - soup = self.soup(markup) - assert isinstance(soup.contents[0], Comment) - assert soup.contents[0] == '?xml version="1.0" encoding="utf-8"?' - assert "html" == soup.contents[0].next_element.name diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 35e1dc2c585cb36c126934fb91ca856c1fcef7f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68224 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 PCm7+RGNS}Oh8f}?S@I}K diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc deleted file mode 100644 index e8fe1a02064cb113a6a31eb078943c36867c1eba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1566 zcmah}&u<$=6n?Y6lGt?;5x0rcw00AOY9O|d2x^JzC{PiEVhaf)wXR{c*&Qbvuf1kx zoYbx(0gA+>hjL2QOA8l3`6u9p#Kj??n1xD6oVd{%sZvkO>}G{&UGY|W`@MPZdpmF5 zoBbgY2?3Lp(uW%>62Kqa2!z?5^e(X19vEOC3ySlUh`X?V99C4CQc`xO3z*Qsdug4lYEGq5f7!C_ z3Q;Yyg4OF)D=8<1)^m9~!EnOBx}`Z9HSOA4Yj zv&2bRKWbU04b5UfSN@I4^02fQmQD0YhGQ>x!7=s9)0}9Kx@OPwxOu9rXA8R6cPI+O z-0p=CKTgWDF9zB_#tX0`wow~x_Va=$A&4pqm*Im|fE|ejErLy+{RwGH0b@sQ%Wa`@ z9)Jk%z^AA!IHT=>Z6xEKf1uCtx#FN!2W>@gGcUmipGx)wjYrUgId}yK+GZ1b6%c!x za9z9#+bAjKTj$rvtEshyX&Kl_4W5RSx~(}iS8CAmg{0!}19BBy(``oKx5Pce{i<13 z{i#v^J2kGNvtDDv4LO)#s#a~il2lxYV5{sZKE)k9<(=D3&{j<-Ru#WAEKkx|3(_o&9k#-5F1JCey!6oa>&B z-(9@3*onSyd-3=9+}#^@ZgiqA-d^gCNB71)ANzUy+=DTQz4l0i(WRqE_8^jdOir** z-&~$sz9@coQGP=h$|r~1VO6bZRjjIRNM(I88WzVVRP`fvU5`CVy~&GnC4S0oxX%6o zRZJbTg`Fr%`3>}#24{jR-Z4*cKwe^M7rJuzvumGRJCbJ(h~d8Z^`_DP=xNUN67Y?1 diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc deleted file mode 100644 index b42bab9b8f4e36528bd2cec1589cbab8fa821b39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7588 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 diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_css.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_css.cpython-312.pyc deleted file mode 100644 index 67613a376412f185aad3677cd0e9e9fe82610f1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28813 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 U`p`tb53MH4OXkm58msUB0mj$LQ~&?~ diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_dammit.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_dammit.cpython-312.pyc deleted file mode 100644 index 138b3273f32fef75d414a9c0f373ac96834e08b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19774 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 diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc deleted file mode 100644 index 4651c8f0a9664cc606356ff4022bb62371efa080..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7785 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 COzLF- diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc deleted file mode 100644 index ea41f1512b772ca0829b272dc04f3707ba17fcd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7036 zcmb_hUu@gP89$PuM9Gq6Teg$fNy9X*Q>FexNfafeZGhNm;ue`3Ea}#|?gUDtY%2QW zl2jZEc99MRYGWOoU=K0&WONu#CONzecyfe-S7Kzr@weSE(Fin>0iul_9OI9{9--!YGa2d5W0aRG=(HWA~VDk zVbLkd5f&PljtmxTpuB+ zP42u!Rr+pK$)>s%$fHPZA3%6E$uZ@52Yn*Uqbt-qXrA!9MFN;yoK-Y7rDS9_na}B> zlG9jS)^s*0YO=I!@*Xi9Fzl`0gAP_ueIpV5ZcIaSGu zs*+h?Q))iTp3UcHGV(Ev&1>2)9ts2UX*sEnuov=Kna!twsjSH^m_~&KL zK$hGPE9RsMi;4sdD{c@)Qc@{d#X`-C3qS|Ls>;lateOj+m03-MHB@CCakPfKJErSZLRQ;JW_kZy1Wg1+)v;Ges%XFb$s4w`K%{U?WtAJMpwfseD&FDT4{d* zzyG5YQuj=KM|$>|%t*!=qp<{}{T4EU&`a|DAFo1(#B$Cv{%$Kccp zYHl)F^}D9dFgmf%-T9LlgBDS`8Xp=px=2{MTp~e3#HYj($ zMZHK_eMOjQ$p#|7Q0EI=v3R>43nK(tKu3{oSw4d3MG@#7 z=(Qpjd^Pg|%%J}D85F(Nbae`gpWiv@w-p)e!iM2bb->U^ZP=HMK(qrNsA6GMyz}4S z4gLnt4xW%n$s&M4)-D$5f}R?V8V(3#88IpQJw|8T0#rN>F%f*HK`A-ipa4*Y>t|x7 zAe*jJ#XwMPP=FIvG#z6uC&j@l8dOr#47+B!Tf;8N*qf^u9R>s8Qiqth;CC1{7?4uk zCId;-MZ-}MT7&tdD~21G#49|opVq*&Yj}Zd<#{wceq#D9Sfe&=dU$ObMyN@78b^L@ z+LTE9R64ThR56_9oOX7^IO(!&d)b#CU8OOeUWNyLe!i_lo z5XZ4R4#E`sEyavH{&5&2)BXj;RkZE(tuC!Bt-ZbJ9bC2Vr63W&6PLT&TSnWEgc-a z?fBxr=E3oM?$c#E5UqMvJiqq-@bD<===%;4PT$|$U1bXDe?M$T9RpU^1MdN=S^erp z9Y>qG9%(0FtvC9{2GO5=V`22=@t4Ni(Vao(Sdh9CAaEIWj<-=?AqJN&0+;R1@jmLS z0|b=C6Uj_L(`6NFau}-_yRG4@l7keWC`-ezE#_Xx>To#1g<_!)Cxmz*7z+f8BS}@% zW`|R$gp?AaVlWXDQh`u76iEnCDHMtE3676MMV^asvdoKnd%oXd`O&jIU)|rOG1hlI zb=$SPL>Ljxo~`E7A(J)#S$?JBF9Jv-=1J@)2>7>9&2ev%lPY$0ep>B@%COHZU?qV! z7ZpfvO|vr%@Fu0=1iWHK_KLk~*fPON)B#M|ZGu>>WmR-E;U2gTtPQRY-*a={Q>Z<#<>5*m?vd68l(#&m z2G&)t|i)l5D7>5s1S*9F(DLeg;odz`JfQxqTxU^ z$P0W+w0xM0!Nd^(#O67!333=VX0V-tMr)9RfLVi2x)xr6P4#IEJ?b&&^iw8YOlTN( zIcIv_TR7X)x80m?L0a z|Eu!UAPBF9aKS^-q_rMXYi7Ej$d~0fWI=gVD?Zn(ugAV)HdRe^?4_wb>xek4&B;k6 zr6jErw5BpZ?6_k;YctX4h19N)vXxLNf6h?Fqe$VQZ$j2xJWdd0HASP zDk+5}Sqw;_P>PE-0R|_vrnP0D@oZ~bBI_}{;f&JgT5(>v># zD${Unl+!DT@Cfv)k9*od6O9&j;%0_hg=CYX9c_l^GYNhL(`k4*uE>P+N*2g30Hi0) zbE09x8M#5K3BS`|@Vz5G{uthiuU)t}e(J(&@e6OAIrIA42AS6k+nflWXl*W|!09g@ z$9E3#xM54@m7HPA!>y%ZgR3zK%%z^AGH@HK#U({mPlK=;UM!@l)m#;rR8rVtXKl}| zuG@IH0tG%{?c4IQB`=(gwvL2LN5c2K!nV76&9=3Fs09DrL(3Bnd_6ZJ*CRJxz5eQF z`!{{ZHv%Q!@G|qj+qpWwGQYaGvbZ*}p4yn*^hTC#54^r>r`HBHy@$8F10^ps2JbS1 zCY1bLcxm`51(xOlVe(SJT&6o7f4?ARDqqww5X_)7T{T0x`XYX{;k6iTVDmr?SFlA{ z9fE#!6c;$VR-@)H?UFL5zKq{r#qV?i=lZ6Hxmkg;naHbccmysE!JoDOVEzb|-DuzQ zSKlmm_tN_}LS+QiZGHz=WdYgUAHVzIyIb_Z5`A!+>H3FzV%z;nnWmhs9olZUf7?#c zfgLZj%D7eDznkDYlEy4a7px8U5lmlzX` zVqk)b7?_~DM$l8Dd+r{J-KBdr=@Z*@ThnU3BRzP=4w&(Il0LC>6k0nJvcFs&fLA!R zSkpe03y9}=o!Cp53a`o%X!_W?uZ*DD=y`}M6B*`S_Wj&tXDTph=|=Tx%zmj`^M zZ-Rh=lWfCPNqa5v7=hmgGL>5q8*Um-^Zo>97jPdfYH{;s+KpRQG%(uX#{|gOv5AWC zLxa)wx;a_pKIS~0-j2bfqzrpLfv>+Spt%TNDk2ZyG0ZC!5T8^~Rvpzw5 zOF9YLPA?){U!#t%k>`7oBFM7KPW1oX7ToskU;SX^gDvl|lK0q#ebYO7bz<9h@W#pO zC%1erm3%L4ys_zvTs^nlb7;N0)bqk$droc)eKAlve)8&M*@Z~vszzyhq4zjKDd7%`nP-femRK+?SEuu VYip;NF%P=qag6Pw?(`B+{s;ORxU>KO diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc deleted file mode 100644 index f4ade480f7e85a44ee78fe34e197a293191201c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11948 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 H*yz6jhRT(v diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc deleted file mode 100644 index 79d4657f76459206dae06ed6a32466d76732b0fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7270 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 diff --git a/.venv/Lib/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc b/.venv/Lib/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc deleted file mode 100644 index 1bdee6f1494fff4871a1ad1c011b2d4c73f3acd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31355 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 KPdxbI_xC^GvI#f< diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase deleted file mode 100644 index 4828f8a..0000000 --- a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase +++ /dev/null @@ -1 +0,0 @@ - ÿÿ ÿ

\ No newline at end of file diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase deleted file mode 100644 index 8a585ce9270e58b125922297f2d099298adac822..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15347 zcmeHOKW`H;6u+P#aRU+(18Xxd6l%E*Nl7L5s!A+KhygMnL5ETmLXBVgZv$er@K!|sD^YeJSDOAWa&ttPlG6X?Atl{} z^qDpjS}5Y|WIWoTq(csczd4*??66BhVoGhy6y1ZDBgWIhQ~nf$4?LB=5tQo zxX3XIMJ!OhCjE@@G@nnHL!!ULItAw?J4Na|Tz{fnYNoHpCUhroxQ^Xm|6~3AZ`jNU z_1CN>Z8L2Ov5UvVto$ukPyf~8Z|ZG_z+Cw)}rtPVgJ$Y!^aQq_qB2x+d@%#VL&Ee zscL#D6CO7NUrf^%e&SnKww(HyG#lR3!%5nHqKHLiq!Uq%XT(ATAI~R!c+#u~ktD)W z#Z-lH42O%htTt3XpZZq_8E}9wb>zG-$Bf4}bwbGBM0e%#VflQ3>E%3$>n4SKSi0u< zER%m$TsEp5ifAh3ZBVWkB$KNF37662`3#lv#vffpN$8m zN~NsW&nsp9m$XI|Y?vkxR-@e#J2vfv={I9yD{8L>?bJ5jl{m^X>DgR>Pz4nzY55>9 zaJF$P4nM{r0N0v8sLEMw1+^QiLKN+(xQwxB!0bXrBv?Z{w${rqtoY4tO&Vk2ajs38ITfhY1|%rRV$pMf6PhuP>A~gb(by@6 zIYN?5j_g2E=LC?WXmn7m$gyJwVL_x)6E>WMna*0~7+ng6=am8TKe^U~eF_~XCRZkW z#PW{M(|AZY!jT)*wowa!XyA7C+-+hS%aO@_kcpK7$) zCWCD<@Kz>oC}@WX+hj0SGTJ5s9fT9I*)juIwVk>gO$LI&wIfvqDdYl5f{7)#xCTIF z2SI2-qp#%56T}6sGt3_+us`Vd;ONzB-y@~Ll>LlA@XZVW@(&R0YF diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase deleted file mode 100644 index 0fe66dd23fe94a8e451dfb1a84da38ed0984c1f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19469 zcmeHP%}&BV5UwW1c<}1c&|0d-m{hN9YYZMVF=z-E6E3Azz?Aa07`*ugp1gb37w}np z1J6Ey_J;^Y+hVrDb~+?vcLObSXLo15`M%w!71Cc4g4b8Y>@_=7*S$g~EsGkt2Bn={ zt2=1kXi~B5P|KmamD`Rb<;p=_zIm%4C&qy-Vu088oOsuGz>Kq!-D0_0%~Ls_F?gfesF!B~xlP=*UCbCH?n*-O%0 z!Q*F>?46hl=N3}p9^s$pfQ;#K?C}VRg&?#Cu4Gl`M+NhN`Lsc{A^94o$;0t3y>S870B{5&zz9DFt<}-BMx(8V;~9 zu^`3{e->4K<9oQkG(Mym>pheEPdQ^GK5fr%nc+{ydd)pa{!emW8I*DurdQ@~y8Kk4 zgV7-WU60=nl>ER&`8c&A8JzU^4}@gt+g^h^gT@rwKLtV<2l@NX63OYId;^?(0~P60 z?9W6QN1A0E6WR+_CBVe3&|S@XJ2R{CP{xr=dJz@rVH;L3n4Q9zrUy|Y_Y}rG!O4js mqyYzMPzM!p)C@wIG(#Cwq{BE*384&|DuI`yvfSgo2>k@d3|T1v diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase deleted file mode 100644 index fd411427d765e9b17e1e6a015485a70632bb9554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 TcmY$eDbjbbRX@cb^ZOhC75W5K diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase deleted file mode 100644 index 6248b2c..0000000 --- a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase +++ /dev/null @@ -1 +0,0 @@ -ÿ >tet>< \ No newline at end of file diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase deleted file mode 100644 index 107da539fc15bd1664e35287ace9feda21cb5820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11502 zcmeHNy>HV%6gOf+VqhSEDxuawNKi#?;xtXg#SCTdK!q3y#cd3AnkG&P3ldWY7XAYy zCT0f2N_Q3{#Kh8pfq{iTAiQ_)?sEPrNt;$FI=4Ds&hO(s-o1P8XBP^E%c~a(bbUIR z>pt6&8VYYetR1|1@3DT}-suHUu57m=zZDhNUbKCCoqp6en~h@8f`8Us?*#40@z@;v zvWixx>qm8ug?`kSZAMZ199wmM)@|Fljl~QWU$J;93#i=Gnw~*BlHQ#|0?zbH*5 zb%|;A>ykT1x$T5V0o|~j6!-jKFyP&Q0fx?{e_SD_qO!^BSE=P1b3*t-8C14p{iSNc z2V3ItzI+T%ukbpRx(HH0EkaF-OQ}&>bS_;QQIeM5QcmbNA;V7VgCSi+Ka`)}b4~+u zIOf`Y|F-|bcGS`*xVc><+HeK=DuR7kbb;M|VG*n$UVC7lv5TH2TY-e=Ct3={xQ+R4 zwyZppvo(W_ZxdtZ*>Zz`2*oa8?n9GW;CglXx z<}63=pqMsNj5^H-eT8Y@E zP=-sP&U&-KBcEQhQFN;n4^K@xO-DQbCK=e7a4zp`HQ}5I=Oz-?nQ%^KGA3<_C5= zlRW%*ktfj|g`Fl))G`RHqfkU^=K$nAEVm4Oss1xm@?`cmF%gp;&h|LjDKbyFFvm(o zWHM`)cSw5|y>6c;zMKmSoRv`l zPeWS%fLuIZqeLOxJve;>FPgW-2pF5U#T0&+x5X53 zjQLv8ye*brDwwY#Fm>Y}L;QzdMc~-Z@auB}FN(+qLgC{?R>|o0jGKi4oeBP!uvKWO zmx{C@5I3Jxz--`-k(ePz3Jtudax^kV11};Vc?{4p4le@a3||N1H!?MkT}(oo#aihv D9d3o5 diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase deleted file mode 100644 index 367106c..0000000 --- a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase +++ /dev/null @@ -1,2 +0,0 @@ - -t \ No newline at end of file diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase deleted file mode 100644 index a823d557b4bebed8a9cdb880d281c9de69a1aa0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3546 zcmdP2$xSTDup1>uLtr!nMnhmU1V%$(Gz3ONU^E0qLtw~uwSNNv*}xU^oQ!vv$DtbH{XnB<{4q&MBMIvxRFa&-_pUv zaZ?A@)wk1eCmnC=bU*Q=8+sfD%u9F-wunGF9Af5kU{XeIH<5gU7$((-f1t0?R%dI;Jq*Qch%_#M(x|K>?1-n+*fFB zm6{d^8#<{hj+7bdpv`Q#2CcfFkUioNUyXr5z+=fRP%u7K(G*r#6$M^Z_&u?|;XuBN z@N6(okxftZk53XI6>lL`P*y0e{H4&t=5>jM|{*N|q#^8%sAhqM+Y3%AITJ zj+ie=x^@H_p!D;o#ZMNvPoPiY!4dto?gr%>8ZfxWSt4CK@!+{gLI_zD^Y~@@!h9AT zhwtJ(69K8%&(5%E2fpgGkYsM!X=s?z8oHP}&TI@w9WRoXm;n8Ha{-ib=yrZ_~b; zLif2&eN24}r`0u!2Q^n!;Z(g+b!QW%0&VHg*@TwX)&r$x>#WdFWGZjuEVhzaKfVQc zE1wv%%}(9W_#3HHZI>9f_+=c57M9cCNo@`2bnw)yoeHG+-$q-W|1arjzM|GxoYGoC z;*bTH!DdtxtcOJ%%uC0=se>6mD|1!l76U4^eq4Nq!{I_ly+tmKJqqfTb*ceU6z362 ztyNgQGww04iSboml65FWdBXI!jzWnWgo#v19R>P(S{7XznX3V~Twq+Re44__&~>h> q43wHvMb7{ew`wA?1}AsyPlT5DF{Md(5}xqoqavh!LXgNIAN~adfn_KF diff --git a/.venv/Lib/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase b/.venv/Lib/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase deleted file mode 100644 index 885711554056588a381fd9a251d48ce76a916a59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103 zcma!IT*$!C&%p3|?)u|48N3V(Hi{|v$wno$1*wb-3(;hvkz^S9^*|aEj@#ts@G|Jx OROIF`00A~ppfmtd#~j4~ diff --git a/.venv/Lib/site-packages/bs4/tests/test_builder.py b/.venv/Lib/site-packages/bs4/tests/test_builder.py deleted file mode 100644 index 87d6758..0000000 --- a/.venv/Lib/site-packages/bs4/tests/test_builder.py +++ /dev/null @@ -1,28 +0,0 @@ -import pytest -from unittest.mock import patch -from bs4.builder import DetectsXMLParsedAsHTML - - -class TestDetectsXMLParsedAsHTML: - @pytest.mark.parametrize( - "markup,looks_like_xml", - [ - ("No xml declaration", False), - ("obviously HTMLActually XHTML", False), - (" < html>Tricky XHTML", False), - ("", True), - ], - ) - def test_warn_if_markup_looks_like_xml(self, markup, looks_like_xml): - # Test of our ability to guess at whether markup looks XML-ish - # _and_ not HTML-ish. - with patch("bs4.builder.DetectsXMLParsedAsHTML._warn") as mock: - for data in markup, markup.encode("utf8"): - result = DetectsXMLParsedAsHTML.warn_if_markup_looks_like_xml(data) - assert result == looks_like_xml - if looks_like_xml: - assert mock.called - else: - assert not mock.called - mock.reset_mock() diff --git a/.venv/Lib/site-packages/bs4/tests/test_builder_registry.py b/.venv/Lib/site-packages/bs4/tests/test_builder_registry.py deleted file mode 100644 index ad4b5a9..0000000 --- a/.venv/Lib/site-packages/bs4/tests/test_builder_registry.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Tests of the builder registry.""" - -import pytest -import warnings -from typing import Type - -from bs4 import BeautifulSoup -from bs4.builder import ( - builder_registry as registry, - TreeBuilder, - TreeBuilderRegistry, -) -from bs4.builder._htmlparser import HTMLParserTreeBuilder - -from . import ( - HTML5LIB_PRESENT, - LXML_PRESENT, -) - -if HTML5LIB_PRESENT: - from bs4.builder._html5lib import HTML5TreeBuilder - -if LXML_PRESENT: - from bs4.builder._lxml import ( - LXMLTreeBuilderForXML, - LXMLTreeBuilder, - ) - - -# TODO: Split out the lxml and html5lib tests into their own classes -# and gate with pytest.mark.skipIf. -class TestBuiltInRegistry(object): - """Test the built-in registry with the default builders registered.""" - - def test_combination(self): - assert registry.lookup("strict", "html") == HTMLParserTreeBuilder - if LXML_PRESENT: - assert registry.lookup("fast", "html") == LXMLTreeBuilder - assert registry.lookup("permissive", "xml") == LXMLTreeBuilderForXML - if HTML5LIB_PRESENT: - assert registry.lookup("html5lib", "html") == HTML5TreeBuilder - - def test_lookup_by_markup_type(self): - if LXML_PRESENT: - assert registry.lookup("html") == LXMLTreeBuilder - assert registry.lookup("xml") == LXMLTreeBuilderForXML - else: - assert registry.lookup("xml") is None - if HTML5LIB_PRESENT: - assert registry.lookup("html") == HTML5TreeBuilder - else: - assert registry.lookup("html") == HTMLParserTreeBuilder - - def test_named_library(self): - if LXML_PRESENT: - assert registry.lookup("lxml", "xml") == LXMLTreeBuilderForXML - assert registry.lookup("lxml", "html") == LXMLTreeBuilder - if HTML5LIB_PRESENT: - assert registry.lookup("html5lib") == HTML5TreeBuilder - - assert registry.lookup("html.parser") == HTMLParserTreeBuilder - - def test_beautifulsoup_constructor_does_lookup(self): - with warnings.catch_warnings(record=True): - # This will create a warning about not explicitly - # specifying a parser, but we'll ignore it. - - # You can pass in a string. - BeautifulSoup("", features="html") - # Or a list of strings. - BeautifulSoup("", features=["html", "fast"]) - pass - - # You'll get an exception if BS can't find an appropriate - # builder. - with pytest.raises(ValueError): - BeautifulSoup("", features="no-such-feature") - - -class TestRegistry(object): - """Test the TreeBuilderRegistry class in general.""" - - def setup_method(self): - self.registry = TreeBuilderRegistry() - - def builder_for_features(self, *feature_list: str) -> Type[TreeBuilder]: - cls = type( - "Builder_" + "_".join(feature_list), (object,), {"features": feature_list} - ) - - self.registry.register(cls) - return cls - - def test_register_with_no_features(self): - builder = self.builder_for_features() - - # Since the builder advertises no features, you can't find it - # by looking up features. - assert self.registry.lookup("foo") is None - - # But you can find it by doing a lookup with no features, if - # this happens to be the only registered builder. - assert self.registry.lookup() == builder - - def test_register_with_features_makes_lookup_succeed(self): - builder = self.builder_for_features("foo", "bar") - assert self.registry.lookup("foo") is builder - assert self.registry.lookup("bar") is builder - - def test_lookup_fails_when_no_builder_implements_feature(self): - assert self.registry.lookup("baz") is None - - def test_lookup_gets_most_recent_registration_when_no_feature_specified(self): - self.builder_for_features("foo") - builder2 = self.builder_for_features("bar") - assert self.registry.lookup() == builder2 - - def test_lookup_fails_when_no_tree_builders_registered(self): - assert self.registry.lookup() is None - - def test_lookup_gets_most_recent_builder_supporting_all_features(self): - self.builder_for_features("foo") - self.builder_for_features("bar") - has_both_early = self.builder_for_features("foo", "bar", "baz") - has_both_late = self.builder_for_features("foo", "bar", "quux") - self.builder_for_features("bar") - self.builder_for_features("foo") - - # There are two builders featuring 'foo' and 'bar', but - # the one that also features 'quux' was registered later. - assert self.registry.lookup("foo", "bar") == has_both_late - - # There is only one builder featuring 'foo', 'bar', and 'baz'. - assert self.registry.lookup("foo", "bar", "baz") == has_both_early - - def test_lookup_fails_when_cannot_reconcile_requested_features(self): - self.builder_for_features("foo", "bar") - self.builder_for_features("foo", "baz") - assert self.registry.lookup("bar", "baz") is None diff --git a/.venv/Lib/site-packages/bs4/tests/test_css.py b/.venv/Lib/site-packages/bs4/tests/test_css.py deleted file mode 100644 index b1c4237..0000000 --- a/.venv/Lib/site-packages/bs4/tests/test_css.py +++ /dev/null @@ -1,536 +0,0 @@ -import pytest -import types - -from bs4 import ( - BeautifulSoup, - ResultSet, -) - -from typing import ( - Any, - List, - Tuple, - Type, -) - -from packaging.version import Version - -from . import ( - SoupTest, - SOUP_SIEVE_PRESENT, -) - -SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS: Type[Exception] -if SOUP_SIEVE_PRESENT: - from soupsieve import __version__, SelectorSyntaxError - - # Some behavior changes in soupsieve 2.6 that affects one of our - # tests. For the test to run under all versions of Python - # supported by Beautiful Soup (which includes versions of Python - # not supported by soupsieve 2.6) we need to check both behaviors. - SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS = SelectorSyntaxError - if Version(__version__) < Version("2.6"): - SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS = NotImplementedError - - -@pytest.mark.skipif(not SOUP_SIEVE_PRESENT, reason="Soup Sieve not installed") -class TestCSSSelectors(SoupTest): - """Test basic CSS selector functionality. - - This functionality is implemented in soupsieve, which has a much - more comprehensive test suite, so this is basically an extra check - that soupsieve works as expected. - """ - - HTML = """ - - - -The title - - - -Hello there. -
-
-

An H1

-

Some text

-

Some more text

-

An H2

-

Another

-Bob -

Another H2

-me - -span1a1 -span1a2 test - -span2a1 - - - -
- -
- - - - - - - - -

English

-

English UK

-

English US

-

French

-
- - -""" - - def setup_method(self): - self._soup = BeautifulSoup(self.HTML, "html.parser") - - def assert_css_selects( - self, selector: str, expected_ids: List[str], **kwargs: Any - ) -> None: - results = self._soup.select(selector, **kwargs) - assert isinstance(results, ResultSet) - el_ids = [el["id"] for el in results] - el_ids.sort() - expected_ids.sort() - assert expected_ids == el_ids, "Selector %s, expected [%s], got [%s]" % ( - selector, - ", ".join(expected_ids), - ", ".join(el_ids), - ) - - assertSelect = assert_css_selects - - def assert_css_select_multiple(self, *tests: Tuple[str, List[str]]): - for selector, expected_ids in tests: - self.assert_css_selects(selector, expected_ids) - - def test_precompiled(self): - sel = self._soup.css.compile("div") - - els = self._soup.select(sel) - assert len(els) == 4 - for div in els: - assert div.name == "div" - - el = self._soup.select_one(sel) - assert "main" == el["id"] - - def test_one_tag_one(self): - els = self._soup.select("title") - assert len(els) == 1 - assert els[0].name == "title" - assert els[0].contents == ["The title"] - - def test_one_tag_many(self): - els = self._soup.select("div") - assert len(els) == 4 - for div in els: - assert div.name == "div" - - el = self._soup.select_one("div") - assert "main" == el["id"] - - def test_select_one_returns_none_if_no_match(self): - match = self._soup.select_one("nonexistenttag") - assert None is match - - def test_tag_in_tag_one(self): - self.assert_css_selects("div div", ["inner", "data1"]) - - def test_tag_in_tag_many(self): - for selector in ("html div", "html body div", "body div"): - self.assert_css_selects(selector, ["data1", "main", "inner", "footer"]) - - def test_limit(self): - self.assert_css_selects("html div", ["main"], limit=1) - self.assert_css_selects("html body div", ["inner", "main"], limit=2) - self.assert_css_selects( - "body div", ["data1", "main", "inner", "footer"], limit=10 - ) - - def test_tag_no_match(self): - assert len(self._soup.select("del")) == 0 - - def test_invalid_tag(self): - with pytest.raises(SelectorSyntaxError): - self._soup.select("tag%t") - - def test_select_dashed_tag_ids(self): - self.assert_css_selects("custom-dashed-tag", ["dash1", "dash2"]) - - def test_select_dashed_by_id(self): - dashed = self._soup.select('custom-dashed-tag[id="dash2"]') - assert dashed[0].name == "custom-dashed-tag" - assert dashed[0]["id"] == "dash2" - - def test_dashed_tag_text(self): - assert self._soup.select("body > custom-dashed-tag")[0].text == "Hello there." - - def test_select_dashed_matches_find_all(self): - assert self._soup.select("custom-dashed-tag") == self._soup.find_all( - "custom-dashed-tag" - ) - - def test_header_tags(self): - self.assert_css_select_multiple( - ("h1", ["header1"]), - ("h2", ["header2", "header3"]), - ) - - def test_class_one(self): - for selector in (".onep", "p.onep", "html p.onep"): - els = self._soup.select(selector) - assert len(els) == 1 - assert els[0].name == "p" - assert els[0]["class"] == ["onep"] - - def test_class_mismatched_tag(self): - els = self._soup.select("div.onep") - assert len(els) == 0 - - def test_one_id(self): - for selector in ("div#inner", "#inner", "div div#inner"): - self.assert_css_selects(selector, ["inner"]) - - def test_bad_id(self): - els = self._soup.select("#doesnotexist") - assert len(els) == 0 - - def test_items_in_id(self): - els = self._soup.select("div#inner p") - assert len(els) == 3 - for el in els: - assert el.name == "p" - assert els[1]["class"] == ["onep"] - assert not els[0].has_attr("class") - - def test_a_bunch_of_emptys(self): - for selector in ("div#main del", "div#main div.oops", "div div#main"): - assert len(self._soup.select(selector)) == 0 - - def test_multi_class_support(self): - for selector in ( - ".class1", - "p.class1", - ".class2", - "p.class2", - ".class3", - "p.class3", - "html p.class2", - "div#inner .class2", - ): - self.assert_css_selects(selector, ["pmulti"]) - - def test_multi_class_selection(self): - for selector in (".class1.class3", ".class3.class2", ".class1.class2.class3"): - self.assert_css_selects(selector, ["pmulti"]) - - def test_child_selector(self): - self.assert_css_selects(".s1 > a", ["s1a1", "s1a2"]) - self.assert_css_selects(".s1 > a span", ["s1a2s1"]) - - def test_child_selector_id(self): - self.assert_css_selects(".s1 > a#s1a2 span", ["s1a2s1"]) - - def test_attribute_equals(self): - self.assert_css_select_multiple( - ('p[class="onep"]', ["p1"]), - ('p[id="p1"]', ["p1"]), - ('[class="onep"]', ["p1"]), - ('[id="p1"]', ["p1"]), - ('link[rel="stylesheet"]', ["l1"]), - ('link[type="text/css"]', ["l1"]), - ('link[href="blah.css"]', ["l1"]), - ('link[href="no-blah.css"]', []), - ('[rel="stylesheet"]', ["l1"]), - ('[type="text/css"]', ["l1"]), - ('[href="blah.css"]', ["l1"]), - ('[href="no-blah.css"]', []), - ('p[href="no-blah.css"]', []), - ('[href="no-blah.css"]', []), - ) - - def test_attribute_tilde(self): - self.assert_css_select_multiple( - ('p[class~="class1"]', ["pmulti"]), - ('p[class~="class2"]', ["pmulti"]), - ('p[class~="class3"]', ["pmulti"]), - ('[class~="class1"]', ["pmulti"]), - ('[class~="class2"]', ["pmulti"]), - ('[class~="class3"]', ["pmulti"]), - ('a[rel~="friend"]', ["bob"]), - ('a[rel~="met"]', ["bob"]), - ('[rel~="friend"]', ["bob"]), - ('[rel~="met"]', ["bob"]), - ) - - def test_attribute_startswith(self): - self.assert_css_select_multiple( - ('[rel^="style"]', ["l1"]), - ('link[rel^="style"]', ["l1"]), - ('notlink[rel^="notstyle"]', []), - ('[rel^="notstyle"]', []), - ('link[rel^="notstyle"]', []), - ('link[href^="bla"]', ["l1"]), - ('a[href^="http://"]', ["bob", "me"]), - ('[href^="http://"]', ["bob", "me"]), - ('[id^="p"]', ["pmulti", "p1"]), - ('[id^="m"]', ["me", "main"]), - ('div[id^="m"]', ["main"]), - ('a[id^="m"]', ["me"]), - ('div[data-tag^="dashed"]', ["data1"]), - ) - - def test_attribute_endswith(self): - self.assert_css_select_multiple( - ('[href$=".css"]', ["l1"]), - ('link[href$=".css"]', ["l1"]), - ('link[id$="1"]', ["l1"]), - ( - '[id$="1"]', - ["data1", "l1", "p1", "header1", "s1a1", "s2a1", "s1a2s1", "dash1"], - ), - ('div[id$="1"]', ["data1"]), - ('[id$="noending"]', []), - ) - - def test_attribute_contains(self): - self.assert_css_select_multiple( - # From test_attribute_startswith - ('[rel*="style"]', ["l1"]), - ('link[rel*="style"]', ["l1"]), - ('notlink[rel*="notstyle"]', []), - ('[rel*="notstyle"]', []), - ('link[rel*="notstyle"]', []), - ('link[href*="bla"]', ["l1"]), - ('[href*="http://"]', ["bob", "me"]), - ('[id*="p"]', ["pmulti", "p1"]), - ('div[id*="m"]', ["main"]), - ('a[id*="m"]', ["me"]), - # From test_attribute_endswith - ('[href*=".css"]', ["l1"]), - ('link[href*=".css"]', ["l1"]), - ('link[id*="1"]', ["l1"]), - ( - '[id*="1"]', - [ - "data1", - "l1", - "p1", - "header1", - "s1a1", - "s1a2", - "s2a1", - "s1a2s1", - "dash1", - ], - ), - ('div[id*="1"]', ["data1"]), - ('[id*="noending"]', []), - # New for this test - ('[href*="."]', ["bob", "me", "l1"]), - ('a[href*="."]', ["bob", "me"]), - ('link[href*="."]', ["l1"]), - ('div[id*="n"]', ["main", "inner"]), - ('div[id*="nn"]', ["inner"]), - ('div[data-tag*="edval"]', ["data1"]), - ) - - def test_attribute_exact_or_hypen(self): - self.assert_css_select_multiple( - ('p[lang|="en"]', ["lang-en", "lang-en-gb", "lang-en-us"]), - ('[lang|="en"]', ["lang-en", "lang-en-gb", "lang-en-us"]), - ('p[lang|="fr"]', ["lang-fr"]), - ('p[lang|="gb"]', []), - ) - - def test_attribute_exists(self): - self.assert_css_select_multiple( - ("[rel]", ["l1", "bob", "me"]), - ("link[rel]", ["l1"]), - ("a[rel]", ["bob", "me"]), - ("[lang]", ["lang-en", "lang-en-gb", "lang-en-us", "lang-fr"]), - ("p[class]", ["p1", "pmulti"]), - ("[blah]", []), - ("p[blah]", []), - ("div[data-tag]", ["data1"]), - ) - - def test_quoted_space_in_selector_name(self): - html = """
nope
-
yes
- """ - soup = BeautifulSoup(html, "html.parser") - [chosen] = soup.select('div[style="display: right"]') - assert "yes" == chosen.string - - def test_unsupported_pseudoclass(self): - with pytest.raises(SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS): - self._soup.select("a:no-such-pseudoclass") - - with pytest.raises(SelectorSyntaxError): - self._soup.select("a:nth-of-type(a)") - - def test_nth_of_type(self): - # Try to select first paragraph - els = self._soup.select("div#inner p:nth-of-type(1)") - assert len(els) == 1 - assert els[0].string == "Some text" - - # Try to select third paragraph - els = self._soup.select("div#inner p:nth-of-type(3)") - assert len(els) == 1 - assert els[0].string == "Another" - - # Try to select (non-existent!) fourth paragraph - els = self._soup.select("div#inner p:nth-of-type(4)") - assert len(els) == 0 - - # Zero will select no tags. - els = self._soup.select("div p:nth-of-type(0)") - assert len(els) == 0 - - def test_nth_of_type_direct_descendant(self): - els = self._soup.select("div#inner > p:nth-of-type(1)") - assert len(els) == 1 - assert els[0].string == "Some text" - - def test_id_child_selector_nth_of_type(self): - self.assert_css_selects("#inner > p:nth-of-type(2)", ["p1"]) - - def test_select_on_element(self): - # Other tests operate on the tree; this operates on an element - # within the tree. - inner = self._soup.find("div", id="main") - selected = inner.select("div") - # The
tag was selected. The