This is page 26 of 168. Use http://codebase.md/romanshablio/mcp_server?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .DS_Store
├── .venv
│ ├── __pycache__
│ │ └── hello.cpython-312.pyc
│ ├── bin
│ │ ├── activate
│ │ ├── activate.csh
│ │ ├── activate.fish
│ │ ├── Activate.ps1
│ │ ├── flask
│ │ ├── normalizer
│ │ ├── pip
│ │ ├── pip3
│ │ ├── pip3.12
│ │ ├── python
│ │ ├── python3
│ │ └── python3.12
│ ├── hello.py
│ ├── lib
│ │ └── python3.12
│ │ └── site-packages
│ │ ├── beautifulsoup4-4.12.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ ├── AUTHORS
│ │ │ │ └── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── blinker
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _utilities.cpython-312.pyc
│ │ │ │ └── base.cpython-312.pyc
│ │ │ ├── _utilities.py
│ │ │ ├── base.py
│ │ │ └── py.typed
│ │ ├── blinker-1.8.2.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── bs4
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── css.cpython-312.pyc
│ │ │ │ ├── dammit.cpython-312.pyc
│ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ ├── element.cpython-312.pyc
│ │ │ │ └── formatter.cpython-312.pyc
│ │ │ ├── builder
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _html5lib.cpython-312.pyc
│ │ │ │ │ ├── _htmlparser.cpython-312.pyc
│ │ │ │ │ └── _lxml.cpython-312.pyc
│ │ │ │ ├── _html5lib.py
│ │ │ │ ├── _htmlparser.py
│ │ │ │ └── _lxml.py
│ │ │ ├── css.py
│ │ │ ├── dammit.py
│ │ │ ├── diagnose.py
│ │ │ ├── element.py
│ │ │ ├── formatter.py
│ │ │ └── tests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── test_builder_registry.cpython-312.pyc
│ │ │ │ ├── test_builder.cpython-312.pyc
│ │ │ │ ├── test_css.cpython-312.pyc
│ │ │ │ ├── test_dammit.cpython-312.pyc
│ │ │ │ ├── test_docs.cpython-312.pyc
│ │ │ │ ├── test_element.cpython-312.pyc
│ │ │ │ ├── test_formatter.cpython-312.pyc
│ │ │ │ ├── test_fuzz.cpython-312.pyc
│ │ │ │ ├── test_html5lib.cpython-312.pyc
│ │ │ │ ├── test_htmlparser.cpython-312.pyc
│ │ │ │ ├── test_lxml.cpython-312.pyc
│ │ │ │ ├── test_navigablestring.cpython-312.pyc
│ │ │ │ ├── test_pageelement.cpython-312.pyc
│ │ │ │ ├── test_soup.cpython-312.pyc
│ │ │ │ ├── test_tag.cpython-312.pyc
│ │ │ │ └── test_tree.cpython-312.pyc
│ │ │ ├── fuzz
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase
│ │ │ │ ├── crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase
│ │ │ │ └── crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase
│ │ │ ├── test_builder_registry.py
│ │ │ ├── test_builder.py
│ │ │ ├── test_css.py
│ │ │ ├── test_dammit.py
│ │ │ ├── test_docs.py
│ │ │ ├── test_element.py
│ │ │ ├── test_formatter.py
│ │ │ ├── test_fuzz.py
│ │ │ ├── test_html5lib.py
│ │ │ ├── test_htmlparser.py
│ │ │ ├── test_lxml.py
│ │ │ ├── test_navigablestring.py
│ │ │ ├── test_pageelement.py
│ │ │ ├── test_soup.py
│ │ │ ├── test_tag.py
│ │ │ └── test_tree.py
│ │ ├── certifi
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── core.cpython-312.pyc
│ │ │ ├── cacert.pem
│ │ │ ├── core.py
│ │ │ └── py.typed
│ │ ├── certifi-2024.8.30.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── charset_normalizer
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── cd.cpython-312.pyc
│ │ │ │ ├── constant.cpython-312.pyc
│ │ │ │ ├── legacy.cpython-312.pyc
│ │ │ │ ├── md.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── version.cpython-312.pyc
│ │ │ ├── api.py
│ │ │ ├── cd.py
│ │ │ ├── cli
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ └── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── __main__.cpython-312.pyc
│ │ │ ├── constant.py
│ │ │ ├── legacy.py
│ │ │ ├── md__mypyc.cpython-312-darwin.so
│ │ │ ├── md.cpython-312-darwin.so
│ │ │ ├── md.py
│ │ │ ├── models.py
│ │ │ ├── py.typed
│ │ │ ├── utils.py
│ │ │ └── version.py
│ │ ├── charset_normalizer-3.4.0.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── click
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ ├── _termui_impl.cpython-312.pyc
│ │ │ │ ├── _textwrap.cpython-312.pyc
│ │ │ │ ├── _winconsole.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── decorators.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formatting.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── shell_completion.cpython-312.pyc
│ │ │ │ ├── termui.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── types.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── _compat.py
│ │ │ ├── _termui_impl.py
│ │ │ ├── _textwrap.py
│ │ │ ├── _winconsole.py
│ │ │ ├── core.py
│ │ │ ├── decorators.py
│ │ │ ├── exceptions.py
│ │ │ ├── formatting.py
│ │ │ ├── globals.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── shell_completion.py
│ │ │ ├── termui.py
│ │ │ ├── testing.py
│ │ │ ├── types.py
│ │ │ └── utils.py
│ │ ├── click-8.1.7.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.rst
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── fake_useragent
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ ├── fake.cpython-312.pyc
│ │ │ │ ├── log.cpython-312.pyc
│ │ │ │ ├── settings.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── data
│ │ │ │ └── browsers.json
│ │ │ ├── errors.py
│ │ │ ├── fake.py
│ │ │ ├── log.py
│ │ │ ├── settings.py
│ │ │ └── utils.py
│ │ ├── fake_useragent-1.5.1.dist-info
│ │ │ ├── AUTHORS
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── flask
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ ├── cli.cpython-312.pyc
│ │ │ │ ├── config.cpython-312.pyc
│ │ │ │ ├── ctx.cpython-312.pyc
│ │ │ │ ├── debughelpers.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── helpers.cpython-312.pyc
│ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── signals.cpython-312.pyc
│ │ │ │ ├── templating.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── typing.cpython-312.pyc
│ │ │ │ ├── views.cpython-312.pyc
│ │ │ │ └── wrappers.cpython-312.pyc
│ │ │ ├── app.py
│ │ │ ├── blueprints.py
│ │ │ ├── cli.py
│ │ │ ├── config.py
│ │ │ ├── ctx.py
│ │ │ ├── debughelpers.py
│ │ │ ├── globals.py
│ │ │ ├── helpers.py
│ │ │ ├── json
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ └── tag.cpython-312.pyc
│ │ │ │ ├── provider.py
│ │ │ │ └── tag.py
│ │ │ ├── logging.py
│ │ │ ├── py.typed
│ │ │ ├── sansio
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ │ └── scaffold.cpython-312.pyc
│ │ │ │ ├── app.py
│ │ │ │ ├── blueprints.py
│ │ │ │ ├── README.md
│ │ │ │ └── scaffold.py
│ │ │ ├── sessions.py
│ │ │ ├── signals.py
│ │ │ ├── templating.py
│ │ │ ├── testing.py
│ │ │ ├── typing.py
│ │ │ ├── views.py
│ │ │ └── wrappers.py
│ │ ├── flask-3.0.3.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── idna
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ ├── codec.py
│ │ │ ├── compat.py
│ │ │ ├── core.py
│ │ │ ├── idnadata.py
│ │ │ ├── intranges.py
│ │ │ ├── package_data.py
│ │ │ ├── py.typed
│ │ │ └── uts46data.py
│ │ ├── idna-3.10.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── itsdangerous
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ ├── exc.cpython-312.pyc
│ │ │ │ ├── serializer.cpython-312.pyc
│ │ │ │ ├── signer.cpython-312.pyc
│ │ │ │ ├── timed.cpython-312.pyc
│ │ │ │ └── url_safe.cpython-312.pyc
│ │ │ ├── _json.py
│ │ │ ├── encoding.py
│ │ │ ├── exc.py
│ │ │ ├── py.typed
│ │ │ ├── serializer.py
│ │ │ ├── signer.py
│ │ │ ├── timed.py
│ │ │ └── url_safe.py
│ │ ├── itsdangerous-2.2.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── jinja2
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _identifier.cpython-312.pyc
│ │ │ │ ├── async_utils.cpython-312.pyc
│ │ │ │ ├── bccache.cpython-312.pyc
│ │ │ │ ├── compiler.cpython-312.pyc
│ │ │ │ ├── constants.cpython-312.pyc
│ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ ├── defaults.cpython-312.pyc
│ │ │ │ ├── environment.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ ├── filters.cpython-312.pyc
│ │ │ │ ├── idtracking.cpython-312.pyc
│ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ ├── loaders.cpython-312.pyc
│ │ │ │ ├── meta.cpython-312.pyc
│ │ │ │ ├── nativetypes.cpython-312.pyc
│ │ │ │ ├── nodes.cpython-312.pyc
│ │ │ │ ├── optimizer.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── runtime.cpython-312.pyc
│ │ │ │ ├── sandbox.cpython-312.pyc
│ │ │ │ ├── tests.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── visitor.cpython-312.pyc
│ │ │ ├── _identifier.py
│ │ │ ├── async_utils.py
│ │ │ ├── bccache.py
│ │ │ ├── compiler.py
│ │ │ ├── constants.py
│ │ │ ├── debug.py
│ │ │ ├── defaults.py
│ │ │ ├── environment.py
│ │ │ ├── exceptions.py
│ │ │ ├── ext.py
│ │ │ ├── filters.py
│ │ │ ├── idtracking.py
│ │ │ ├── lexer.py
│ │ │ ├── loaders.py
│ │ │ ├── meta.py
│ │ │ ├── nativetypes.py
│ │ │ ├── nodes.py
│ │ │ ├── optimizer.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── runtime.py
│ │ │ ├── sandbox.py
│ │ │ ├── tests.py
│ │ │ ├── utils.py
│ │ │ └── visitor.py
│ │ ├── jinja2-3.1.4.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── lxml
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _elementpath.cpython-312.pyc
│ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ ├── cssselect.cpython-312.pyc
│ │ │ │ ├── doctestcompare.cpython-312.pyc
│ │ │ │ ├── ElementInclude.cpython-312.pyc
│ │ │ │ ├── pyclasslookup.cpython-312.pyc
│ │ │ │ ├── sax.cpython-312.pyc
│ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ ├── _elementpath.cpython-312-darwin.so
│ │ │ ├── _elementpath.py
│ │ │ ├── apihelpers.pxi
│ │ │ ├── builder.cpython-312-darwin.so
│ │ │ ├── builder.py
│ │ │ ├── classlookup.pxi
│ │ │ ├── cleanup.pxi
│ │ │ ├── cssselect.py
│ │ │ ├── debug.pxi
│ │ │ ├── docloader.pxi
│ │ │ ├── doctestcompare.py
│ │ │ ├── dtd.pxi
│ │ │ ├── ElementInclude.py
│ │ │ ├── etree_api.h
│ │ │ ├── etree.cpython-312-darwin.so
│ │ │ ├── etree.h
│ │ │ ├── etree.pyx
│ │ │ ├── extensions.pxi
│ │ │ ├── html
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _diffcommand.cpython-312.pyc
│ │ │ │ │ ├── _html5builder.cpython-312.pyc
│ │ │ │ │ ├── _setmixin.cpython-312.pyc
│ │ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ │ ├── clean.cpython-312.pyc
│ │ │ │ │ ├── defs.cpython-312.pyc
│ │ │ │ │ ├── diff.cpython-312.pyc
│ │ │ │ │ ├── ElementSoup.cpython-312.pyc
│ │ │ │ │ ├── formfill.cpython-312.pyc
│ │ │ │ │ ├── html5parser.cpython-312.pyc
│ │ │ │ │ ├── soupparser.cpython-312.pyc
│ │ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ │ ├── _diffcommand.py
│ │ │ │ ├── _html5builder.py
│ │ │ │ ├── _setmixin.py
│ │ │ │ ├── builder.py
│ │ │ │ ├── clean.py
│ │ │ │ ├── defs.py
│ │ │ │ ├── diff.cpython-312-darwin.so
│ │ │ │ ├── diff.py
│ │ │ │ ├── ElementSoup.py
│ │ │ │ ├── formfill.py
│ │ │ │ ├── html5parser.py
│ │ │ │ ├── soupparser.py
│ │ │ │ └── usedoctest.py
│ │ │ ├── includes
│ │ │ │ ├── __init__.pxd
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── c14n.pxd
│ │ │ │ ├── config.pxd
│ │ │ │ ├── dtdvalid.pxd
│ │ │ │ ├── etree_defs.h
│ │ │ │ ├── etreepublic.pxd
│ │ │ │ ├── extlibs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── libcharset.h
│ │ │ │ │ ├── localcharset.h
│ │ │ │ │ ├── zconf.h
│ │ │ │ │ └── zlib.h
│ │ │ │ ├── htmlparser.pxd
│ │ │ │ ├── libexslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── exslt.h
│ │ │ │ │ ├── exsltconfig.h
│ │ │ │ │ └── exsltexports.h
│ │ │ │ ├── libxml
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── c14n.h
│ │ │ │ │ ├── catalog.h
│ │ │ │ │ ├── chvalid.h
│ │ │ │ │ ├── debugXML.h
│ │ │ │ │ ├── dict.h
│ │ │ │ │ ├── encoding.h
│ │ │ │ │ ├── entities.h
│ │ │ │ │ ├── globals.h
│ │ │ │ │ ├── hash.h
│ │ │ │ │ ├── HTMLparser.h
│ │ │ │ │ ├── HTMLtree.h
│ │ │ │ │ ├── list.h
│ │ │ │ │ ├── nanoftp.h
│ │ │ │ │ ├── nanohttp.h
│ │ │ │ │ ├── parser.h
│ │ │ │ │ ├── parserInternals.h
│ │ │ │ │ ├── relaxng.h
│ │ │ │ │ ├── SAX.h
│ │ │ │ │ ├── SAX2.h
│ │ │ │ │ ├── schemasInternals.h
│ │ │ │ │ ├── schematron.h
│ │ │ │ │ ├── threads.h
│ │ │ │ │ ├── tree.h
│ │ │ │ │ ├── uri.h
│ │ │ │ │ ├── valid.h
│ │ │ │ │ ├── xinclude.h
│ │ │ │ │ ├── xlink.h
│ │ │ │ │ ├── xmlautomata.h
│ │ │ │ │ ├── xmlerror.h
│ │ │ │ │ ├── xmlexports.h
│ │ │ │ │ ├── xmlIO.h
│ │ │ │ │ ├── xmlmemory.h
│ │ │ │ │ ├── xmlmodule.h
│ │ │ │ │ ├── xmlreader.h
│ │ │ │ │ ├── xmlregexp.h
│ │ │ │ │ ├── xmlsave.h
│ │ │ │ │ ├── xmlschemas.h
│ │ │ │ │ ├── xmlschemastypes.h
│ │ │ │ │ ├── xmlstring.h
│ │ │ │ │ ├── xmlunicode.h
│ │ │ │ │ ├── xmlversion.h
│ │ │ │ │ ├── xmlwriter.h
│ │ │ │ │ ├── xpath.h
│ │ │ │ │ ├── xpathInternals.h
│ │ │ │ │ └── xpointer.h
│ │ │ │ ├── libxslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── attributes.h
│ │ │ │ │ ├── documents.h
│ │ │ │ │ ├── extensions.h
│ │ │ │ │ ├── extra.h
│ │ │ │ │ ├── functions.h
│ │ │ │ │ ├── imports.h
│ │ │ │ │ ├── keys.h
│ │ │ │ │ ├── namespaces.h
│ │ │ │ │ ├── numbersInternals.h
│ │ │ │ │ ├── pattern.h
│ │ │ │ │ ├── preproc.h
│ │ │ │ │ ├── security.h
│ │ │ │ │ ├── templates.h
│ │ │ │ │ ├── transform.h
│ │ │ │ │ ├── variables.h
│ │ │ │ │ ├── xslt.h
│ │ │ │ │ ├── xsltconfig.h
│ │ │ │ │ ├── xsltexports.h
│ │ │ │ │ ├── xsltInternals.h
│ │ │ │ │ ├── xsltlocale.h
│ │ │ │ │ └── xsltutils.h
│ │ │ │ ├── lxml-version.h
│ │ │ │ ├── relaxng.pxd
│ │ │ │ ├── schematron.pxd
│ │ │ │ ├── tree.pxd
│ │ │ │ ├── uri.pxd
│ │ │ │ ├── xinclude.pxd
│ │ │ │ ├── xmlerror.pxd
│ │ │ │ ├── xmlparser.pxd
│ │ │ │ ├── xmlschema.pxd
│ │ │ │ ├── xpath.pxd
│ │ │ │ └── xslt.pxd
│ │ │ ├── isoschematron
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ └── resources
│ │ │ │ ├── rng
│ │ │ │ │ └── iso-schematron.rng
│ │ │ │ └── xsl
│ │ │ │ ├── iso-schematron-xslt1
│ │ │ │ │ ├── iso_abstract_expand.xsl
│ │ │ │ │ ├── iso_dsdl_include.xsl
│ │ │ │ │ ├── iso_schematron_message.xsl
│ │ │ │ │ ├── iso_schematron_skeleton_for_xslt1.xsl
│ │ │ │ │ ├── iso_svrl_for_xslt1.xsl
│ │ │ │ │ └── readme.txt
│ │ │ │ ├── RNG2Schtrn.xsl
│ │ │ │ └── XSD2Schtrn.xsl
│ │ │ ├── iterparse.pxi
│ │ │ ├── lxml.etree_api.h
│ │ │ ├── lxml.etree.h
│ │ │ ├── nsclasses.pxi
│ │ │ ├── objectify.cpython-312-darwin.so
│ │ │ ├── objectify.pyx
│ │ │ ├── objectpath.pxi
│ │ │ ├── parser.pxi
│ │ │ ├── parsertarget.pxi
│ │ │ ├── proxy.pxi
│ │ │ ├── public-api.pxi
│ │ │ ├── pyclasslookup.py
│ │ │ ├── readonlytree.pxi
│ │ │ ├── relaxng.pxi
│ │ │ ├── sax.cpython-312-darwin.so
│ │ │ ├── sax.py
│ │ │ ├── saxparser.pxi
│ │ │ ├── schematron.pxi
│ │ │ ├── serializer.pxi
│ │ │ ├── usedoctest.py
│ │ │ ├── xinclude.pxi
│ │ │ ├── xmlerror.pxi
│ │ │ ├── xmlid.pxi
│ │ │ ├── xmlschema.pxi
│ │ │ ├── xpath.pxi
│ │ │ ├── xslt.pxi
│ │ │ └── xsltext.pxi
│ │ ├── lxml-5.3.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── LICENSES.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── markupsafe
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── _native.cpython-312.pyc
│ │ │ ├── _native.py
│ │ │ ├── _speedups.c
│ │ │ ├── _speedups.cpython-312-darwin.so
│ │ │ ├── _speedups.pyi
│ │ │ └── py.typed
│ │ ├── MarkupSafe-3.0.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── pip
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pip-runner__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── __pip-runner__.cpython-312.pyc
│ │ │ ├── _internal
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── build_env.cpython-312.pyc
│ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ ├── pyproject.cpython-312.pyc
│ │ │ │ │ ├── self_outdated_check.cpython-312.pyc
│ │ │ │ │ └── wheel_builder.cpython-312.pyc
│ │ │ │ ├── build_env.py
│ │ │ │ ├── cache.py
│ │ │ │ ├── cli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── autocompletion.cpython-312.pyc
│ │ │ │ │ │ ├── base_command.cpython-312.pyc
│ │ │ │ │ │ ├── cmdoptions.cpython-312.pyc
│ │ │ │ │ │ ├── command_context.cpython-312.pyc
│ │ │ │ │ │ ├── index_command.cpython-312.pyc
│ │ │ │ │ │ ├── main_parser.cpython-312.pyc
│ │ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bars.cpython-312.pyc
│ │ │ │ │ │ ├── req_command.cpython-312.pyc
│ │ │ │ │ │ ├── spinners.cpython-312.pyc
│ │ │ │ │ │ └── status_codes.cpython-312.pyc
│ │ │ │ │ ├── autocompletion.py
│ │ │ │ │ ├── base_command.py
│ │ │ │ │ ├── cmdoptions.py
│ │ │ │ │ ├── command_context.py
│ │ │ │ │ ├── index_command.py
│ │ │ │ │ ├── main_parser.py
│ │ │ │ │ ├── main.py
│ │ │ │ │ ├── parser.py
│ │ │ │ │ ├── progress_bars.py
│ │ │ │ │ ├── req_command.py
│ │ │ │ │ ├── spinners.py
│ │ │ │ │ └── status_codes.py
│ │ │ │ ├── commands
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── completion.cpython-312.pyc
│ │ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ ├── hash.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── inspect.cpython-312.pyc
│ │ │ │ │ │ ├── install.cpython-312.pyc
│ │ │ │ │ │ ├── list.cpython-312.pyc
│ │ │ │ │ │ ├── search.cpython-312.pyc
│ │ │ │ │ │ ├── show.cpython-312.pyc
│ │ │ │ │ │ ├── uninstall.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── completion.py
│ │ │ │ │ ├── configuration.py
│ │ │ │ │ ├── debug.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── hash.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── inspect.py
│ │ │ │ │ ├── install.py
│ │ │ │ │ ├── list.py
│ │ │ │ │ ├── search.py
│ │ │ │ │ ├── show.py
│ │ │ │ │ ├── uninstall.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── configuration.py
│ │ │ │ ├── distributions
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── installed.cpython-312.pyc
│ │ │ │ │ │ ├── sdist.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── installed.py
│ │ │ │ │ ├── sdist.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── index
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── collector.cpython-312.pyc
│ │ │ │ │ │ ├── package_finder.cpython-312.pyc
│ │ │ │ │ │ └── sources.cpython-312.pyc
│ │ │ │ │ ├── collector.py
│ │ │ │ │ ├── package_finder.py
│ │ │ │ │ └── sources.py
│ │ │ │ ├── locations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _distutils.cpython-312.pyc
│ │ │ │ │ │ ├── _sysconfig.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── _distutils.py
│ │ │ │ │ ├── _sysconfig.py
│ │ │ │ │ └── base.py
│ │ │ │ ├── main.py
│ │ │ │ ├── metadata
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ └── pkg_resources.cpython-312.pyc
│ │ │ │ │ ├── _json.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── importlib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ │ ├── _dists.cpython-312.pyc
│ │ │ │ │ │ │ └── _envs.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.py
│ │ │ │ │ │ ├── _dists.py
│ │ │ │ │ │ └── _envs.py
│ │ │ │ │ └── pkg_resources.py
│ │ │ │ ├── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── candidate.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url.cpython-312.pyc
│ │ │ │ │ │ ├── format_control.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── installation_report.cpython-312.pyc
│ │ │ │ │ │ ├── link.cpython-312.pyc
│ │ │ │ │ │ ├── scheme.cpython-312.pyc
│ │ │ │ │ │ ├── search_scope.cpython-312.pyc
│ │ │ │ │ │ ├── selection_prefs.cpython-312.pyc
│ │ │ │ │ │ ├── target_python.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── candidate.py
│ │ │ │ │ ├── direct_url.py
│ │ │ │ │ ├── format_control.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── installation_report.py
│ │ │ │ │ ├── link.py
│ │ │ │ │ ├── scheme.py
│ │ │ │ │ ├── search_scope.py
│ │ │ │ │ ├── selection_prefs.py
│ │ │ │ │ ├── target_python.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── network
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── lazy_wheel.cpython-312.pyc
│ │ │ │ │ │ ├── session.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── xmlrpc.cpython-312.pyc
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── lazy_wheel.py
│ │ │ │ │ ├── session.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── xmlrpc.py
│ │ │ │ ├── operations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ └── prepare.cpython-312.pyc
│ │ │ │ │ ├── build
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── build_tracker.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_legacy.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── build_tracker.py
│ │ │ │ │ │ ├── metadata_editable.py
│ │ │ │ │ │ ├── metadata_legacy.py
│ │ │ │ │ │ ├── metadata.py
│ │ │ │ │ │ ├── wheel_editable.py
│ │ │ │ │ │ ├── wheel_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── install
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── editable_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── editable_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ └── prepare.py
│ │ │ │ ├── pyproject.py
│ │ │ │ ├── req
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── constructors.cpython-312.pyc
│ │ │ │ │ │ ├── req_file.cpython-312.pyc
│ │ │ │ │ │ ├── req_install.cpython-312.pyc
│ │ │ │ │ │ ├── req_set.cpython-312.pyc
│ │ │ │ │ │ └── req_uninstall.cpython-312.pyc
│ │ │ │ │ ├── constructors.py
│ │ │ │ │ ├── req_file.py
│ │ │ │ │ ├── req_install.py
│ │ │ │ │ ├── req_set.py
│ │ │ │ │ └── req_uninstall.py
│ │ │ │ ├── resolution
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── legacy
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ │ └── resolver.py
│ │ │ │ │ └── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── candidates.cpython-312.pyc
│ │ │ │ │ │ ├── factory.cpython-312.pyc
│ │ │ │ │ │ ├── found_candidates.cpython-312.pyc
│ │ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ │ ├── reporter.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── candidates.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── found_candidates.py
│ │ │ │ │ ├── provider.py
│ │ │ │ │ ├── reporter.py
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ └── resolver.py
│ │ │ │ ├── self_outdated_check.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _jaraco_text.cpython-312.pyc
│ │ │ │ │ │ ├── _log.cpython-312.pyc
│ │ │ │ │ │ ├── appdirs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── compatibility_tags.cpython-312.pyc
│ │ │ │ │ │ ├── datetime.cpython-312.pyc
│ │ │ │ │ │ ├── deprecation.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url_helpers.cpython-312.pyc
│ │ │ │ │ │ ├── egg_link.cpython-312.pyc
│ │ │ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ │ │ ├── entrypoints.cpython-312.pyc
│ │ │ │ │ │ ├── filesystem.cpython-312.pyc
│ │ │ │ │ │ ├── filetypes.cpython-312.pyc
│ │ │ │ │ │ ├── glibc.cpython-312.pyc
│ │ │ │ │ │ ├── hashes.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── misc.cpython-312.pyc
│ │ │ │ │ │ ├── packaging.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── setuptools_build.cpython-312.pyc
│ │ │ │ │ │ ├── subprocess.cpython-312.pyc
│ │ │ │ │ │ ├── temp_dir.cpython-312.pyc
│ │ │ │ │ │ ├── unpacking.cpython-312.pyc
│ │ │ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ │ │ ├── virtualenv.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── _jaraco_text.py
│ │ │ │ │ ├── _log.py
│ │ │ │ │ ├── appdirs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── compatibility_tags.py
│ │ │ │ │ ├── datetime.py
│ │ │ │ │ ├── deprecation.py
│ │ │ │ │ ├── direct_url_helpers.py
│ │ │ │ │ ├── egg_link.py
│ │ │ │ │ ├── encoding.py
│ │ │ │ │ ├── entrypoints.py
│ │ │ │ │ ├── filesystem.py
│ │ │ │ │ ├── filetypes.py
│ │ │ │ │ ├── glibc.py
│ │ │ │ │ ├── hashes.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── packaging.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── setuptools_build.py
│ │ │ │ │ ├── subprocess.py
│ │ │ │ │ ├── temp_dir.py
│ │ │ │ │ ├── unpacking.py
│ │ │ │ │ ├── urls.py
│ │ │ │ │ ├── virtualenv.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── vcs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── bazaar.cpython-312.pyc
│ │ │ │ │ │ ├── git.cpython-312.pyc
│ │ │ │ │ │ ├── mercurial.cpython-312.pyc
│ │ │ │ │ │ ├── subversion.cpython-312.pyc
│ │ │ │ │ │ └── versioncontrol.cpython-312.pyc
│ │ │ │ │ ├── bazaar.py
│ │ │ │ │ ├── git.py
│ │ │ │ │ ├── mercurial.py
│ │ │ │ │ ├── subversion.py
│ │ │ │ │ └── versioncontrol.py
│ │ │ │ └── wheel_builder.py
│ │ │ ├── _vendor
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ └── typing_extensions.cpython-312.pyc
│ │ │ │ ├── cachecontrol
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _cmd.cpython-312.pyc
│ │ │ │ │ │ ├── adapter.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── controller.cpython-312.pyc
│ │ │ │ │ │ ├── filewrapper.cpython-312.pyc
│ │ │ │ │ │ ├── heuristics.cpython-312.pyc
│ │ │ │ │ │ ├── serialize.cpython-312.pyc
│ │ │ │ │ │ └── wrapper.cpython-312.pyc
│ │ │ │ │ ├── _cmd.py
│ │ │ │ │ ├── adapter.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── caches
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── file_cache.cpython-312.pyc
│ │ │ │ │ │ │ └── redis_cache.cpython-312.pyc
│ │ │ │ │ │ ├── file_cache.py
│ │ │ │ │ │ └── redis_cache.py
│ │ │ │ │ ├── controller.py
│ │ │ │ │ ├── filewrapper.py
│ │ │ │ │ ├── heuristics.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── serialize.py
│ │ │ │ │ └── wrapper.py
│ │ │ │ ├── certifi
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── core.cpython-312.pyc
│ │ │ │ │ ├── cacert.pem
│ │ │ │ │ ├── core.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── distlib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── database.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── locators.cpython-312.pyc
│ │ │ │ │ │ ├── manifest.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── resources.cpython-312.pyc
│ │ │ │ │ │ ├── scripts.cpython-312.pyc
│ │ │ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── database.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── locators.py
│ │ │ │ │ ├── manifest.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ ├── scripts.py
│ │ │ │ │ ├── t32.exe
│ │ │ │ │ ├── t64-arm.exe
│ │ │ │ │ ├── t64.exe
│ │ │ │ │ ├── util.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ ├── w32.exe
│ │ │ │ │ ├── w64-arm.exe
│ │ │ │ │ ├── w64.exe
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── distro
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── distro.cpython-312.pyc
│ │ │ │ │ ├── distro.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── idna
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ │ │ ├── codec.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── core.py
│ │ │ │ │ ├── idnadata.py
│ │ │ │ │ ├── intranges.py
│ │ │ │ │ ├── package_data.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ └── uts46data.py
│ │ │ │ ├── msgpack
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ │ │ └── fallback.cpython-312.pyc
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── ext.py
│ │ │ │ │ └── fallback.py
│ │ │ │ ├── packaging
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _elffile.cpython-312.pyc
│ │ │ │ │ │ ├── _manylinux.cpython-312.pyc
│ │ │ │ │ │ ├── _musllinux.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _structures.cpython-312.pyc
│ │ │ │ │ │ ├── _tokenizer.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ ├── specifiers.cpython-312.pyc
│ │ │ │ │ │ ├── tags.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── version.cpython-312.pyc
│ │ │ │ │ ├── _elffile.py
│ │ │ │ │ ├── _manylinux.py
│ │ │ │ │ ├── _musllinux.py
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _structures.py
│ │ │ │ │ ├── _tokenizer.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ ├── specifiers.py
│ │ │ │ │ ├── tags.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── version.py
│ │ │ │ ├── pkg_resources
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── platformdirs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── android.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── macos.cpython-312.pyc
│ │ │ │ │ │ ├── unix.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── windows.cpython-312.pyc
│ │ │ │ │ ├── android.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── unix.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── pygments
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── cmdline.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── filter.cpython-312.pyc
│ │ │ │ │ │ ├── formatter.cpython-312.pyc
│ │ │ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ │ │ ├── modeline.cpython-312.pyc
│ │ │ │ │ │ ├── plugin.cpython-312.pyc
│ │ │ │ │ │ ├── regexopt.cpython-312.pyc
│ │ │ │ │ │ ├── scanner.cpython-312.pyc
│ │ │ │ │ │ ├── sphinxext.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── token.cpython-312.pyc
│ │ │ │ │ │ ├── unistring.cpython-312.pyc
│ │ │ │ │ │ └── util.cpython-312.pyc
│ │ │ │ │ ├── cmdline.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── filter.py
│ │ │ │ │ ├── filters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── formatter.py
│ │ │ │ │ ├── formatters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ ├── bbcode.cpython-312.pyc
│ │ │ │ │ │ │ ├── groff.cpython-312.pyc
│ │ │ │ │ │ │ ├── html.cpython-312.pyc
│ │ │ │ │ │ │ ├── img.cpython-312.pyc
│ │ │ │ │ │ │ ├── irc.cpython-312.pyc
│ │ │ │ │ │ │ ├── latex.cpython-312.pyc
│ │ │ │ │ │ │ ├── other.cpython-312.pyc
│ │ │ │ │ │ │ ├── pangomarkup.cpython-312.pyc
│ │ │ │ │ │ │ ├── rtf.cpython-312.pyc
│ │ │ │ │ │ │ ├── svg.cpython-312.pyc
│ │ │ │ │ │ │ ├── terminal.cpython-312.pyc
│ │ │ │ │ │ │ └── terminal256.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ ├── bbcode.py
│ │ │ │ │ │ ├── groff.py
│ │ │ │ │ │ ├── html.py
│ │ │ │ │ │ ├── img.py
│ │ │ │ │ │ ├── irc.py
│ │ │ │ │ │ ├── latex.py
│ │ │ │ │ │ ├── other.py
│ │ │ │ │ │ ├── pangomarkup.py
│ │ │ │ │ │ ├── rtf.py
│ │ │ │ │ │ ├── svg.py
│ │ │ │ │ │ ├── terminal.py
│ │ │ │ │ │ └── terminal256.py
│ │ │ │ │ ├── lexer.py
│ │ │ │ │ ├── lexers
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ └── python.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ └── python.py
│ │ │ │ │ ├── modeline.py
│ │ │ │ │ ├── plugin.py
│ │ │ │ │ ├── regexopt.py
│ │ │ │ │ ├── scanner.py
│ │ │ │ │ ├── sphinxext.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styles
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── _mapping.cpython-312.pyc
│ │ │ │ │ │ └── _mapping.py
│ │ │ │ │ ├── token.py
│ │ │ │ │ ├── unistring.py
│ │ │ │ │ └── util.py
│ │ │ │ ├── pyproject_hooks
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ └── _impl.cpython-312.pyc
│ │ │ │ │ ├── _compat.py
│ │ │ │ │ ├── _impl.py
│ │ │ │ │ └── _in_process
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── _in_process.cpython-312.pyc
│ │ │ │ │ └── _in_process.py
│ │ │ │ ├── requests
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ │ ├── __version__.py
│ │ │ │ │ ├── _internal_utils.py
│ │ │ │ │ ├── adapters.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── certs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── cookies.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── hooks.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ ├── packages.py
│ │ │ │ │ ├── sessions.py
│ │ │ │ │ ├── status_codes.py
│ │ │ │ │ ├── structures.py
│ │ │ │ │ └── utils.py
│ │ │ │ ├── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── providers.cpython-312.pyc
│ │ │ │ │ │ ├── reporters.cpython-312.pyc
│ │ │ │ │ │ ├── resolvers.cpython-312.pyc
│ │ │ │ │ │ └── structs.cpython-312.pyc
│ │ │ │ │ ├── compat
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── collections_abc.cpython-312.pyc
│ │ │ │ │ │ └── collections_abc.py
│ │ │ │ │ ├── providers.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── reporters.py
│ │ │ │ │ ├── resolvers.py
│ │ │ │ │ └── structs.py
│ │ │ │ ├── rich
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── _cell_widths.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_codes.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_replace.cpython-312.pyc
│ │ │ │ │ │ ├── _export_format.cpython-312.pyc
│ │ │ │ │ │ ├── _extension.cpython-312.pyc
│ │ │ │ │ │ ├── _fileno.cpython-312.pyc
│ │ │ │ │ │ ├── _inspect.cpython-312.pyc
│ │ │ │ │ │ ├── _log_render.cpython-312.pyc
│ │ │ │ │ │ ├── _loop.cpython-312.pyc
│ │ │ │ │ │ ├── _null_file.cpython-312.pyc
│ │ │ │ │ │ ├── _palettes.cpython-312.pyc
│ │ │ │ │ │ ├── _pick.cpython-312.pyc
│ │ │ │ │ │ ├── _ratio.cpython-312.pyc
│ │ │ │ │ │ ├── _spinners.cpython-312.pyc
│ │ │ │ │ │ ├── _stack.cpython-312.pyc
│ │ │ │ │ │ ├── _timer.cpython-312.pyc
│ │ │ │ │ │ ├── _win32_console.cpython-312.pyc
│ │ │ │ │ │ ├── _windows_renderer.cpython-312.pyc
│ │ │ │ │ │ ├── _windows.cpython-312.pyc
│ │ │ │ │ │ ├── _wrap.cpython-312.pyc
│ │ │ │ │ │ ├── abc.cpython-312.pyc
│ │ │ │ │ │ ├── align.cpython-312.pyc
│ │ │ │ │ │ ├── ansi.cpython-312.pyc
│ │ │ │ │ │ ├── bar.cpython-312.pyc
│ │ │ │ │ │ ├── box.cpython-312.pyc
│ │ │ │ │ │ ├── cells.cpython-312.pyc
│ │ │ │ │ │ ├── color_triplet.cpython-312.pyc
│ │ │ │ │ │ ├── color.cpython-312.pyc
│ │ │ │ │ │ ├── columns.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── constrain.cpython-312.pyc
│ │ │ │ │ │ ├── containers.cpython-312.pyc
│ │ │ │ │ │ ├── control.cpython-312.pyc
│ │ │ │ │ │ ├── default_styles.cpython-312.pyc
│ │ │ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ │ │ ├── emoji.cpython-312.pyc
│ │ │ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ │ │ ├── file_proxy.cpython-312.pyc
│ │ │ │ │ │ ├── filesize.cpython-312.pyc
│ │ │ │ │ │ ├── highlighter.cpython-312.pyc
│ │ │ │ │ │ ├── json.cpython-312.pyc
│ │ │ │ │ │ ├── jupyter.cpython-312.pyc
│ │ │ │ │ │ ├── layout.cpython-312.pyc
│ │ │ │ │ │ ├── live_render.cpython-312.pyc
│ │ │ │ │ │ ├── live.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── markup.cpython-312.pyc
│ │ │ │ │ │ ├── measure.cpython-312.pyc
│ │ │ │ │ │ ├── padding.cpython-312.pyc
│ │ │ │ │ │ ├── pager.cpython-312.pyc
│ │ │ │ │ │ ├── palette.cpython-312.pyc
│ │ │ │ │ │ ├── panel.cpython-312.pyc
│ │ │ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bar.cpython-312.pyc
│ │ │ │ │ │ ├── progress.cpython-312.pyc
│ │ │ │ │ │ ├── prompt.cpython-312.pyc
│ │ │ │ │ │ ├── protocol.cpython-312.pyc
│ │ │ │ │ │ ├── region.cpython-312.pyc
│ │ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ │ ├── rule.cpython-312.pyc
│ │ │ │ │ │ ├── scope.cpython-312.pyc
│ │ │ │ │ │ ├── screen.cpython-312.pyc
│ │ │ │ │ │ ├── segment.cpython-312.pyc
│ │ │ │ │ │ ├── spinner.cpython-312.pyc
│ │ │ │ │ │ ├── status.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── styled.cpython-312.pyc
│ │ │ │ │ │ ├── syntax.cpython-312.pyc
│ │ │ │ │ │ ├── table.cpython-312.pyc
│ │ │ │ │ │ ├── terminal_theme.cpython-312.pyc
│ │ │ │ │ │ ├── text.cpython-312.pyc
│ │ │ │ │ │ ├── theme.cpython-312.pyc
│ │ │ │ │ │ ├── themes.cpython-312.pyc
│ │ │ │ │ │ ├── traceback.cpython-312.pyc
│ │ │ │ │ │ └── tree.cpython-312.pyc
│ │ │ │ │ ├── _cell_widths.py
│ │ │ │ │ ├── _emoji_codes.py
│ │ │ │ │ ├── _emoji_replace.py
│ │ │ │ │ ├── _export_format.py
│ │ │ │ │ ├── _extension.py
│ │ │ │ │ ├── _fileno.py
│ │ │ │ │ ├── _inspect.py
│ │ │ │ │ ├── _log_render.py
│ │ │ │ │ ├── _loop.py
│ │ │ │ │ ├── _null_file.py
│ │ │ │ │ ├── _palettes.py
│ │ │ │ │ ├── _pick.py
│ │ │ │ │ ├── _ratio.py
│ │ │ │ │ ├── _spinners.py
│ │ │ │ │ ├── _stack.py
│ │ │ │ │ ├── _timer.py
│ │ │ │ │ ├── _win32_console.py
│ │ │ │ │ ├── _windows_renderer.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ ├── _wrap.py
│ │ │ │ │ ├── abc.py
│ │ │ │ │ ├── align.py
│ │ │ │ │ ├── ansi.py
│ │ │ │ │ ├── bar.py
│ │ │ │ │ ├── box.py
│ │ │ │ │ ├── cells.py
│ │ │ │ │ ├── color_triplet.py
│ │ │ │ │ ├── color.py
│ │ │ │ │ ├── columns.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── constrain.py
│ │ │ │ │ ├── containers.py
│ │ │ │ │ ├── control.py
│ │ │ │ │ ├── default_styles.py
│ │ │ │ │ ├── diagnose.py
│ │ │ │ │ ├── emoji.py
│ │ │ │ │ ├── errors.py
│ │ │ │ │ ├── file_proxy.py
│ │ │ │ │ ├── filesize.py
│ │ │ │ │ ├── highlighter.py
│ │ │ │ │ ├── json.py
│ │ │ │ │ ├── jupyter.py
│ │ │ │ │ ├── layout.py
│ │ │ │ │ ├── live_render.py
│ │ │ │ │ ├── live.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── markup.py
│ │ │ │ │ ├── measure.py
│ │ │ │ │ ├── padding.py
│ │ │ │ │ ├── pager.py
│ │ │ │ │ ├── palette.py
│ │ │ │ │ ├── panel.py
│ │ │ │ │ ├── pretty.py
│ │ │ │ │ ├── progress_bar.py
│ │ │ │ │ ├── progress.py
│ │ │ │ │ ├── prompt.py
│ │ │ │ │ ├── protocol.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── region.py
│ │ │ │ │ ├── repr.py
│ │ │ │ │ ├── rule.py
│ │ │ │ │ ├── scope.py
│ │ │ │ │ ├── screen.py
│ │ │ │ │ ├── segment.py
│ │ │ │ │ ├── spinner.py
│ │ │ │ │ ├── status.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styled.py
│ │ │ │ │ ├── syntax.py
│ │ │ │ │ ├── table.py
│ │ │ │ │ ├── terminal_theme.py
│ │ │ │ │ ├── text.py
│ │ │ │ │ ├── theme.py
│ │ │ │ │ ├── themes.py
│ │ │ │ │ ├── traceback.py
│ │ │ │ │ └── tree.py
│ │ │ │ ├── tomli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _re.cpython-312.pyc
│ │ │ │ │ │ └── _types.cpython-312.pyc
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _re.py
│ │ │ │ │ ├── _types.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── truststore
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _api.cpython-312.pyc
│ │ │ │ │ │ ├── _macos.cpython-312.pyc
│ │ │ │ │ │ ├── _openssl.cpython-312.pyc
│ │ │ │ │ │ ├── _ssl_constants.cpython-312.pyc
│ │ │ │ │ │ └── _windows.cpython-312.pyc
│ │ │ │ │ ├── _api.py
│ │ │ │ │ ├── _macos.py
│ │ │ │ │ ├── _openssl.py
│ │ │ │ │ ├── _ssl_constants.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── typing_extensions.py
│ │ │ │ ├── urllib3
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── _collections.py
│ │ │ │ │ ├── _version.py
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── connectionpool.py
│ │ │ │ │ ├── contrib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _appengine_environ.cpython-312.pyc
│ │ │ │ │ │ │ ├── appengine.cpython-312.pyc
│ │ │ │ │ │ │ ├── ntlmpool.cpython-312.pyc
│ │ │ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ │ │ ├── securetransport.cpython-312.pyc
│ │ │ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ │ │ ├── _appengine_environ.py
│ │ │ │ │ │ ├── _securetransport
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── bindings.cpython-312.pyc
│ │ │ │ │ │ │ │ └── low_level.cpython-312.pyc
│ │ │ │ │ │ │ ├── bindings.py
│ │ │ │ │ │ │ └── low_level.py
│ │ │ │ │ │ ├── appengine.py
│ │ │ │ │ │ ├── ntlmpool.py
│ │ │ │ │ │ ├── pyopenssl.py
│ │ │ │ │ │ ├── securetransport.py
│ │ │ │ │ │ └── socks.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── fields.py
│ │ │ │ │ ├── filepost.py
│ │ │ │ │ ├── packages
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── six.cpython-312.pyc
│ │ │ │ │ │ ├── backports
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── makefile.cpython-312.pyc
│ │ │ │ │ │ │ │ └── weakref_finalize.cpython-312.pyc
│ │ │ │ │ │ │ ├── makefile.py
│ │ │ │ │ │ │ └── weakref_finalize.py
│ │ │ │ │ │ └── six.py
│ │ │ │ │ ├── poolmanager.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ └── util
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ │ │ ├── queue.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ │ │ └── wait.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── proxy.py
│ │ │ │ │ ├── queue.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── ssl_.py
│ │ │ │ │ ├── ssl_match_hostname.py
│ │ │ │ │ ├── ssltransport.py
│ │ │ │ │ ├── timeout.py
│ │ │ │ │ ├── url.py
│ │ │ │ │ └── wait.py
│ │ │ │ └── vendor.txt
│ │ │ └── py.typed
│ │ ├── pip-24.2.dist-info
│ │ │ ├── AUTHORS.txt
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── requests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── __version__.py
│ │ │ ├── _internal_utils.py
│ │ │ ├── adapters.py
│ │ │ ├── api.py
│ │ │ ├── auth.py
│ │ │ ├── certs.py
│ │ │ ├── compat.py
│ │ │ ├── cookies.py
│ │ │ ├── exceptions.py
│ │ │ ├── help.py
│ │ │ ├── hooks.py
│ │ │ ├── models.py
│ │ │ ├── packages.py
│ │ │ ├── sessions.py
│ │ │ ├── status_codes.py
│ │ │ ├── structures.py
│ │ │ └── utils.py
│ │ ├── requests-2.32.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── soupsieve
│ │ │ ├── __init__.py
│ │ │ ├── __meta__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __meta__.cpython-312.pyc
│ │ │ │ ├── css_match.cpython-312.pyc
│ │ │ │ ├── css_parser.cpython-312.pyc
│ │ │ │ ├── css_types.cpython-312.pyc
│ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ └── util.cpython-312.pyc
│ │ │ ├── css_match.py
│ │ │ ├── css_parser.py
│ │ │ ├── css_types.py
│ │ │ ├── pretty.py
│ │ │ ├── py.typed
│ │ │ └── util.py
│ │ ├── soupsieve-2.6.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── urllib3
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _base_connection.cpython-312.pyc
│ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ ├── _request_methods.cpython-312.pyc
│ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ └── response.cpython-312.pyc
│ │ │ ├── _base_connection.py
│ │ │ ├── _collections.py
│ │ │ ├── _request_methods.py
│ │ │ ├── _version.py
│ │ │ ├── connection.py
│ │ │ ├── connectionpool.py
│ │ │ ├── contrib
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ ├── emscripten
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── fetch.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── emscripten_fetch_worker.js
│ │ │ │ │ ├── fetch.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ └── response.py
│ │ │ │ ├── pyopenssl.py
│ │ │ │ └── socks.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── filepost.py
│ │ │ ├── http2
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ └── probe.cpython-312.pyc
│ │ │ │ ├── connection.py
│ │ │ │ └── probe.py
│ │ │ ├── poolmanager.py
│ │ │ ├── py.typed
│ │ │ ├── response.py
│ │ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ └── wait.cpython-312.pyc
│ │ │ ├── connection.py
│ │ │ ├── proxy.py
│ │ │ ├── request.py
│ │ │ ├── response.py
│ │ │ ├── retry.py
│ │ │ ├── ssl_.py
│ │ │ ├── ssl_match_hostname.py
│ │ │ ├── ssltransport.py
│ │ │ ├── timeout.py
│ │ │ ├── url.py
│ │ │ ├── util.py
│ │ │ └── wait.py
│ │ ├── urllib3-2.2.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── useragent
│ │ │ ├── __init__.py
│ │ │ ├── __init__.pyc
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── resources
│ │ │ │ └── user_agent_data.json
│ │ │ └── test
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── test_additional_os.json
│ │ │ ├── test_browser.json
│ │ │ ├── test_device.json
│ │ │ ├── test_firefox.json
│ │ │ ├── test_os.json
│ │ │ └── test_pgts_browser.json
│ │ ├── useragent-0.1.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── werkzeug
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _internal.cpython-312.pyc
│ │ │ │ ├── _reloader.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formparser.cpython-312.pyc
│ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ ├── local.cpython-312.pyc
│ │ │ │ ├── security.cpython-312.pyc
│ │ │ │ ├── serving.cpython-312.pyc
│ │ │ │ ├── test.cpython-312.pyc
│ │ │ │ ├── testapp.cpython-312.pyc
│ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ ├── user_agent.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── wsgi.cpython-312.pyc
│ │ │ ├── _internal.py
│ │ │ ├── _reloader.py
│ │ │ ├── datastructures
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── accept.cpython-312.pyc
│ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ ├── cache_control.cpython-312.pyc
│ │ │ │ │ ├── csp.cpython-312.pyc
│ │ │ │ │ ├── etag.cpython-312.pyc
│ │ │ │ │ ├── file_storage.cpython-312.pyc
│ │ │ │ │ ├── headers.cpython-312.pyc
│ │ │ │ │ ├── mixins.cpython-312.pyc
│ │ │ │ │ ├── range.cpython-312.pyc
│ │ │ │ │ └── structures.cpython-312.pyc
│ │ │ │ ├── accept.py
│ │ │ │ ├── accept.pyi
│ │ │ │ ├── auth.py
│ │ │ │ ├── cache_control.py
│ │ │ │ ├── cache_control.pyi
│ │ │ │ ├── csp.py
│ │ │ │ ├── csp.pyi
│ │ │ │ ├── etag.py
│ │ │ │ ├── etag.pyi
│ │ │ │ ├── file_storage.py
│ │ │ │ ├── file_storage.pyi
│ │ │ │ ├── headers.py
│ │ │ │ ├── headers.pyi
│ │ │ │ ├── mixins.py
│ │ │ │ ├── mixins.pyi
│ │ │ │ ├── range.py
│ │ │ │ ├── range.pyi
│ │ │ │ ├── structures.py
│ │ │ │ └── structures.pyi
│ │ │ ├── debug
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ └── tbtools.cpython-312.pyc
│ │ │ │ ├── console.py
│ │ │ │ ├── repr.py
│ │ │ │ ├── shared
│ │ │ │ │ ├── console.png
│ │ │ │ │ ├── debugger.js
│ │ │ │ │ ├── ICON_LICENSE.md
│ │ │ │ │ ├── less.png
│ │ │ │ │ ├── more.png
│ │ │ │ │ └── style.css
│ │ │ │ └── tbtools.py
│ │ │ ├── exceptions.py
│ │ │ ├── formparser.py
│ │ │ ├── http.py
│ │ │ ├── local.py
│ │ │ ├── middleware
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── dispatcher.cpython-312.pyc
│ │ │ │ │ ├── http_proxy.cpython-312.pyc
│ │ │ │ │ ├── lint.cpython-312.pyc
│ │ │ │ │ ├── profiler.cpython-312.pyc
│ │ │ │ │ ├── proxy_fix.cpython-312.pyc
│ │ │ │ │ └── shared_data.cpython-312.pyc
│ │ │ │ ├── dispatcher.py
│ │ │ │ ├── http_proxy.py
│ │ │ │ ├── lint.py
│ │ │ │ ├── profiler.py
│ │ │ │ ├── proxy_fix.py
│ │ │ │ └── shared_data.py
│ │ │ ├── py.typed
│ │ │ ├── routing
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── converters.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── map.cpython-312.pyc
│ │ │ │ │ ├── matcher.cpython-312.pyc
│ │ │ │ │ └── rules.cpython-312.pyc
│ │ │ │ ├── converters.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── map.py
│ │ │ │ ├── matcher.py
│ │ │ │ └── rules.py
│ │ │ ├── sansio
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ │ ├── multipart.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ ├── http.py
│ │ │ │ ├── multipart.py
│ │ │ │ ├── request.py
│ │ │ │ ├── response.py
│ │ │ │ └── utils.py
│ │ │ ├── security.py
│ │ │ ├── serving.py
│ │ │ ├── test.py
│ │ │ ├── testapp.py
│ │ │ ├── urls.py
│ │ │ ├── user_agent.py
│ │ │ ├── utils.py
│ │ │ ├── wrappers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ ├── request.py
│ │ │ │ └── response.py
│ │ │ └── wsgi.py
│ │ └── werkzeug-3.0.4.dist-info
│ │ ├── INSTALLER
│ │ ├── LICENSE.txt
│ │ ├── METADATA
│ │ ├── RECORD
│ │ └── WHEEL
│ ├── pyvenv.cfg
│ ├── static
│ │ └── styles.css
│ ├── templates
│ │ └── index.html
│ └── test.py
├── cline_config.json
├── mcp_server.py
├── README.md
├── search_results.json
├── settings.json
└── test_files
├── text1.txt
└── text2.txt
```
# Files
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/flask/templating.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import typing as t
4 |
5 | from jinja2 import BaseLoader
6 | from jinja2 import Environment as BaseEnvironment
7 | from jinja2 import Template
8 | from jinja2 import TemplateNotFound
9 |
10 | from .globals import _cv_app
11 | from .globals import _cv_request
12 | from .globals import current_app
13 | from .globals import request
14 | from .helpers import stream_with_context
15 | from .signals import before_render_template
16 | from .signals import template_rendered
17 |
18 | if t.TYPE_CHECKING: # pragma: no cover
19 | from .app import Flask
20 | from .sansio.app import App
21 | from .sansio.scaffold import Scaffold
22 |
23 |
24 | def _default_template_ctx_processor() -> dict[str, t.Any]:
25 | """Default template context processor. Injects `request`,
26 | `session` and `g`.
27 | """
28 | appctx = _cv_app.get(None)
29 | reqctx = _cv_request.get(None)
30 | rv: dict[str, t.Any] = {}
31 | if appctx is not None:
32 | rv["g"] = appctx.g
33 | if reqctx is not None:
34 | rv["request"] = reqctx.request
35 | rv["session"] = reqctx.session
36 | return rv
37 |
38 |
39 | class Environment(BaseEnvironment):
40 | """Works like a regular Jinja2 environment but has some additional
41 | knowledge of how Flask's blueprint works so that it can prepend the
42 | name of the blueprint to referenced templates if necessary.
43 | """
44 |
45 | def __init__(self, app: App, **options: t.Any) -> None:
46 | if "loader" not in options:
47 | options["loader"] = app.create_global_jinja_loader()
48 | BaseEnvironment.__init__(self, **options)
49 | self.app = app
50 |
51 |
52 | class DispatchingJinjaLoader(BaseLoader):
53 | """A loader that looks for templates in the application and all
54 | the blueprint folders.
55 | """
56 |
57 | def __init__(self, app: App) -> None:
58 | self.app = app
59 |
60 | def get_source(
61 | self, environment: BaseEnvironment, template: str
62 | ) -> tuple[str, str | None, t.Callable[[], bool] | None]:
63 | if self.app.config["EXPLAIN_TEMPLATE_LOADING"]:
64 | return self._get_source_explained(environment, template)
65 | return self._get_source_fast(environment, template)
66 |
67 | def _get_source_explained(
68 | self, environment: BaseEnvironment, template: str
69 | ) -> tuple[str, str | None, t.Callable[[], bool] | None]:
70 | attempts = []
71 | rv: tuple[str, str | None, t.Callable[[], bool] | None] | None
72 | trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None
73 |
74 | for srcobj, loader in self._iter_loaders(template):
75 | try:
76 | rv = loader.get_source(environment, template)
77 | if trv is None:
78 | trv = rv
79 | except TemplateNotFound:
80 | rv = None
81 | attempts.append((loader, srcobj, rv))
82 |
83 | from .debughelpers import explain_template_loading_attempts
84 |
85 | explain_template_loading_attempts(self.app, template, attempts)
86 |
87 | if trv is not None:
88 | return trv
89 | raise TemplateNotFound(template)
90 |
91 | def _get_source_fast(
92 | self, environment: BaseEnvironment, template: str
93 | ) -> tuple[str, str | None, t.Callable[[], bool] | None]:
94 | for _srcobj, loader in self._iter_loaders(template):
95 | try:
96 | return loader.get_source(environment, template)
97 | except TemplateNotFound:
98 | continue
99 | raise TemplateNotFound(template)
100 |
101 | def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]:
102 | loader = self.app.jinja_loader
103 | if loader is not None:
104 | yield self.app, loader
105 |
106 | for blueprint in self.app.iter_blueprints():
107 | loader = blueprint.jinja_loader
108 | if loader is not None:
109 | yield blueprint, loader
110 |
111 | def list_templates(self) -> list[str]:
112 | result = set()
113 | loader = self.app.jinja_loader
114 | if loader is not None:
115 | result.update(loader.list_templates())
116 |
117 | for blueprint in self.app.iter_blueprints():
118 | loader = blueprint.jinja_loader
119 | if loader is not None:
120 | for template in loader.list_templates():
121 | result.add(template)
122 |
123 | return list(result)
124 |
125 |
126 | def _render(app: Flask, template: Template, context: dict[str, t.Any]) -> str:
127 | app.update_template_context(context)
128 | before_render_template.send(
129 | app, _async_wrapper=app.ensure_sync, template=template, context=context
130 | )
131 | rv = template.render(context)
132 | template_rendered.send(
133 | app, _async_wrapper=app.ensure_sync, template=template, context=context
134 | )
135 | return rv
136 |
137 |
138 | def render_template(
139 | template_name_or_list: str | Template | list[str | Template],
140 | **context: t.Any,
141 | ) -> str:
142 | """Render a template by name with the given context.
143 |
144 | :param template_name_or_list: The name of the template to render. If
145 | a list is given, the first name to exist will be rendered.
146 | :param context: The variables to make available in the template.
147 | """
148 | app = current_app._get_current_object() # type: ignore[attr-defined]
149 | template = app.jinja_env.get_or_select_template(template_name_or_list)
150 | return _render(app, template, context)
151 |
152 |
153 | def render_template_string(source: str, **context: t.Any) -> str:
154 | """Render a template from the given source string with the given
155 | context.
156 |
157 | :param source: The source code of the template to render.
158 | :param context: The variables to make available in the template.
159 | """
160 | app = current_app._get_current_object() # type: ignore[attr-defined]
161 | template = app.jinja_env.from_string(source)
162 | return _render(app, template, context)
163 |
164 |
165 | def _stream(
166 | app: Flask, template: Template, context: dict[str, t.Any]
167 | ) -> t.Iterator[str]:
168 | app.update_template_context(context)
169 | before_render_template.send(
170 | app, _async_wrapper=app.ensure_sync, template=template, context=context
171 | )
172 |
173 | def generate() -> t.Iterator[str]:
174 | yield from template.generate(context)
175 | template_rendered.send(
176 | app, _async_wrapper=app.ensure_sync, template=template, context=context
177 | )
178 |
179 | rv = generate()
180 |
181 | # If a request context is active, keep it while generating.
182 | if request:
183 | rv = stream_with_context(rv)
184 |
185 | return rv
186 |
187 |
188 | def stream_template(
189 | template_name_or_list: str | Template | list[str | Template],
190 | **context: t.Any,
191 | ) -> t.Iterator[str]:
192 | """Render a template by name with the given context as a stream.
193 | This returns an iterator of strings, which can be used as a
194 | streaming response from a view.
195 |
196 | :param template_name_or_list: The name of the template to render. If
197 | a list is given, the first name to exist will be rendered.
198 | :param context: The variables to make available in the template.
199 |
200 | .. versionadded:: 2.2
201 | """
202 | app = current_app._get_current_object() # type: ignore[attr-defined]
203 | template = app.jinja_env.get_or_select_template(template_name_or_list)
204 | return _stream(app, template, context)
205 |
206 |
207 | def stream_template_string(source: str, **context: t.Any) -> t.Iterator[str]:
208 | """Render a template from the given source string with the given
209 | context as a stream. This returns an iterator of strings, which can
210 | be used as a streaming response from a view.
211 |
212 | :param source: The source code of the template to render.
213 | :param context: The variables to make available in the template.
214 |
215 | .. versionadded:: 2.2
216 | """
217 | app = current_app._get_current_object() # type: ignore[attr-defined]
218 | template = app.jinja_env.from_string(source)
219 | return _stream(app, template, context)
220 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/urllib3/contrib/socks.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | This module contains provisional support for SOCKS proxies from within
3 | urllib3. This module supports SOCKS4, SOCKS4A (an extension of SOCKS4), and
4 | SOCKS5. To enable its functionality, either install PySocks or install this
5 | module with the ``socks`` extra.
6 |
7 | The SOCKS implementation supports the full range of urllib3 features. It also
8 | supports the following SOCKS features:
9 |
10 | - SOCKS4A (``proxy_url='socks4a://...``)
11 | - SOCKS4 (``proxy_url='socks4://...``)
12 | - SOCKS5 with remote DNS (``proxy_url='socks5h://...``)
13 | - SOCKS5 with local DNS (``proxy_url='socks5://...``)
14 | - Usernames and passwords for the SOCKS proxy
15 |
16 | .. note::
17 | It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in
18 | your ``proxy_url`` to ensure that DNS resolution is done from the remote
19 | server instead of client-side when connecting to a domain name.
20 |
21 | SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5
22 | supports IPv4, IPv6, and domain names.
23 |
24 | When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url``
25 | will be sent as the ``userid`` section of the SOCKS request:
26 |
27 | .. code-block:: python
28 |
29 | proxy_url="socks4a://<userid>@proxy-host"
30 |
31 | When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion
32 | of the ``proxy_url`` will be sent as the username/password to authenticate
33 | with the proxy:
34 |
35 | .. code-block:: python
36 |
37 | proxy_url="socks5h://<username>:<password>@proxy-host"
38 |
39 | """
40 |
41 | from __future__ import annotations
42 |
43 | try:
44 | import socks # type: ignore[import-not-found]
45 | except ImportError:
46 | import warnings
47 |
48 | from ..exceptions import DependencyWarning
49 |
50 | warnings.warn(
51 | (
52 | "SOCKS support in urllib3 requires the installation of optional "
53 | "dependencies: specifically, PySocks. For more information, see "
54 | "https://urllib3.readthedocs.io/en/latest/advanced-usage.html#socks-proxies"
55 | ),
56 | DependencyWarning,
57 | )
58 | raise
59 |
60 | import typing
61 | from socket import timeout as SocketTimeout
62 |
63 | from ..connection import HTTPConnection, HTTPSConnection
64 | from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool
65 | from ..exceptions import ConnectTimeoutError, NewConnectionError
66 | from ..poolmanager import PoolManager
67 | from ..util.url import parse_url
68 |
69 | try:
70 | import ssl
71 | except ImportError:
72 | ssl = None # type: ignore[assignment]
73 |
74 |
75 | class _TYPE_SOCKS_OPTIONS(typing.TypedDict):
76 | socks_version: int
77 | proxy_host: str | None
78 | proxy_port: str | None
79 | username: str | None
80 | password: str | None
81 | rdns: bool
82 |
83 |
84 | class SOCKSConnection(HTTPConnection):
85 | """
86 | A plain-text HTTP connection that connects via a SOCKS proxy.
87 | """
88 |
89 | def __init__(
90 | self,
91 | _socks_options: _TYPE_SOCKS_OPTIONS,
92 | *args: typing.Any,
93 | **kwargs: typing.Any,
94 | ) -> None:
95 | self._socks_options = _socks_options
96 | super().__init__(*args, **kwargs)
97 |
98 | def _new_conn(self) -> socks.socksocket:
99 | """
100 | Establish a new connection via the SOCKS proxy.
101 | """
102 | extra_kw: dict[str, typing.Any] = {}
103 | if self.source_address:
104 | extra_kw["source_address"] = self.source_address
105 |
106 | if self.socket_options:
107 | extra_kw["socket_options"] = self.socket_options
108 |
109 | try:
110 | conn = socks.create_connection(
111 | (self.host, self.port),
112 | proxy_type=self._socks_options["socks_version"],
113 | proxy_addr=self._socks_options["proxy_host"],
114 | proxy_port=self._socks_options["proxy_port"],
115 | proxy_username=self._socks_options["username"],
116 | proxy_password=self._socks_options["password"],
117 | proxy_rdns=self._socks_options["rdns"],
118 | timeout=self.timeout,
119 | **extra_kw,
120 | )
121 |
122 | except SocketTimeout as e:
123 | raise ConnectTimeoutError(
124 | self,
125 | f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
126 | ) from e
127 |
128 | except socks.ProxyError as e:
129 | # This is fragile as hell, but it seems to be the only way to raise
130 | # useful errors here.
131 | if e.socket_err:
132 | error = e.socket_err
133 | if isinstance(error, SocketTimeout):
134 | raise ConnectTimeoutError(
135 | self,
136 | f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
137 | ) from e
138 | else:
139 | # Adding `from e` messes with coverage somehow, so it's omitted.
140 | # See #2386.
141 | raise NewConnectionError(
142 | self, f"Failed to establish a new connection: {error}"
143 | )
144 | else:
145 | raise NewConnectionError(
146 | self, f"Failed to establish a new connection: {e}"
147 | ) from e
148 |
149 | except OSError as e: # Defensive: PySocks should catch all these.
150 | raise NewConnectionError(
151 | self, f"Failed to establish a new connection: {e}"
152 | ) from e
153 |
154 | return conn
155 |
156 |
157 | # We don't need to duplicate the Verified/Unverified distinction from
158 | # urllib3/connection.py here because the HTTPSConnection will already have been
159 | # correctly set to either the Verified or Unverified form by that module. This
160 | # means the SOCKSHTTPSConnection will automatically be the correct type.
161 | class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection):
162 | pass
163 |
164 |
165 | class SOCKSHTTPConnectionPool(HTTPConnectionPool):
166 | ConnectionCls = SOCKSConnection
167 |
168 |
169 | class SOCKSHTTPSConnectionPool(HTTPSConnectionPool):
170 | ConnectionCls = SOCKSHTTPSConnection
171 |
172 |
173 | class SOCKSProxyManager(PoolManager):
174 | """
175 | A version of the urllib3 ProxyManager that routes connections via the
176 | defined SOCKS proxy.
177 | """
178 |
179 | pool_classes_by_scheme = {
180 | "http": SOCKSHTTPConnectionPool,
181 | "https": SOCKSHTTPSConnectionPool,
182 | }
183 |
184 | def __init__(
185 | self,
186 | proxy_url: str,
187 | username: str | None = None,
188 | password: str | None = None,
189 | num_pools: int = 10,
190 | headers: typing.Mapping[str, str] | None = None,
191 | **connection_pool_kw: typing.Any,
192 | ):
193 | parsed = parse_url(proxy_url)
194 |
195 | if username is None and password is None and parsed.auth is not None:
196 | split = parsed.auth.split(":")
197 | if len(split) == 2:
198 | username, password = split
199 | if parsed.scheme == "socks5":
200 | socks_version = socks.PROXY_TYPE_SOCKS5
201 | rdns = False
202 | elif parsed.scheme == "socks5h":
203 | socks_version = socks.PROXY_TYPE_SOCKS5
204 | rdns = True
205 | elif parsed.scheme == "socks4":
206 | socks_version = socks.PROXY_TYPE_SOCKS4
207 | rdns = False
208 | elif parsed.scheme == "socks4a":
209 | socks_version = socks.PROXY_TYPE_SOCKS4
210 | rdns = True
211 | else:
212 | raise ValueError(f"Unable to determine SOCKS version from {proxy_url}")
213 |
214 | self.proxy_url = proxy_url
215 |
216 | socks_options = {
217 | "socks_version": socks_version,
218 | "proxy_host": parsed.host,
219 | "proxy_port": parsed.port,
220 | "username": username,
221 | "password": password,
222 | "rdns": rdns,
223 | }
224 | connection_pool_kw["_socks_options"] = socks_options
225 |
226 | super().__init__(num_pools, headers, **connection_pool_kw)
227 |
228 | self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme
229 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/bs4/tests/test_lxml.py:
--------------------------------------------------------------------------------
```python
1 | """Tests to ensure that the lxml tree builder generates good trees."""
2 |
3 | import pickle
4 | import pytest
5 | import re
6 | import warnings
7 | from . import LXML_PRESENT, LXML_VERSION
8 |
9 | if LXML_PRESENT:
10 | from bs4.builder import LXMLTreeBuilder, LXMLTreeBuilderForXML
11 |
12 | from bs4 import (
13 | BeautifulSoup,
14 | BeautifulStoneSoup,
15 | )
16 | from bs4.element import Comment, Doctype, SoupStrainer
17 | from . import (
18 | HTMLTreeBuilderSmokeTest,
19 | XMLTreeBuilderSmokeTest,
20 | SOUP_SIEVE_PRESENT,
21 | SoupTest,
22 | )
23 |
24 | @pytest.mark.skipif(
25 | not LXML_PRESENT,
26 | reason="lxml seems not to be present, not testing its tree builder."
27 | )
28 | class TestLXMLTreeBuilder(SoupTest, HTMLTreeBuilderSmokeTest):
29 | """See ``HTMLTreeBuilderSmokeTest``."""
30 |
31 | @property
32 | def default_builder(self):
33 | return LXMLTreeBuilder
34 |
35 | def test_out_of_range_entity(self):
36 | self.assert_soup(
37 | "<p>foo�bar</p>", "<p>foobar</p>")
38 | self.assert_soup(
39 | "<p>foo�bar</p>", "<p>foobar</p>")
40 | self.assert_soup(
41 | "<p>foo�bar</p>", "<p>foobar</p>")
42 |
43 | def test_entities_in_foreign_document_encoding(self):
44 | # We can't implement this case correctly because by the time we
45 | # hear about markup like "“", it's been (incorrectly) converted into
46 | # a string like u'\x93'
47 | pass
48 |
49 | # In lxml < 2.3.5, an empty doctype causes a segfault. Skip this
50 | # test if an old version of lxml is installed.
51 |
52 | @pytest.mark.skipif(
53 | not LXML_PRESENT or LXML_VERSION < (2,3,5,0),
54 | reason="Skipping doctype test for old version of lxml to avoid segfault."
55 | )
56 | def test_empty_doctype(self):
57 | soup = self.soup("<!DOCTYPE>")
58 | doctype = soup.contents[0]
59 | assert "" == doctype.strip()
60 |
61 | def test_beautifulstonesoup_is_xml_parser(self):
62 | # Make sure that the deprecated BSS class uses an xml builder
63 | # if one is installed.
64 | with warnings.catch_warnings(record=True) as w:
65 | soup = BeautifulStoneSoup("<b />")
66 | assert "<b/>" == str(soup.b)
67 | [warning] = w
68 | assert warning.filename == __file__
69 | assert "BeautifulStoneSoup class is deprecated" in str(warning.message)
70 |
71 | def test_tracking_line_numbers(self):
72 | # The lxml TreeBuilder cannot keep track of line numbers from
73 | # the original markup. Even if you ask for line numbers, we
74 | # don't have 'em.
75 | #
76 | # This means that if you have a tag like <sourceline> or
77 | # <sourcepos>, attribute access will find it rather than
78 | # giving you a numeric answer.
79 | soup = self.soup(
80 | "\n <p>\n\n<sourceline>\n<b>text</b></sourceline><sourcepos></p>",
81 | store_line_numbers=True
82 | )
83 | assert "sourceline" == soup.p.sourceline.name
84 | assert "sourcepos" == soup.p.sourcepos.name
85 |
86 | @pytest.mark.skipif(
87 | not LXML_PRESENT,
88 | reason="lxml seems not to be present, not testing its XML tree builder."
89 | )
90 | class TestLXMLXMLTreeBuilder(SoupTest, XMLTreeBuilderSmokeTest):
91 | """See ``HTMLTreeBuilderSmokeTest``."""
92 |
93 | @property
94 | def default_builder(self):
95 | return LXMLTreeBuilderForXML
96 |
97 | def test_namespace_indexing(self):
98 | soup = self.soup(
99 | '<?xml version="1.1"?>\n'
100 | '<root>'
101 | '<tag xmlns="http://unprefixed-namespace.com">content</tag>'
102 | '<prefix:tag2 xmlns:prefix="http://prefixed-namespace.com">content</prefix:tag2>'
103 | '<prefix2:tag3 xmlns:prefix2="http://another-namespace.com">'
104 | '<subtag xmlns="http://another-unprefixed-namespace.com">'
105 | '<subsubtag xmlns="http://yet-another-unprefixed-namespace.com">'
106 | '</prefix2:tag3>'
107 | '</root>'
108 | )
109 |
110 | # The BeautifulSoup object includes every namespace prefix
111 | # defined in the entire document. This is the default set of
112 | # namespaces used by soupsieve.
113 | #
114 | # Un-prefixed namespaces are not included, and if a given
115 | # prefix is defined twice, only the first prefix encountered
116 | # in the document shows up here.
117 | assert soup._namespaces == {
118 | 'xml': 'http://www.w3.org/XML/1998/namespace',
119 | 'prefix': 'http://prefixed-namespace.com',
120 | 'prefix2': 'http://another-namespace.com'
121 | }
122 |
123 | # A Tag object includes only the namespace prefixes
124 | # that were in scope when it was parsed.
125 |
126 | # We do not track un-prefixed namespaces as we can only hold
127 | # one (the first one), and it will be recognized as the
128 | # default namespace by soupsieve, even when operating from a
129 | # tag with a different un-prefixed namespace.
130 | assert soup.tag._namespaces == {
131 | 'xml': 'http://www.w3.org/XML/1998/namespace',
132 | }
133 |
134 | assert soup.tag2._namespaces == {
135 | 'prefix': 'http://prefixed-namespace.com',
136 | 'xml': 'http://www.w3.org/XML/1998/namespace',
137 | }
138 |
139 | assert soup.subtag._namespaces == {
140 | 'prefix2': 'http://another-namespace.com',
141 | 'xml': 'http://www.w3.org/XML/1998/namespace',
142 | }
143 |
144 | assert soup.subsubtag._namespaces == {
145 | 'prefix2': 'http://another-namespace.com',
146 | 'xml': 'http://www.w3.org/XML/1998/namespace',
147 | }
148 |
149 |
150 | @pytest.mark.skipif(
151 | not SOUP_SIEVE_PRESENT, reason="Soup Sieve not installed"
152 | )
153 | def test_namespace_interaction_with_select_and_find(self):
154 | # Demonstrate how namespaces interact with select* and
155 | # find* methods.
156 |
157 | soup = self.soup(
158 | '<?xml version="1.1"?>\n'
159 | '<root>'
160 | '<tag xmlns="http://unprefixed-namespace.com">content</tag>'
161 | '<prefix:tag2 xmlns:prefix="http://prefixed-namespace.com">content</tag>'
162 | '<subtag xmlns:prefix="http://another-namespace-same-prefix.com">'
163 | '<prefix:tag3>'
164 | '</subtag>'
165 | '</root>'
166 | )
167 |
168 | # soupselect uses namespace URIs.
169 | assert soup.select_one('tag').name == 'tag'
170 | assert soup.select_one('prefix|tag2').name == 'tag2'
171 |
172 | # If a prefix is declared more than once, only the first usage
173 | # is registered with the BeautifulSoup object.
174 | assert soup.select_one('prefix|tag3') is None
175 |
176 | # But you can always explicitly specify a namespace dictionary.
177 | assert soup.select_one(
178 | 'prefix|tag3', namespaces=soup.subtag._namespaces
179 | ).name == 'tag3'
180 |
181 | # And a Tag (as opposed to the BeautifulSoup object) will
182 | # have a set of default namespaces scoped to that Tag.
183 | assert soup.subtag.select_one('prefix|tag3').name=='tag3'
184 |
185 | # the find() methods aren't fully namespace-aware; they just
186 | # look at prefixes.
187 | assert soup.find('tag').name == 'tag'
188 | assert soup.find('prefix:tag2').name == 'tag2'
189 | assert soup.find('prefix:tag3').name == 'tag3'
190 | assert soup.subtag.find('prefix:tag3').name == 'tag3'
191 |
192 | def test_pickle_restores_builder(self):
193 | # The lxml TreeBuilder is not picklable, so when unpickling
194 | # a document created with it, a new TreeBuilder of the
195 | # appropriate class is created.
196 | soup = self.soup("<a>some markup</a>")
197 | assert isinstance(soup.builder, self.default_builder)
198 | pickled = pickle.dumps(soup)
199 | unpickled = pickle.loads(pickled)
200 |
201 | assert "some markup" == unpickled.a.string
202 | assert unpickled.builder != soup.builder
203 | assert isinstance(unpickled.builder, self.default_builder)
204 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py:
--------------------------------------------------------------------------------
```python
1 | """Lazy ZIP over HTTP"""
2 |
3 | __all__ = ["HTTPRangeRequestUnsupported", "dist_from_wheel_url"]
4 |
5 | from bisect import bisect_left, bisect_right
6 | from contextlib import contextmanager
7 | from tempfile import NamedTemporaryFile
8 | from typing import Any, Dict, Generator, List, Optional, Tuple
9 | from zipfile import BadZipFile, ZipFile
10 |
11 | from pip._vendor.packaging.utils import canonicalize_name
12 | from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response
13 |
14 | from pip._internal.metadata import BaseDistribution, MemoryWheel, get_wheel_distribution
15 | from pip._internal.network.session import PipSession
16 | from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks
17 |
18 |
19 | class HTTPRangeRequestUnsupported(Exception):
20 | pass
21 |
22 |
23 | def dist_from_wheel_url(name: str, url: str, session: PipSession) -> BaseDistribution:
24 | """Return a distribution object from the given wheel URL.
25 |
26 | This uses HTTP range requests to only fetch the portion of the wheel
27 | containing metadata, just enough for the object to be constructed.
28 | If such requests are not supported, HTTPRangeRequestUnsupported
29 | is raised.
30 | """
31 | with LazyZipOverHTTP(url, session) as zf:
32 | # For read-only ZIP files, ZipFile only needs methods read,
33 | # seek, seekable and tell, not the whole IO protocol.
34 | wheel = MemoryWheel(zf.name, zf) # type: ignore
35 | # After context manager exit, wheel.name
36 | # is an invalid file by intention.
37 | return get_wheel_distribution(wheel, canonicalize_name(name))
38 |
39 |
40 | class LazyZipOverHTTP:
41 | """File-like object mapped to a ZIP file over HTTP.
42 |
43 | This uses HTTP range requests to lazily fetch the file's content,
44 | which is supposed to be fed to ZipFile. If such requests are not
45 | supported by the server, raise HTTPRangeRequestUnsupported
46 | during initialization.
47 | """
48 |
49 | def __init__(
50 | self, url: str, session: PipSession, chunk_size: int = CONTENT_CHUNK_SIZE
51 | ) -> None:
52 | head = session.head(url, headers=HEADERS)
53 | raise_for_status(head)
54 | assert head.status_code == 200
55 | self._session, self._url, self._chunk_size = session, url, chunk_size
56 | self._length = int(head.headers["Content-Length"])
57 | self._file = NamedTemporaryFile()
58 | self.truncate(self._length)
59 | self._left: List[int] = []
60 | self._right: List[int] = []
61 | if "bytes" not in head.headers.get("Accept-Ranges", "none"):
62 | raise HTTPRangeRequestUnsupported("range request is not supported")
63 | self._check_zip()
64 |
65 | @property
66 | def mode(self) -> str:
67 | """Opening mode, which is always rb."""
68 | return "rb"
69 |
70 | @property
71 | def name(self) -> str:
72 | """Path to the underlying file."""
73 | return self._file.name
74 |
75 | def seekable(self) -> bool:
76 | """Return whether random access is supported, which is True."""
77 | return True
78 |
79 | def close(self) -> None:
80 | """Close the file."""
81 | self._file.close()
82 |
83 | @property
84 | def closed(self) -> bool:
85 | """Whether the file is closed."""
86 | return self._file.closed
87 |
88 | def read(self, size: int = -1) -> bytes:
89 | """Read up to size bytes from the object and return them.
90 |
91 | As a convenience, if size is unspecified or -1,
92 | all bytes until EOF are returned. Fewer than
93 | size bytes may be returned if EOF is reached.
94 | """
95 | download_size = max(size, self._chunk_size)
96 | start, length = self.tell(), self._length
97 | stop = length if size < 0 else min(start + download_size, length)
98 | start = max(0, stop - download_size)
99 | self._download(start, stop - 1)
100 | return self._file.read(size)
101 |
102 | def readable(self) -> bool:
103 | """Return whether the file is readable, which is True."""
104 | return True
105 |
106 | def seek(self, offset: int, whence: int = 0) -> int:
107 | """Change stream position and return the new absolute position.
108 |
109 | Seek to offset relative position indicated by whence:
110 | * 0: Start of stream (the default). pos should be >= 0;
111 | * 1: Current position - pos may be negative;
112 | * 2: End of stream - pos usually negative.
113 | """
114 | return self._file.seek(offset, whence)
115 |
116 | def tell(self) -> int:
117 | """Return the current position."""
118 | return self._file.tell()
119 |
120 | def truncate(self, size: Optional[int] = None) -> int:
121 | """Resize the stream to the given size in bytes.
122 |
123 | If size is unspecified resize to the current position.
124 | The current stream position isn't changed.
125 |
126 | Return the new file size.
127 | """
128 | return self._file.truncate(size)
129 |
130 | def writable(self) -> bool:
131 | """Return False."""
132 | return False
133 |
134 | def __enter__(self) -> "LazyZipOverHTTP":
135 | self._file.__enter__()
136 | return self
137 |
138 | def __exit__(self, *exc: Any) -> None:
139 | self._file.__exit__(*exc)
140 |
141 | @contextmanager
142 | def _stay(self) -> Generator[None, None, None]:
143 | """Return a context manager keeping the position.
144 |
145 | At the end of the block, seek back to original position.
146 | """
147 | pos = self.tell()
148 | try:
149 | yield
150 | finally:
151 | self.seek(pos)
152 |
153 | def _check_zip(self) -> None:
154 | """Check and download until the file is a valid ZIP."""
155 | end = self._length - 1
156 | for start in reversed(range(0, end, self._chunk_size)):
157 | self._download(start, end)
158 | with self._stay():
159 | try:
160 | # For read-only ZIP files, ZipFile only needs
161 | # methods read, seek, seekable and tell.
162 | ZipFile(self) # type: ignore
163 | except BadZipFile:
164 | pass
165 | else:
166 | break
167 |
168 | def _stream_response(
169 | self, start: int, end: int, base_headers: Dict[str, str] = HEADERS
170 | ) -> Response:
171 | """Return HTTP response to a range request from start to end."""
172 | headers = base_headers.copy()
173 | headers["Range"] = f"bytes={start}-{end}"
174 | # TODO: Get range requests to be correctly cached
175 | headers["Cache-Control"] = "no-cache"
176 | return self._session.get(self._url, headers=headers, stream=True)
177 |
178 | def _merge(
179 | self, start: int, end: int, left: int, right: int
180 | ) -> Generator[Tuple[int, int], None, None]:
181 | """Return a generator of intervals to be fetched.
182 |
183 | Args:
184 | start (int): Start of needed interval
185 | end (int): End of needed interval
186 | left (int): Index of first overlapping downloaded data
187 | right (int): Index after last overlapping downloaded data
188 | """
189 | lslice, rslice = self._left[left:right], self._right[left:right]
190 | i = start = min([start] + lslice[:1])
191 | end = max([end] + rslice[-1:])
192 | for j, k in zip(lslice, rslice):
193 | if j > i:
194 | yield i, j - 1
195 | i = k + 1
196 | if i <= end:
197 | yield i, end
198 | self._left[left:right], self._right[left:right] = [start], [end]
199 |
200 | def _download(self, start: int, end: int) -> None:
201 | """Download bytes from start to end inclusively."""
202 | with self._stay():
203 | left = bisect_left(self._right, start)
204 | right = bisect_right(self._left, end)
205 | for start, end in self._merge(start, end, left, right):
206 | response = self._stream_response(start, end)
207 | response.raise_for_status()
208 | self.seek(start)
209 | for chunk in response_chunks(response, self._chunk_size):
210 | self._file.write(chunk)
211 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/flask/json/provider.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import dataclasses
4 | import decimal
5 | import json
6 | import typing as t
7 | import uuid
8 | import weakref
9 | from datetime import date
10 |
11 | from werkzeug.http import http_date
12 |
13 | if t.TYPE_CHECKING: # pragma: no cover
14 | from werkzeug.sansio.response import Response
15 |
16 | from ..sansio.app import App
17 |
18 |
19 | class JSONProvider:
20 | """A standard set of JSON operations for an application. Subclasses
21 | of this can be used to customize JSON behavior or use different
22 | JSON libraries.
23 |
24 | To implement a provider for a specific library, subclass this base
25 | class and implement at least :meth:`dumps` and :meth:`loads`. All
26 | other methods have default implementations.
27 |
28 | To use a different provider, either subclass ``Flask`` and set
29 | :attr:`~flask.Flask.json_provider_class` to a provider class, or set
30 | :attr:`app.json <flask.Flask.json>` to an instance of the class.
31 |
32 | :param app: An application instance. This will be stored as a
33 | :class:`weakref.proxy` on the :attr:`_app` attribute.
34 |
35 | .. versionadded:: 2.2
36 | """
37 |
38 | def __init__(self, app: App) -> None:
39 | self._app: App = weakref.proxy(app)
40 |
41 | def dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
42 | """Serialize data as JSON.
43 |
44 | :param obj: The data to serialize.
45 | :param kwargs: May be passed to the underlying JSON library.
46 | """
47 | raise NotImplementedError
48 |
49 | def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None:
50 | """Serialize data as JSON and write to a file.
51 |
52 | :param obj: The data to serialize.
53 | :param fp: A file opened for writing text. Should use the UTF-8
54 | encoding to be valid JSON.
55 | :param kwargs: May be passed to the underlying JSON library.
56 | """
57 | fp.write(self.dumps(obj, **kwargs))
58 |
59 | def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:
60 | """Deserialize data as JSON.
61 |
62 | :param s: Text or UTF-8 bytes.
63 | :param kwargs: May be passed to the underlying JSON library.
64 | """
65 | raise NotImplementedError
66 |
67 | def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any:
68 | """Deserialize data as JSON read from a file.
69 |
70 | :param fp: A file opened for reading text or UTF-8 bytes.
71 | :param kwargs: May be passed to the underlying JSON library.
72 | """
73 | return self.loads(fp.read(), **kwargs)
74 |
75 | def _prepare_response_obj(
76 | self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any]
77 | ) -> t.Any:
78 | if args and kwargs:
79 | raise TypeError("app.json.response() takes either args or kwargs, not both")
80 |
81 | if not args and not kwargs:
82 | return None
83 |
84 | if len(args) == 1:
85 | return args[0]
86 |
87 | return args or kwargs
88 |
89 | def response(self, *args: t.Any, **kwargs: t.Any) -> Response:
90 | """Serialize the given arguments as JSON, and return a
91 | :class:`~flask.Response` object with the ``application/json``
92 | mimetype.
93 |
94 | The :func:`~flask.json.jsonify` function calls this method for
95 | the current application.
96 |
97 | Either positional or keyword arguments can be given, not both.
98 | If no arguments are given, ``None`` is serialized.
99 |
100 | :param args: A single value to serialize, or multiple values to
101 | treat as a list to serialize.
102 | :param kwargs: Treat as a dict to serialize.
103 | """
104 | obj = self._prepare_response_obj(args, kwargs)
105 | return self._app.response_class(self.dumps(obj), mimetype="application/json")
106 |
107 |
108 | def _default(o: t.Any) -> t.Any:
109 | if isinstance(o, date):
110 | return http_date(o)
111 |
112 | if isinstance(o, (decimal.Decimal, uuid.UUID)):
113 | return str(o)
114 |
115 | if dataclasses and dataclasses.is_dataclass(o):
116 | return dataclasses.asdict(o)
117 |
118 | if hasattr(o, "__html__"):
119 | return str(o.__html__())
120 |
121 | raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")
122 |
123 |
124 | class DefaultJSONProvider(JSONProvider):
125 | """Provide JSON operations using Python's built-in :mod:`json`
126 | library. Serializes the following additional data types:
127 |
128 | - :class:`datetime.datetime` and :class:`datetime.date` are
129 | serialized to :rfc:`822` strings. This is the same as the HTTP
130 | date format.
131 | - :class:`uuid.UUID` is serialized to a string.
132 | - :class:`dataclasses.dataclass` is passed to
133 | :func:`dataclasses.asdict`.
134 | - :class:`~markupsafe.Markup` (or any object with a ``__html__``
135 | method) will call the ``__html__`` method to get a string.
136 | """
137 |
138 | default: t.Callable[[t.Any], t.Any] = staticmethod(_default) # type: ignore[assignment]
139 | """Apply this function to any object that :meth:`json.dumps` does
140 | not know how to serialize. It should return a valid JSON type or
141 | raise a ``TypeError``.
142 | """
143 |
144 | ensure_ascii = True
145 | """Replace non-ASCII characters with escape sequences. This may be
146 | more compatible with some clients, but can be disabled for better
147 | performance and size.
148 | """
149 |
150 | sort_keys = True
151 | """Sort the keys in any serialized dicts. This may be useful for
152 | some caching situations, but can be disabled for better performance.
153 | When enabled, keys must all be strings, they are not converted
154 | before sorting.
155 | """
156 |
157 | compact: bool | None = None
158 | """If ``True``, or ``None`` out of debug mode, the :meth:`response`
159 | output will not add indentation, newlines, or spaces. If ``False``,
160 | or ``None`` in debug mode, it will use a non-compact representation.
161 | """
162 |
163 | mimetype = "application/json"
164 | """The mimetype set in :meth:`response`."""
165 |
166 | def dumps(self, obj: t.Any, **kwargs: t.Any) -> str:
167 | """Serialize data as JSON to a string.
168 |
169 | Keyword arguments are passed to :func:`json.dumps`. Sets some
170 | parameter defaults from the :attr:`default`,
171 | :attr:`ensure_ascii`, and :attr:`sort_keys` attributes.
172 |
173 | :param obj: The data to serialize.
174 | :param kwargs: Passed to :func:`json.dumps`.
175 | """
176 | kwargs.setdefault("default", self.default)
177 | kwargs.setdefault("ensure_ascii", self.ensure_ascii)
178 | kwargs.setdefault("sort_keys", self.sort_keys)
179 | return json.dumps(obj, **kwargs)
180 |
181 | def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any:
182 | """Deserialize data as JSON from a string or bytes.
183 |
184 | :param s: Text or UTF-8 bytes.
185 | :param kwargs: Passed to :func:`json.loads`.
186 | """
187 | return json.loads(s, **kwargs)
188 |
189 | def response(self, *args: t.Any, **kwargs: t.Any) -> Response:
190 | """Serialize the given arguments as JSON, and return a
191 | :class:`~flask.Response` object with it. The response mimetype
192 | will be "application/json" and can be changed with
193 | :attr:`mimetype`.
194 |
195 | If :attr:`compact` is ``False`` or debug mode is enabled, the
196 | output will be formatted to be easier to read.
197 |
198 | Either positional or keyword arguments can be given, not both.
199 | If no arguments are given, ``None`` is serialized.
200 |
201 | :param args: A single value to serialize, or multiple values to
202 | treat as a list to serialize.
203 | :param kwargs: Treat as a dict to serialize.
204 | """
205 | obj = self._prepare_response_obj(args, kwargs)
206 | dump_args: dict[str, t.Any] = {}
207 |
208 | if (self.compact is None and self._app.debug) or self.compact is False:
209 | dump_args.setdefault("indent", 2)
210 | else:
211 | dump_args.setdefault("separators", (",", ":"))
212 |
213 | return self._app.response_class(
214 | f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype
215 | )
216 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py:
--------------------------------------------------------------------------------
```python
1 | import logging
2 | import os
3 | import sys
4 | import sysconfig
5 | import typing
6 |
7 | from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid
8 | from pip._internal.models.scheme import SCHEME_KEYS, Scheme
9 | from pip._internal.utils.virtualenv import running_under_virtualenv
10 |
11 | from .base import change_root, get_major_minor_version, is_osx_framework
12 |
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | # Notes on _infer_* functions.
17 | # Unfortunately ``get_default_scheme()`` didn't exist before 3.10, so there's no
18 | # way to ask things like "what is the '_prefix' scheme on this platform". These
19 | # functions try to answer that with some heuristics while accounting for ad-hoc
20 | # platforms not covered by CPython's default sysconfig implementation. If the
21 | # ad-hoc implementation does not fully implement sysconfig, we'll fall back to
22 | # a POSIX scheme.
23 |
24 | _AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names())
25 |
26 | _PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None)
27 |
28 |
29 | def _should_use_osx_framework_prefix() -> bool:
30 | """Check for Apple's ``osx_framework_library`` scheme.
31 |
32 | Python distributed by Apple's Command Line Tools has this special scheme
33 | that's used when:
34 |
35 | * This is a framework build.
36 | * We are installing into the system prefix.
37 |
38 | This does not account for ``pip install --prefix`` (also means we're not
39 | installing to the system prefix), which should use ``posix_prefix``, but
40 | logic here means ``_infer_prefix()`` outputs ``osx_framework_library``. But
41 | since ``prefix`` is not available for ``sysconfig.get_default_scheme()``,
42 | which is the stdlib replacement for ``_infer_prefix()``, presumably Apple
43 | wouldn't be able to magically switch between ``osx_framework_library`` and
44 | ``posix_prefix``. ``_infer_prefix()`` returning ``osx_framework_library``
45 | means its behavior is consistent whether we use the stdlib implementation
46 | or our own, and we deal with this special case in ``get_scheme()`` instead.
47 | """
48 | return (
49 | "osx_framework_library" in _AVAILABLE_SCHEMES
50 | and not running_under_virtualenv()
51 | and is_osx_framework()
52 | )
53 |
54 |
55 | def _infer_prefix() -> str:
56 | """Try to find a prefix scheme for the current platform.
57 |
58 | This tries:
59 |
60 | * A special ``osx_framework_library`` for Python distributed by Apple's
61 | Command Line Tools, when not running in a virtual environment.
62 | * Implementation + OS, used by PyPy on Windows (``pypy_nt``).
63 | * Implementation without OS, used by PyPy on POSIX (``pypy``).
64 | * OS + "prefix", used by CPython on POSIX (``posix_prefix``).
65 | * Just the OS name, used by CPython on Windows (``nt``).
66 |
67 | If none of the above works, fall back to ``posix_prefix``.
68 | """
69 | if _PREFERRED_SCHEME_API:
70 | return _PREFERRED_SCHEME_API("prefix")
71 | if _should_use_osx_framework_prefix():
72 | return "osx_framework_library"
73 | implementation_suffixed = f"{sys.implementation.name}_{os.name}"
74 | if implementation_suffixed in _AVAILABLE_SCHEMES:
75 | return implementation_suffixed
76 | if sys.implementation.name in _AVAILABLE_SCHEMES:
77 | return sys.implementation.name
78 | suffixed = f"{os.name}_prefix"
79 | if suffixed in _AVAILABLE_SCHEMES:
80 | return suffixed
81 | if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt".
82 | return os.name
83 | return "posix_prefix"
84 |
85 |
86 | def _infer_user() -> str:
87 | """Try to find a user scheme for the current platform."""
88 | if _PREFERRED_SCHEME_API:
89 | return _PREFERRED_SCHEME_API("user")
90 | if is_osx_framework() and not running_under_virtualenv():
91 | suffixed = "osx_framework_user"
92 | else:
93 | suffixed = f"{os.name}_user"
94 | if suffixed in _AVAILABLE_SCHEMES:
95 | return suffixed
96 | if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable.
97 | raise UserInstallationInvalid()
98 | return "posix_user"
99 |
100 |
101 | def _infer_home() -> str:
102 | """Try to find a home for the current platform."""
103 | if _PREFERRED_SCHEME_API:
104 | return _PREFERRED_SCHEME_API("home")
105 | suffixed = f"{os.name}_home"
106 | if suffixed in _AVAILABLE_SCHEMES:
107 | return suffixed
108 | return "posix_home"
109 |
110 |
111 | # Update these keys if the user sets a custom home.
112 | _HOME_KEYS = [
113 | "installed_base",
114 | "base",
115 | "installed_platbase",
116 | "platbase",
117 | "prefix",
118 | "exec_prefix",
119 | ]
120 | if sysconfig.get_config_var("userbase") is not None:
121 | _HOME_KEYS.append("userbase")
122 |
123 |
124 | def get_scheme(
125 | dist_name: str,
126 | user: bool = False,
127 | home: typing.Optional[str] = None,
128 | root: typing.Optional[str] = None,
129 | isolated: bool = False,
130 | prefix: typing.Optional[str] = None,
131 | ) -> Scheme:
132 | """
133 | Get the "scheme" corresponding to the input parameters.
134 |
135 | :param dist_name: the name of the package to retrieve the scheme for, used
136 | in the headers scheme path
137 | :param user: indicates to use the "user" scheme
138 | :param home: indicates to use the "home" scheme
139 | :param root: root under which other directories are re-based
140 | :param isolated: ignored, but kept for distutils compatibility (where
141 | this controls whether the user-site pydistutils.cfg is honored)
142 | :param prefix: indicates to use the "prefix" scheme and provides the
143 | base directory for the same
144 | """
145 | if user and prefix:
146 | raise InvalidSchemeCombination("--user", "--prefix")
147 | if home and prefix:
148 | raise InvalidSchemeCombination("--home", "--prefix")
149 |
150 | if home is not None:
151 | scheme_name = _infer_home()
152 | elif user:
153 | scheme_name = _infer_user()
154 | else:
155 | scheme_name = _infer_prefix()
156 |
157 | # Special case: When installing into a custom prefix, use posix_prefix
158 | # instead of osx_framework_library. See _should_use_osx_framework_prefix()
159 | # docstring for details.
160 | if prefix is not None and scheme_name == "osx_framework_library":
161 | scheme_name = "posix_prefix"
162 |
163 | if home is not None:
164 | variables = {k: home for k in _HOME_KEYS}
165 | elif prefix is not None:
166 | variables = {k: prefix for k in _HOME_KEYS}
167 | else:
168 | variables = {}
169 |
170 | paths = sysconfig.get_paths(scheme=scheme_name, vars=variables)
171 |
172 | # Logic here is very arbitrary, we're doing it for compatibility, don't ask.
173 | # 1. Pip historically uses a special header path in virtual environments.
174 | # 2. If the distribution name is not known, distutils uses 'UNKNOWN'. We
175 | # only do the same when not running in a virtual environment because
176 | # pip's historical header path logic (see point 1) did not do this.
177 | if running_under_virtualenv():
178 | if user:
179 | base = variables.get("userbase", sys.prefix)
180 | else:
181 | base = variables.get("base", sys.prefix)
182 | python_xy = f"python{get_major_minor_version()}"
183 | paths["include"] = os.path.join(base, "include", "site", python_xy)
184 | elif not dist_name:
185 | dist_name = "UNKNOWN"
186 |
187 | scheme = Scheme(
188 | platlib=paths["platlib"],
189 | purelib=paths["purelib"],
190 | headers=os.path.join(paths["include"], dist_name),
191 | scripts=paths["scripts"],
192 | data=paths["data"],
193 | )
194 | if root is not None:
195 | converted_keys = {}
196 | for key in SCHEME_KEYS:
197 | converted_keys[key] = change_root(root, getattr(scheme, key))
198 | scheme = Scheme(**converted_keys)
199 | return scheme
200 |
201 |
202 | def get_bin_prefix() -> str:
203 | # Forcing to use /usr/local/bin for standard macOS framework installs.
204 | if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/":
205 | return "/usr/local/bin"
206 | return sysconfig.get_paths()["scripts"]
207 |
208 |
209 | def get_purelib() -> str:
210 | return sysconfig.get_paths()["purelib"]
211 |
212 |
213 | def get_platlib() -> str:
214 | return sysconfig.get_paths()["platlib"]
215 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/werkzeug/middleware/http_proxy.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | Basic HTTP Proxy
3 | ================
4 |
5 | .. autoclass:: ProxyMiddleware
6 |
7 | :copyright: 2007 Pallets
8 | :license: BSD-3-Clause
9 | """
10 |
11 | from __future__ import annotations
12 |
13 | import typing as t
14 | from http import client
15 | from urllib.parse import quote
16 | from urllib.parse import urlsplit
17 |
18 | from ..datastructures import EnvironHeaders
19 | from ..http import is_hop_by_hop_header
20 | from ..wsgi import get_input_stream
21 |
22 | if t.TYPE_CHECKING:
23 | from _typeshed.wsgi import StartResponse
24 | from _typeshed.wsgi import WSGIApplication
25 | from _typeshed.wsgi import WSGIEnvironment
26 |
27 |
28 | class ProxyMiddleware:
29 | """Proxy requests under a path to an external server, routing other
30 | requests to the app.
31 |
32 | This middleware can only proxy HTTP requests, as HTTP is the only
33 | protocol handled by the WSGI server. Other protocols, such as
34 | WebSocket requests, cannot be proxied at this layer. This should
35 | only be used for development, in production a real proxy server
36 | should be used.
37 |
38 | The middleware takes a dict mapping a path prefix to a dict
39 | describing the host to be proxied to::
40 |
41 | app = ProxyMiddleware(app, {
42 | "/static/": {
43 | "target": "http://127.0.0.1:5001/",
44 | }
45 | })
46 |
47 | Each host has the following options:
48 |
49 | ``target``:
50 | The target URL to dispatch to. This is required.
51 | ``remove_prefix``:
52 | Whether to remove the prefix from the URL before dispatching it
53 | to the target. The default is ``False``.
54 | ``host``:
55 | ``"<auto>"`` (default):
56 | The host header is automatically rewritten to the URL of the
57 | target.
58 | ``None``:
59 | The host header is unmodified from the client request.
60 | Any other value:
61 | The host header is overwritten with the value.
62 | ``headers``:
63 | A dictionary of headers to be sent with the request to the
64 | target. The default is ``{}``.
65 | ``ssl_context``:
66 | A :class:`ssl.SSLContext` defining how to verify requests if the
67 | target is HTTPS. The default is ``None``.
68 |
69 | In the example above, everything under ``"/static/"`` is proxied to
70 | the server on port 5001. The host header is rewritten to the target,
71 | and the ``"/static/"`` prefix is removed from the URLs.
72 |
73 | :param app: The WSGI application to wrap.
74 | :param targets: Proxy target configurations. See description above.
75 | :param chunk_size: Size of chunks to read from input stream and
76 | write to target.
77 | :param timeout: Seconds before an operation to a target fails.
78 |
79 | .. versionadded:: 0.14
80 | """
81 |
82 | def __init__(
83 | self,
84 | app: WSGIApplication,
85 | targets: t.Mapping[str, dict[str, t.Any]],
86 | chunk_size: int = 2 << 13,
87 | timeout: int = 10,
88 | ) -> None:
89 | def _set_defaults(opts: dict[str, t.Any]) -> dict[str, t.Any]:
90 | opts.setdefault("remove_prefix", False)
91 | opts.setdefault("host", "<auto>")
92 | opts.setdefault("headers", {})
93 | opts.setdefault("ssl_context", None)
94 | return opts
95 |
96 | self.app = app
97 | self.targets = {
98 | f"/{k.strip('/')}/": _set_defaults(v) for k, v in targets.items()
99 | }
100 | self.chunk_size = chunk_size
101 | self.timeout = timeout
102 |
103 | def proxy_to(
104 | self, opts: dict[str, t.Any], path: str, prefix: str
105 | ) -> WSGIApplication:
106 | target = urlsplit(opts["target"])
107 | # socket can handle unicode host, but header must be ascii
108 | host = target.hostname.encode("idna").decode("ascii")
109 |
110 | def application(
111 | environ: WSGIEnvironment, start_response: StartResponse
112 | ) -> t.Iterable[bytes]:
113 | headers = list(EnvironHeaders(environ).items())
114 | headers[:] = [
115 | (k, v)
116 | for k, v in headers
117 | if not is_hop_by_hop_header(k)
118 | and k.lower() not in ("content-length", "host")
119 | ]
120 | headers.append(("Connection", "close"))
121 |
122 | if opts["host"] == "<auto>":
123 | headers.append(("Host", host))
124 | elif opts["host"] is None:
125 | headers.append(("Host", environ["HTTP_HOST"]))
126 | else:
127 | headers.append(("Host", opts["host"]))
128 |
129 | headers.extend(opts["headers"].items())
130 | remote_path = path
131 |
132 | if opts["remove_prefix"]:
133 | remote_path = remote_path[len(prefix) :].lstrip("/")
134 | remote_path = f"{target.path.rstrip('/')}/{remote_path}"
135 |
136 | content_length = environ.get("CONTENT_LENGTH")
137 | chunked = False
138 |
139 | if content_length not in ("", None):
140 | headers.append(("Content-Length", content_length)) # type: ignore
141 | elif content_length is not None:
142 | headers.append(("Transfer-Encoding", "chunked"))
143 | chunked = True
144 |
145 | try:
146 | if target.scheme == "http":
147 | con = client.HTTPConnection(
148 | host, target.port or 80, timeout=self.timeout
149 | )
150 | elif target.scheme == "https":
151 | con = client.HTTPSConnection(
152 | host,
153 | target.port or 443,
154 | timeout=self.timeout,
155 | context=opts["ssl_context"],
156 | )
157 | else:
158 | raise RuntimeError(
159 | "Target scheme must be 'http' or 'https', got"
160 | f" {target.scheme!r}."
161 | )
162 |
163 | con.connect()
164 | # safe = https://url.spec.whatwg.org/#url-path-segment-string
165 | # as well as percent for things that are already quoted
166 | remote_url = quote(remote_path, safe="!$&'()*+,/:;=@%")
167 | querystring = environ["QUERY_STRING"]
168 |
169 | if querystring:
170 | remote_url = f"{remote_url}?{querystring}"
171 |
172 | con.putrequest(environ["REQUEST_METHOD"], remote_url, skip_host=True)
173 |
174 | for k, v in headers:
175 | if k.lower() == "connection":
176 | v = "close"
177 |
178 | con.putheader(k, v)
179 |
180 | con.endheaders()
181 | stream = get_input_stream(environ)
182 |
183 | while True:
184 | data = stream.read(self.chunk_size)
185 |
186 | if not data:
187 | break
188 |
189 | if chunked:
190 | con.send(b"%x\r\n%s\r\n" % (len(data), data))
191 | else:
192 | con.send(data)
193 |
194 | resp = con.getresponse()
195 | except OSError:
196 | from ..exceptions import BadGateway
197 |
198 | return BadGateway()(environ, start_response)
199 |
200 | start_response(
201 | f"{resp.status} {resp.reason}",
202 | [
203 | (k.title(), v)
204 | for k, v in resp.getheaders()
205 | if not is_hop_by_hop_header(k)
206 | ],
207 | )
208 |
209 | def read() -> t.Iterator[bytes]:
210 | while True:
211 | try:
212 | data = resp.read(self.chunk_size)
213 | except OSError:
214 | break
215 |
216 | if not data:
217 | break
218 |
219 | yield data
220 |
221 | return read()
222 |
223 | return application
224 |
225 | def __call__(
226 | self, environ: WSGIEnvironment, start_response: StartResponse
227 | ) -> t.Iterable[bytes]:
228 | path = environ["PATH_INFO"]
229 | app = self.app
230 |
231 | for prefix, opts in self.targets.items():
232 | if path.startswith(prefix):
233 | app = self.proxy_to(opts, path, prefix)
234 | break
235 |
236 | return app(environ, start_response)
237 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/werkzeug/routing/matcher.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import re
4 | import typing as t
5 | from dataclasses import dataclass
6 | from dataclasses import field
7 |
8 | from .converters import ValidationError
9 | from .exceptions import NoMatch
10 | from .exceptions import RequestAliasRedirect
11 | from .exceptions import RequestPath
12 | from .rules import Rule
13 | from .rules import RulePart
14 |
15 |
16 | class SlashRequired(Exception):
17 | pass
18 |
19 |
20 | @dataclass
21 | class State:
22 | """A representation of a rule state.
23 |
24 | This includes the *rules* that correspond to the state and the
25 | possible *static* and *dynamic* transitions to the next state.
26 | """
27 |
28 | dynamic: list[tuple[RulePart, State]] = field(default_factory=list)
29 | rules: list[Rule] = field(default_factory=list)
30 | static: dict[str, State] = field(default_factory=dict)
31 |
32 |
33 | class StateMachineMatcher:
34 | def __init__(self, merge_slashes: bool) -> None:
35 | self._root = State()
36 | self.merge_slashes = merge_slashes
37 |
38 | def add(self, rule: Rule) -> None:
39 | state = self._root
40 | for part in rule._parts:
41 | if part.static:
42 | state.static.setdefault(part.content, State())
43 | state = state.static[part.content]
44 | else:
45 | for test_part, new_state in state.dynamic:
46 | if test_part == part:
47 | state = new_state
48 | break
49 | else:
50 | new_state = State()
51 | state.dynamic.append((part, new_state))
52 | state = new_state
53 | state.rules.append(rule)
54 |
55 | def update(self) -> None:
56 | # For every state the dynamic transitions should be sorted by
57 | # the weight of the transition
58 | state = self._root
59 |
60 | def _update_state(state: State) -> None:
61 | state.dynamic.sort(key=lambda entry: entry[0].weight)
62 | for new_state in state.static.values():
63 | _update_state(new_state)
64 | for _, new_state in state.dynamic:
65 | _update_state(new_state)
66 |
67 | _update_state(state)
68 |
69 | def match(
70 | self, domain: str, path: str, method: str, websocket: bool
71 | ) -> tuple[Rule, t.MutableMapping[str, t.Any]]:
72 | # To match to a rule we need to start at the root state and
73 | # try to follow the transitions until we find a match, or find
74 | # there is no transition to follow.
75 |
76 | have_match_for = set()
77 | websocket_mismatch = False
78 |
79 | def _match(
80 | state: State, parts: list[str], values: list[str]
81 | ) -> tuple[Rule, list[str]] | None:
82 | # This function is meant to be called recursively, and will attempt
83 | # to match the head part to the state's transitions.
84 | nonlocal have_match_for, websocket_mismatch
85 |
86 | # The base case is when all parts have been matched via
87 | # transitions. Hence if there is a rule with methods &
88 | # websocket that work return it and the dynamic values
89 | # extracted.
90 | if parts == []:
91 | for rule in state.rules:
92 | if rule.methods is not None and method not in rule.methods:
93 | have_match_for.update(rule.methods)
94 | elif rule.websocket != websocket:
95 | websocket_mismatch = True
96 | else:
97 | return rule, values
98 |
99 | # Test if there is a match with this path with a
100 | # trailing slash, if so raise an exception to report
101 | # that matching is possible with an additional slash
102 | if "" in state.static:
103 | for rule in state.static[""].rules:
104 | if websocket == rule.websocket and (
105 | rule.methods is None or method in rule.methods
106 | ):
107 | if rule.strict_slashes:
108 | raise SlashRequired()
109 | else:
110 | return rule, values
111 | return None
112 |
113 | part = parts[0]
114 | # To match this part try the static transitions first
115 | if part in state.static:
116 | rv = _match(state.static[part], parts[1:], values)
117 | if rv is not None:
118 | return rv
119 | # No match via the static transitions, so try the dynamic
120 | # ones.
121 | for test_part, new_state in state.dynamic:
122 | target = part
123 | remaining = parts[1:]
124 | # A final part indicates a transition that always
125 | # consumes the remaining parts i.e. transitions to a
126 | # final state.
127 | if test_part.final:
128 | target = "/".join(parts)
129 | remaining = []
130 | match = re.compile(test_part.content).match(target)
131 | if match is not None:
132 | if test_part.suffixed:
133 | # If a part_isolating=False part has a slash suffix, remove the
134 | # suffix from the match and check for the slash redirect next.
135 | suffix = match.groups()[-1]
136 | if suffix == "/":
137 | remaining = [""]
138 |
139 | converter_groups = sorted(
140 | match.groupdict().items(), key=lambda entry: entry[0]
141 | )
142 | groups = [
143 | value
144 | for key, value in converter_groups
145 | if key[:11] == "__werkzeug_"
146 | ]
147 | rv = _match(new_state, remaining, values + groups)
148 | if rv is not None:
149 | return rv
150 |
151 | # If there is no match and the only part left is a
152 | # trailing slash ("") consider rules that aren't
153 | # strict-slashes as these should match if there is a final
154 | # slash part.
155 | if parts == [""]:
156 | for rule in state.rules:
157 | if rule.strict_slashes:
158 | continue
159 | if rule.methods is not None and method not in rule.methods:
160 | have_match_for.update(rule.methods)
161 | elif rule.websocket != websocket:
162 | websocket_mismatch = True
163 | else:
164 | return rule, values
165 |
166 | return None
167 |
168 | try:
169 | rv = _match(self._root, [domain, *path.split("/")], [])
170 | except SlashRequired:
171 | raise RequestPath(f"{path}/") from None
172 |
173 | if self.merge_slashes and rv is None:
174 | # Try to match again, but with slashes merged
175 | path = re.sub("/{2,}?", "/", path)
176 | try:
177 | rv = _match(self._root, [domain, *path.split("/")], [])
178 | except SlashRequired:
179 | raise RequestPath(f"{path}/") from None
180 | if rv is None or rv[0].merge_slashes is False:
181 | raise NoMatch(have_match_for, websocket_mismatch)
182 | else:
183 | raise RequestPath(f"{path}")
184 | elif rv is not None:
185 | rule, values = rv
186 |
187 | result = {}
188 | for name, value in zip(rule._converters.keys(), values):
189 | try:
190 | value = rule._converters[name].to_python(value)
191 | except ValidationError:
192 | raise NoMatch(have_match_for, websocket_mismatch) from None
193 | result[str(name)] = value
194 | if rule.defaults:
195 | result.update(rule.defaults)
196 |
197 | if rule.alias and rule.map.redirect_defaults:
198 | raise RequestAliasRedirect(result, rule.endpoint)
199 |
200 | return rule, result
201 |
202 | raise NoMatch(have_match_for, websocket_mismatch)
203 |
```