This is page 94 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/requests/sessions.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | requests.sessions
3 | ~~~~~~~~~~~~~~~~~
4 |
5 | This module provides a Session object to manage and persist settings across
6 | requests (cookies, auth, proxies).
7 | """
8 | import os
9 | import sys
10 | import time
11 | from collections import OrderedDict
12 | from datetime import timedelta
13 |
14 | from ._internal_utils import to_native_string
15 | from .adapters import HTTPAdapter
16 | from .auth import _basic_auth_str
17 | from .compat import Mapping, cookielib, urljoin, urlparse
18 | from .cookies import (
19 | RequestsCookieJar,
20 | cookiejar_from_dict,
21 | extract_cookies_to_jar,
22 | merge_cookies,
23 | )
24 | from .exceptions import (
25 | ChunkedEncodingError,
26 | ContentDecodingError,
27 | InvalidSchema,
28 | TooManyRedirects,
29 | )
30 | from .hooks import default_hooks, dispatch_hook
31 |
32 | # formerly defined here, reexposed here for backward compatibility
33 | from .models import ( # noqa: F401
34 | DEFAULT_REDIRECT_LIMIT,
35 | REDIRECT_STATI,
36 | PreparedRequest,
37 | Request,
38 | )
39 | from .status_codes import codes
40 | from .structures import CaseInsensitiveDict
41 | from .utils import ( # noqa: F401
42 | DEFAULT_PORTS,
43 | default_headers,
44 | get_auth_from_url,
45 | get_environ_proxies,
46 | get_netrc_auth,
47 | requote_uri,
48 | resolve_proxies,
49 | rewind_body,
50 | should_bypass_proxies,
51 | to_key_val_list,
52 | )
53 |
54 | # Preferred clock, based on which one is more accurate on a given system.
55 | if sys.platform == "win32":
56 | preferred_clock = time.perf_counter
57 | else:
58 | preferred_clock = time.time
59 |
60 |
61 | def merge_setting(request_setting, session_setting, dict_class=OrderedDict):
62 | """Determines appropriate setting for a given request, taking into account
63 | the explicit setting on that request, and the setting in the session. If a
64 | setting is a dictionary, they will be merged together using `dict_class`
65 | """
66 |
67 | if session_setting is None:
68 | return request_setting
69 |
70 | if request_setting is None:
71 | return session_setting
72 |
73 | # Bypass if not a dictionary (e.g. verify)
74 | if not (
75 | isinstance(session_setting, Mapping) and isinstance(request_setting, Mapping)
76 | ):
77 | return request_setting
78 |
79 | merged_setting = dict_class(to_key_val_list(session_setting))
80 | merged_setting.update(to_key_val_list(request_setting))
81 |
82 | # Remove keys that are set to None. Extract keys first to avoid altering
83 | # the dictionary during iteration.
84 | none_keys = [k for (k, v) in merged_setting.items() if v is None]
85 | for key in none_keys:
86 | del merged_setting[key]
87 |
88 | return merged_setting
89 |
90 |
91 | def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict):
92 | """Properly merges both requests and session hooks.
93 |
94 | This is necessary because when request_hooks == {'response': []}, the
95 | merge breaks Session hooks entirely.
96 | """
97 | if session_hooks is None or session_hooks.get("response") == []:
98 | return request_hooks
99 |
100 | if request_hooks is None or request_hooks.get("response") == []:
101 | return session_hooks
102 |
103 | return merge_setting(request_hooks, session_hooks, dict_class)
104 |
105 |
106 | class SessionRedirectMixin:
107 | def get_redirect_target(self, resp):
108 | """Receives a Response. Returns a redirect URI or ``None``"""
109 | # Due to the nature of how requests processes redirects this method will
110 | # be called at least once upon the original response and at least twice
111 | # on each subsequent redirect response (if any).
112 | # If a custom mixin is used to handle this logic, it may be advantageous
113 | # to cache the redirect location onto the response object as a private
114 | # attribute.
115 | if resp.is_redirect:
116 | location = resp.headers["location"]
117 | # Currently the underlying http module on py3 decode headers
118 | # in latin1, but empirical evidence suggests that latin1 is very
119 | # rarely used with non-ASCII characters in HTTP headers.
120 | # It is more likely to get UTF8 header rather than latin1.
121 | # This causes incorrect handling of UTF8 encoded location headers.
122 | # To solve this, we re-encode the location in latin1.
123 | location = location.encode("latin1")
124 | return to_native_string(location, "utf8")
125 | return None
126 |
127 | def should_strip_auth(self, old_url, new_url):
128 | """Decide whether Authorization header should be removed when redirecting"""
129 | old_parsed = urlparse(old_url)
130 | new_parsed = urlparse(new_url)
131 | if old_parsed.hostname != new_parsed.hostname:
132 | return True
133 | # Special case: allow http -> https redirect when using the standard
134 | # ports. This isn't specified by RFC 7235, but is kept to avoid
135 | # breaking backwards compatibility with older versions of requests
136 | # that allowed any redirects on the same host.
137 | if (
138 | old_parsed.scheme == "http"
139 | and old_parsed.port in (80, None)
140 | and new_parsed.scheme == "https"
141 | and new_parsed.port in (443, None)
142 | ):
143 | return False
144 |
145 | # Handle default port usage corresponding to scheme.
146 | changed_port = old_parsed.port != new_parsed.port
147 | changed_scheme = old_parsed.scheme != new_parsed.scheme
148 | default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None)
149 | if (
150 | not changed_scheme
151 | and old_parsed.port in default_port
152 | and new_parsed.port in default_port
153 | ):
154 | return False
155 |
156 | # Standard case: root URI must match
157 | return changed_port or changed_scheme
158 |
159 | def resolve_redirects(
160 | self,
161 | resp,
162 | req,
163 | stream=False,
164 | timeout=None,
165 | verify=True,
166 | cert=None,
167 | proxies=None,
168 | yield_requests=False,
169 | **adapter_kwargs,
170 | ):
171 | """Receives a Response. Returns a generator of Responses or Requests."""
172 |
173 | hist = [] # keep track of history
174 |
175 | url = self.get_redirect_target(resp)
176 | previous_fragment = urlparse(req.url).fragment
177 | while url:
178 | prepared_request = req.copy()
179 |
180 | # Update history and keep track of redirects.
181 | # resp.history must ignore the original request in this loop
182 | hist.append(resp)
183 | resp.history = hist[1:]
184 |
185 | try:
186 | resp.content # Consume socket so it can be released
187 | except (ChunkedEncodingError, ContentDecodingError, RuntimeError):
188 | resp.raw.read(decode_content=False)
189 |
190 | if len(resp.history) >= self.max_redirects:
191 | raise TooManyRedirects(
192 | f"Exceeded {self.max_redirects} redirects.", response=resp
193 | )
194 |
195 | # Release the connection back into the pool.
196 | resp.close()
197 |
198 | # Handle redirection without scheme (see: RFC 1808 Section 4)
199 | if url.startswith("//"):
200 | parsed_rurl = urlparse(resp.url)
201 | url = ":".join([to_native_string(parsed_rurl.scheme), url])
202 |
203 | # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2)
204 | parsed = urlparse(url)
205 | if parsed.fragment == "" and previous_fragment:
206 | parsed = parsed._replace(fragment=previous_fragment)
207 | elif parsed.fragment:
208 | previous_fragment = parsed.fragment
209 | url = parsed.geturl()
210 |
211 | # Facilitate relative 'location' headers, as allowed by RFC 7231.
212 | # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
213 | # Compliant with RFC3986, we percent encode the url.
214 | if not parsed.netloc:
215 | url = urljoin(resp.url, requote_uri(url))
216 | else:
217 | url = requote_uri(url)
218 |
219 | prepared_request.url = to_native_string(url)
220 |
221 | self.rebuild_method(prepared_request, resp)
222 |
223 | # https://github.com/psf/requests/issues/1084
224 | if resp.status_code not in (
225 | codes.temporary_redirect,
226 | codes.permanent_redirect,
227 | ):
228 | # https://github.com/psf/requests/issues/3490
229 | purged_headers = ("Content-Length", "Content-Type", "Transfer-Encoding")
230 | for header in purged_headers:
231 | prepared_request.headers.pop(header, None)
232 | prepared_request.body = None
233 |
234 | headers = prepared_request.headers
235 | headers.pop("Cookie", None)
236 |
237 | # Extract any cookies sent on the response to the cookiejar
238 | # in the new request. Because we've mutated our copied prepared
239 | # request, use the old one that we haven't yet touched.
240 | extract_cookies_to_jar(prepared_request._cookies, req, resp.raw)
241 | merge_cookies(prepared_request._cookies, self.cookies)
242 | prepared_request.prepare_cookies(prepared_request._cookies)
243 |
244 | # Rebuild auth and proxy information.
245 | proxies = self.rebuild_proxies(prepared_request, proxies)
246 | self.rebuild_auth(prepared_request, resp)
247 |
248 | # A failed tell() sets `_body_position` to `object()`. This non-None
249 | # value ensures `rewindable` will be True, allowing us to raise an
250 | # UnrewindableBodyError, instead of hanging the connection.
251 | rewindable = prepared_request._body_position is not None and (
252 | "Content-Length" in headers or "Transfer-Encoding" in headers
253 | )
254 |
255 | # Attempt to rewind consumed file-like object.
256 | if rewindable:
257 | rewind_body(prepared_request)
258 |
259 | # Override the original request.
260 | req = prepared_request
261 |
262 | if yield_requests:
263 | yield req
264 | else:
265 | resp = self.send(
266 | req,
267 | stream=stream,
268 | timeout=timeout,
269 | verify=verify,
270 | cert=cert,
271 | proxies=proxies,
272 | allow_redirects=False,
273 | **adapter_kwargs,
274 | )
275 |
276 | extract_cookies_to_jar(self.cookies, prepared_request, resp.raw)
277 |
278 | # extract redirect url, if any, for the next loop
279 | url = self.get_redirect_target(resp)
280 | yield resp
281 |
282 | def rebuild_auth(self, prepared_request, response):
283 | """When being redirected we may want to strip authentication from the
284 | request to avoid leaking credentials. This method intelligently removes
285 | and reapplies authentication where possible to avoid credential loss.
286 | """
287 | headers = prepared_request.headers
288 | url = prepared_request.url
289 |
290 | if "Authorization" in headers and self.should_strip_auth(
291 | response.request.url, url
292 | ):
293 | # If we get redirected to a new host, we should strip out any
294 | # authentication headers.
295 | del headers["Authorization"]
296 |
297 | # .netrc might have more auth for us on our new host.
298 | new_auth = get_netrc_auth(url) if self.trust_env else None
299 | if new_auth is not None:
300 | prepared_request.prepare_auth(new_auth)
301 |
302 | def rebuild_proxies(self, prepared_request, proxies):
303 | """This method re-evaluates the proxy configuration by considering the
304 | environment variables. If we are redirected to a URL covered by
305 | NO_PROXY, we strip the proxy configuration. Otherwise, we set missing
306 | proxy keys for this URL (in case they were stripped by a previous
307 | redirect).
308 |
309 | This method also replaces the Proxy-Authorization header where
310 | necessary.
311 |
312 | :rtype: dict
313 | """
314 | headers = prepared_request.headers
315 | scheme = urlparse(prepared_request.url).scheme
316 | new_proxies = resolve_proxies(prepared_request, proxies, self.trust_env)
317 |
318 | if "Proxy-Authorization" in headers:
319 | del headers["Proxy-Authorization"]
320 |
321 | try:
322 | username, password = get_auth_from_url(new_proxies[scheme])
323 | except KeyError:
324 | username, password = None, None
325 |
326 | # urllib3 handles proxy authorization for us in the standard adapter.
327 | # Avoid appending this to TLS tunneled requests where it may be leaked.
328 | if not scheme.startswith("https") and username and password:
329 | headers["Proxy-Authorization"] = _basic_auth_str(username, password)
330 |
331 | return new_proxies
332 |
333 | def rebuild_method(self, prepared_request, response):
334 | """When being redirected we may want to change the method of the request
335 | based on certain specs or browser behavior.
336 | """
337 | method = prepared_request.method
338 |
339 | # https://tools.ietf.org/html/rfc7231#section-6.4.4
340 | if response.status_code == codes.see_other and method != "HEAD":
341 | method = "GET"
342 |
343 | # Do what the browsers do, despite standards...
344 | # First, turn 302s into GETs.
345 | if response.status_code == codes.found and method != "HEAD":
346 | method = "GET"
347 |
348 | # Second, if a POST is responded to with a 301, turn it into a GET.
349 | # This bizarre behaviour is explained in Issue 1704.
350 | if response.status_code == codes.moved and method == "POST":
351 | method = "GET"
352 |
353 | prepared_request.method = method
354 |
355 |
356 | class Session(SessionRedirectMixin):
357 | """A Requests session.
358 |
359 | Provides cookie persistence, connection-pooling, and configuration.
360 |
361 | Basic Usage::
362 |
363 | >>> import requests
364 | >>> s = requests.Session()
365 | >>> s.get('https://httpbin.org/get')
366 | <Response [200]>
367 |
368 | Or as a context manager::
369 |
370 | >>> with requests.Session() as s:
371 | ... s.get('https://httpbin.org/get')
372 | <Response [200]>
373 | """
374 |
375 | __attrs__ = [
376 | "headers",
377 | "cookies",
378 | "auth",
379 | "proxies",
380 | "hooks",
381 | "params",
382 | "verify",
383 | "cert",
384 | "adapters",
385 | "stream",
386 | "trust_env",
387 | "max_redirects",
388 | ]
389 |
390 | def __init__(self):
391 | #: A case-insensitive dictionary of headers to be sent on each
392 | #: :class:`Request <Request>` sent from this
393 | #: :class:`Session <Session>`.
394 | self.headers = default_headers()
395 |
396 | #: Default Authentication tuple or object to attach to
397 | #: :class:`Request <Request>`.
398 | self.auth = None
399 |
400 | #: Dictionary mapping protocol or protocol and host to the URL of the proxy
401 | #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to
402 | #: be used on each :class:`Request <Request>`.
403 | self.proxies = {}
404 |
405 | #: Event-handling hooks.
406 | self.hooks = default_hooks()
407 |
408 | #: Dictionary of querystring data to attach to each
409 | #: :class:`Request <Request>`. The dictionary values may be lists for
410 | #: representing multivalued query parameters.
411 | self.params = {}
412 |
413 | #: Stream response content default.
414 | self.stream = False
415 |
416 | #: SSL Verification default.
417 | #: Defaults to `True`, requiring requests to verify the TLS certificate at the
418 | #: remote end.
419 | #: If verify is set to `False`, requests will accept any TLS certificate
420 | #: presented by the server, and will ignore hostname mismatches and/or
421 | #: expired certificates, which will make your application vulnerable to
422 | #: man-in-the-middle (MitM) attacks.
423 | #: Only set this to `False` for testing.
424 | self.verify = True
425 |
426 | #: SSL client certificate default, if String, path to ssl client
427 | #: cert file (.pem). If Tuple, ('cert', 'key') pair.
428 | self.cert = None
429 |
430 | #: Maximum number of redirects allowed. If the request exceeds this
431 | #: limit, a :class:`TooManyRedirects` exception is raised.
432 | #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is
433 | #: 30.
434 | self.max_redirects = DEFAULT_REDIRECT_LIMIT
435 |
436 | #: Trust environment settings for proxy configuration, default
437 | #: authentication and similar.
438 | self.trust_env = True
439 |
440 | #: A CookieJar containing all currently outstanding cookies set on this
441 | #: session. By default it is a
442 | #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but
443 | #: may be any other ``cookielib.CookieJar`` compatible object.
444 | self.cookies = cookiejar_from_dict({})
445 |
446 | # Default connection adapters.
447 | self.adapters = OrderedDict()
448 | self.mount("https://", HTTPAdapter())
449 | self.mount("http://", HTTPAdapter())
450 |
451 | def __enter__(self):
452 | return self
453 |
454 | def __exit__(self, *args):
455 | self.close()
456 |
457 | def prepare_request(self, request):
458 | """Constructs a :class:`PreparedRequest <PreparedRequest>` for
459 | transmission and returns it. The :class:`PreparedRequest` has settings
460 | merged from the :class:`Request <Request>` instance and those of the
461 | :class:`Session`.
462 |
463 | :param request: :class:`Request` instance to prepare with this
464 | session's settings.
465 | :rtype: requests.PreparedRequest
466 | """
467 | cookies = request.cookies or {}
468 |
469 | # Bootstrap CookieJar.
470 | if not isinstance(cookies, cookielib.CookieJar):
471 | cookies = cookiejar_from_dict(cookies)
472 |
473 | # Merge with session cookies
474 | merged_cookies = merge_cookies(
475 | merge_cookies(RequestsCookieJar(), self.cookies), cookies
476 | )
477 |
478 | # Set environment's basic authentication if not explicitly set.
479 | auth = request.auth
480 | if self.trust_env and not auth and not self.auth:
481 | auth = get_netrc_auth(request.url)
482 |
483 | p = PreparedRequest()
484 | p.prepare(
485 | method=request.method.upper(),
486 | url=request.url,
487 | files=request.files,
488 | data=request.data,
489 | json=request.json,
490 | headers=merge_setting(
491 | request.headers, self.headers, dict_class=CaseInsensitiveDict
492 | ),
493 | params=merge_setting(request.params, self.params),
494 | auth=merge_setting(auth, self.auth),
495 | cookies=merged_cookies,
496 | hooks=merge_hooks(request.hooks, self.hooks),
497 | )
498 | return p
499 |
500 | def request(
501 | self,
502 | method,
503 | url,
504 | params=None,
505 | data=None,
506 | headers=None,
507 | cookies=None,
508 | files=None,
509 | auth=None,
510 | timeout=None,
511 | allow_redirects=True,
512 | proxies=None,
513 | hooks=None,
514 | stream=None,
515 | verify=None,
516 | cert=None,
517 | json=None,
518 | ):
519 | """Constructs a :class:`Request <Request>`, prepares it and sends it.
520 | Returns :class:`Response <Response>` object.
521 |
522 | :param method: method for the new :class:`Request` object.
523 | :param url: URL for the new :class:`Request` object.
524 | :param params: (optional) Dictionary or bytes to be sent in the query
525 | string for the :class:`Request`.
526 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
527 | object to send in the body of the :class:`Request`.
528 | :param json: (optional) json to send in the body of the
529 | :class:`Request`.
530 | :param headers: (optional) Dictionary of HTTP Headers to send with the
531 | :class:`Request`.
532 | :param cookies: (optional) Dict or CookieJar object to send with the
533 | :class:`Request`.
534 | :param files: (optional) Dictionary of ``'filename': file-like-objects``
535 | for multipart encoding upload.
536 | :param auth: (optional) Auth tuple or callable to enable
537 | Basic/Digest/Custom HTTP Auth.
538 | :param timeout: (optional) How long to wait for the server to send
539 | data before giving up, as a float, or a :ref:`(connect timeout,
540 | read timeout) <timeouts>` tuple.
541 | :type timeout: float or tuple
542 | :param allow_redirects: (optional) Set to True by default.
543 | :type allow_redirects: bool
544 | :param proxies: (optional) Dictionary mapping protocol or protocol and
545 | hostname to the URL of the proxy.
546 | :param hooks: (optional) Dictionary mapping hook name to one event or
547 | list of events, event must be callable.
548 | :param stream: (optional) whether to immediately download the response
549 | content. Defaults to ``False``.
550 | :param verify: (optional) Either a boolean, in which case it controls whether we verify
551 | the server's TLS certificate, or a string, in which case it must be a path
552 | to a CA bundle to use. Defaults to ``True``. When set to
553 | ``False``, requests will accept any TLS certificate presented by
554 | the server, and will ignore hostname mismatches and/or expired
555 | certificates, which will make your application vulnerable to
556 | man-in-the-middle (MitM) attacks. Setting verify to ``False``
557 | may be useful during local development or testing.
558 | :param cert: (optional) if String, path to ssl client cert file (.pem).
559 | If Tuple, ('cert', 'key') pair.
560 | :rtype: requests.Response
561 | """
562 | # Create the Request.
563 | req = Request(
564 | method=method.upper(),
565 | url=url,
566 | headers=headers,
567 | files=files,
568 | data=data or {},
569 | json=json,
570 | params=params or {},
571 | auth=auth,
572 | cookies=cookies,
573 | hooks=hooks,
574 | )
575 | prep = self.prepare_request(req)
576 |
577 | proxies = proxies or {}
578 |
579 | settings = self.merge_environment_settings(
580 | prep.url, proxies, stream, verify, cert
581 | )
582 |
583 | # Send the request.
584 | send_kwargs = {
585 | "timeout": timeout,
586 | "allow_redirects": allow_redirects,
587 | }
588 | send_kwargs.update(settings)
589 | resp = self.send(prep, **send_kwargs)
590 |
591 | return resp
592 |
593 | def get(self, url, **kwargs):
594 | r"""Sends a GET request. Returns :class:`Response` object.
595 |
596 | :param url: URL for the new :class:`Request` object.
597 | :param \*\*kwargs: Optional arguments that ``request`` takes.
598 | :rtype: requests.Response
599 | """
600 |
601 | kwargs.setdefault("allow_redirects", True)
602 | return self.request("GET", url, **kwargs)
603 |
604 | def options(self, url, **kwargs):
605 | r"""Sends a OPTIONS request. Returns :class:`Response` object.
606 |
607 | :param url: URL for the new :class:`Request` object.
608 | :param \*\*kwargs: Optional arguments that ``request`` takes.
609 | :rtype: requests.Response
610 | """
611 |
612 | kwargs.setdefault("allow_redirects", True)
613 | return self.request("OPTIONS", url, **kwargs)
614 |
615 | def head(self, url, **kwargs):
616 | r"""Sends a HEAD request. Returns :class:`Response` object.
617 |
618 | :param url: URL for the new :class:`Request` object.
619 | :param \*\*kwargs: Optional arguments that ``request`` takes.
620 | :rtype: requests.Response
621 | """
622 |
623 | kwargs.setdefault("allow_redirects", False)
624 | return self.request("HEAD", url, **kwargs)
625 |
626 | def post(self, url, data=None, json=None, **kwargs):
627 | r"""Sends a POST request. Returns :class:`Response` object.
628 |
629 | :param url: URL for the new :class:`Request` object.
630 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
631 | object to send in the body of the :class:`Request`.
632 | :param json: (optional) json to send in the body of the :class:`Request`.
633 | :param \*\*kwargs: Optional arguments that ``request`` takes.
634 | :rtype: requests.Response
635 | """
636 |
637 | return self.request("POST", url, data=data, json=json, **kwargs)
638 |
639 | def put(self, url, data=None, **kwargs):
640 | r"""Sends a PUT request. Returns :class:`Response` object.
641 |
642 | :param url: URL for the new :class:`Request` object.
643 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
644 | object to send in the body of the :class:`Request`.
645 | :param \*\*kwargs: Optional arguments that ``request`` takes.
646 | :rtype: requests.Response
647 | """
648 |
649 | return self.request("PUT", url, data=data, **kwargs)
650 |
651 | def patch(self, url, data=None, **kwargs):
652 | r"""Sends a PATCH request. Returns :class:`Response` object.
653 |
654 | :param url: URL for the new :class:`Request` object.
655 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
656 | object to send in the body of the :class:`Request`.
657 | :param \*\*kwargs: Optional arguments that ``request`` takes.
658 | :rtype: requests.Response
659 | """
660 |
661 | return self.request("PATCH", url, data=data, **kwargs)
662 |
663 | def delete(self, url, **kwargs):
664 | r"""Sends a DELETE request. Returns :class:`Response` object.
665 |
666 | :param url: URL for the new :class:`Request` object.
667 | :param \*\*kwargs: Optional arguments that ``request`` takes.
668 | :rtype: requests.Response
669 | """
670 |
671 | return self.request("DELETE", url, **kwargs)
672 |
673 | def send(self, request, **kwargs):
674 | """Send a given PreparedRequest.
675 |
676 | :rtype: requests.Response
677 | """
678 | # Set defaults that the hooks can utilize to ensure they always have
679 | # the correct parameters to reproduce the previous request.
680 | kwargs.setdefault("stream", self.stream)
681 | kwargs.setdefault("verify", self.verify)
682 | kwargs.setdefault("cert", self.cert)
683 | if "proxies" not in kwargs:
684 | kwargs["proxies"] = resolve_proxies(request, self.proxies, self.trust_env)
685 |
686 | # It's possible that users might accidentally send a Request object.
687 | # Guard against that specific failure case.
688 | if isinstance(request, Request):
689 | raise ValueError("You can only send PreparedRequests.")
690 |
691 | # Set up variables needed for resolve_redirects and dispatching of hooks
692 | allow_redirects = kwargs.pop("allow_redirects", True)
693 | stream = kwargs.get("stream")
694 | hooks = request.hooks
695 |
696 | # Get the appropriate adapter to use
697 | adapter = self.get_adapter(url=request.url)
698 |
699 | # Start time (approximately) of the request
700 | start = preferred_clock()
701 |
702 | # Send the request
703 | r = adapter.send(request, **kwargs)
704 |
705 | # Total elapsed time of the request (approximately)
706 | elapsed = preferred_clock() - start
707 | r.elapsed = timedelta(seconds=elapsed)
708 |
709 | # Response manipulation hooks
710 | r = dispatch_hook("response", hooks, r, **kwargs)
711 |
712 | # Persist cookies
713 | if r.history:
714 | # If the hooks create history then we want those cookies too
715 | for resp in r.history:
716 | extract_cookies_to_jar(self.cookies, resp.request, resp.raw)
717 |
718 | extract_cookies_to_jar(self.cookies, request, r.raw)
719 |
720 | # Resolve redirects if allowed.
721 | if allow_redirects:
722 | # Redirect resolving generator.
723 | gen = self.resolve_redirects(r, request, **kwargs)
724 | history = [resp for resp in gen]
725 | else:
726 | history = []
727 |
728 | # Shuffle things around if there's history.
729 | if history:
730 | # Insert the first (original) request at the start
731 | history.insert(0, r)
732 | # Get the last request made
733 | r = history.pop()
734 | r.history = history
735 |
736 | # If redirects aren't being followed, store the response on the Request for Response.next().
737 | if not allow_redirects:
738 | try:
739 | r._next = next(
740 | self.resolve_redirects(r, request, yield_requests=True, **kwargs)
741 | )
742 | except StopIteration:
743 | pass
744 |
745 | if not stream:
746 | r.content
747 |
748 | return r
749 |
750 | def merge_environment_settings(self, url, proxies, stream, verify, cert):
751 | """
752 | Check the environment and merge it with some settings.
753 |
754 | :rtype: dict
755 | """
756 | # Gather clues from the surrounding environment.
757 | if self.trust_env:
758 | # Set environment's proxies.
759 | no_proxy = proxies.get("no_proxy") if proxies is not None else None
760 | env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
761 | for k, v in env_proxies.items():
762 | proxies.setdefault(k, v)
763 |
764 | # Look for requests environment configuration
765 | # and be compatible with cURL.
766 | if verify is True or verify is None:
767 | verify = (
768 | os.environ.get("REQUESTS_CA_BUNDLE")
769 | or os.environ.get("CURL_CA_BUNDLE")
770 | or verify
771 | )
772 |
773 | # Merge all the kwargs.
774 | proxies = merge_setting(proxies, self.proxies)
775 | stream = merge_setting(stream, self.stream)
776 | verify = merge_setting(verify, self.verify)
777 | cert = merge_setting(cert, self.cert)
778 |
779 | return {"proxies": proxies, "stream": stream, "verify": verify, "cert": cert}
780 |
781 | def get_adapter(self, url):
782 | """
783 | Returns the appropriate connection adapter for the given URL.
784 |
785 | :rtype: requests.adapters.BaseAdapter
786 | """
787 | for prefix, adapter in self.adapters.items():
788 | if url.lower().startswith(prefix.lower()):
789 | return adapter
790 |
791 | # Nothing matches :-/
792 | raise InvalidSchema(f"No connection adapters were found for {url!r}")
793 |
794 | def close(self):
795 | """Closes all adapters and as such the session"""
796 | for v in self.adapters.values():
797 | v.close()
798 |
799 | def mount(self, prefix, adapter):
800 | """Registers a connection adapter to a prefix.
801 |
802 | Adapters are sorted in descending order by prefix length.
803 | """
804 | self.adapters[prefix] = adapter
805 | keys_to_move = [k for k in self.adapters if len(k) < len(prefix)]
806 |
807 | for key in keys_to_move:
808 | self.adapters[key] = self.adapters.pop(key)
809 |
810 | def __getstate__(self):
811 | state = {attr: getattr(self, attr, None) for attr in self.__attrs__}
812 | return state
813 |
814 | def __setstate__(self, state):
815 | for attr, value in state.items():
816 | setattr(self, attr, value)
817 |
818 |
819 | def session():
820 | """
821 | Returns a :class:`Session` for context-management.
822 |
823 | .. deprecated:: 1.0.0
824 |
825 | This method has been deprecated since version 1.0.0 and is only kept for
826 | backwards compatibility. New code should use :class:`~requests.sessions.Session`
827 | to create a session. This may be removed at a future date.
828 |
829 | :rtype: Session
830 | """
831 | return Session()
832 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/flask/sansio/scaffold.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import importlib.util
4 | import os
5 | import pathlib
6 | import sys
7 | import typing as t
8 | from collections import defaultdict
9 | from functools import update_wrapper
10 |
11 | from jinja2 import BaseLoader
12 | from jinja2 import FileSystemLoader
13 | from werkzeug.exceptions import default_exceptions
14 | from werkzeug.exceptions import HTTPException
15 | from werkzeug.utils import cached_property
16 |
17 | from .. import typing as ft
18 | from ..helpers import get_root_path
19 | from ..templating import _default_template_ctx_processor
20 |
21 | if t.TYPE_CHECKING: # pragma: no cover
22 | from click import Group
23 |
24 | # a singleton sentinel value for parameter defaults
25 | _sentinel = object()
26 |
27 | F = t.TypeVar("F", bound=t.Callable[..., t.Any])
28 | T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any])
29 | T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable)
30 | T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable)
31 | T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable)
32 | T_template_context_processor = t.TypeVar(
33 | "T_template_context_processor", bound=ft.TemplateContextProcessorCallable
34 | )
35 | T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable)
36 | T_url_value_preprocessor = t.TypeVar(
37 | "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable
38 | )
39 | T_route = t.TypeVar("T_route", bound=ft.RouteCallable)
40 |
41 |
42 | def setupmethod(f: F) -> F:
43 | f_name = f.__name__
44 |
45 | def wrapper_func(self: Scaffold, *args: t.Any, **kwargs: t.Any) -> t.Any:
46 | self._check_setup_finished(f_name)
47 | return f(self, *args, **kwargs)
48 |
49 | return t.cast(F, update_wrapper(wrapper_func, f))
50 |
51 |
52 | class Scaffold:
53 | """Common behavior shared between :class:`~flask.Flask` and
54 | :class:`~flask.blueprints.Blueprint`.
55 |
56 | :param import_name: The import name of the module where this object
57 | is defined. Usually :attr:`__name__` should be used.
58 | :param static_folder: Path to a folder of static files to serve.
59 | If this is set, a static route will be added.
60 | :param static_url_path: URL prefix for the static route.
61 | :param template_folder: Path to a folder containing template files.
62 | for rendering. If this is set, a Jinja loader will be added.
63 | :param root_path: The path that static, template, and resource files
64 | are relative to. Typically not set, it is discovered based on
65 | the ``import_name``.
66 |
67 | .. versionadded:: 2.0
68 | """
69 |
70 | cli: Group
71 | name: str
72 | _static_folder: str | None = None
73 | _static_url_path: str | None = None
74 |
75 | def __init__(
76 | self,
77 | import_name: str,
78 | static_folder: str | os.PathLike[str] | None = None,
79 | static_url_path: str | None = None,
80 | template_folder: str | os.PathLike[str] | None = None,
81 | root_path: str | None = None,
82 | ):
83 | #: The name of the package or module that this object belongs
84 | #: to. Do not change this once it is set by the constructor.
85 | self.import_name = import_name
86 |
87 | self.static_folder = static_folder # type: ignore
88 | self.static_url_path = static_url_path
89 |
90 | #: The path to the templates folder, relative to
91 | #: :attr:`root_path`, to add to the template loader. ``None`` if
92 | #: templates should not be added.
93 | self.template_folder = template_folder
94 |
95 | if root_path is None:
96 | root_path = get_root_path(self.import_name)
97 |
98 | #: Absolute path to the package on the filesystem. Used to look
99 | #: up resources contained in the package.
100 | self.root_path = root_path
101 |
102 | #: A dictionary mapping endpoint names to view functions.
103 | #:
104 | #: To register a view function, use the :meth:`route` decorator.
105 | #:
106 | #: This data structure is internal. It should not be modified
107 | #: directly and its format may change at any time.
108 | self.view_functions: dict[str, ft.RouteCallable] = {}
109 |
110 | #: A data structure of registered error handlers, in the format
111 | #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is
112 | #: the name of a blueprint the handlers are active for, or
113 | #: ``None`` for all requests. The ``code`` key is the HTTP
114 | #: status code for ``HTTPException``, or ``None`` for
115 | #: other exceptions. The innermost dictionary maps exception
116 | #: classes to handler functions.
117 | #:
118 | #: To register an error handler, use the :meth:`errorhandler`
119 | #: decorator.
120 | #:
121 | #: This data structure is internal. It should not be modified
122 | #: directly and its format may change at any time.
123 | self.error_handler_spec: dict[
124 | ft.AppOrBlueprintKey,
125 | dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]],
126 | ] = defaultdict(lambda: defaultdict(dict))
127 |
128 | #: A data structure of functions to call at the beginning of
129 | #: each request, in the format ``{scope: [functions]}``. The
130 | #: ``scope`` key is the name of a blueprint the functions are
131 | #: active for, or ``None`` for all requests.
132 | #:
133 | #: To register a function, use the :meth:`before_request`
134 | #: decorator.
135 | #:
136 | #: This data structure is internal. It should not be modified
137 | #: directly and its format may change at any time.
138 | self.before_request_funcs: dict[
139 | ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable]
140 | ] = defaultdict(list)
141 |
142 | #: A data structure of functions to call at the end of each
143 | #: request, in the format ``{scope: [functions]}``. The
144 | #: ``scope`` key is the name of a blueprint the functions are
145 | #: active for, or ``None`` for all requests.
146 | #:
147 | #: To register a function, use the :meth:`after_request`
148 | #: decorator.
149 | #:
150 | #: This data structure is internal. It should not be modified
151 | #: directly and its format may change at any time.
152 | self.after_request_funcs: dict[
153 | ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]]
154 | ] = defaultdict(list)
155 |
156 | #: A data structure of functions to call at the end of each
157 | #: request even if an exception is raised, in the format
158 | #: ``{scope: [functions]}``. The ``scope`` key is the name of a
159 | #: blueprint the functions are active for, or ``None`` for all
160 | #: requests.
161 | #:
162 | #: To register a function, use the :meth:`teardown_request`
163 | #: decorator.
164 | #:
165 | #: This data structure is internal. It should not be modified
166 | #: directly and its format may change at any time.
167 | self.teardown_request_funcs: dict[
168 | ft.AppOrBlueprintKey, list[ft.TeardownCallable]
169 | ] = defaultdict(list)
170 |
171 | #: A data structure of functions to call to pass extra context
172 | #: values when rendering templates, in the format
173 | #: ``{scope: [functions]}``. The ``scope`` key is the name of a
174 | #: blueprint the functions are active for, or ``None`` for all
175 | #: requests.
176 | #:
177 | #: To register a function, use the :meth:`context_processor`
178 | #: decorator.
179 | #:
180 | #: This data structure is internal. It should not be modified
181 | #: directly and its format may change at any time.
182 | self.template_context_processors: dict[
183 | ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable]
184 | ] = defaultdict(list, {None: [_default_template_ctx_processor]})
185 |
186 | #: A data structure of functions to call to modify the keyword
187 | #: arguments passed to the view function, in the format
188 | #: ``{scope: [functions]}``. The ``scope`` key is the name of a
189 | #: blueprint the functions are active for, or ``None`` for all
190 | #: requests.
191 | #:
192 | #: To register a function, use the
193 | #: :meth:`url_value_preprocessor` decorator.
194 | #:
195 | #: This data structure is internal. It should not be modified
196 | #: directly and its format may change at any time.
197 | self.url_value_preprocessors: dict[
198 | ft.AppOrBlueprintKey,
199 | list[ft.URLValuePreprocessorCallable],
200 | ] = defaultdict(list)
201 |
202 | #: A data structure of functions to call to modify the keyword
203 | #: arguments when generating URLs, in the format
204 | #: ``{scope: [functions]}``. The ``scope`` key is the name of a
205 | #: blueprint the functions are active for, or ``None`` for all
206 | #: requests.
207 | #:
208 | #: To register a function, use the :meth:`url_defaults`
209 | #: decorator.
210 | #:
211 | #: This data structure is internal. It should not be modified
212 | #: directly and its format may change at any time.
213 | self.url_default_functions: dict[
214 | ft.AppOrBlueprintKey, list[ft.URLDefaultCallable]
215 | ] = defaultdict(list)
216 |
217 | def __repr__(self) -> str:
218 | return f"<{type(self).__name__} {self.name!r}>"
219 |
220 | def _check_setup_finished(self, f_name: str) -> None:
221 | raise NotImplementedError
222 |
223 | @property
224 | def static_folder(self) -> str | None:
225 | """The absolute path to the configured static folder. ``None``
226 | if no static folder is set.
227 | """
228 | if self._static_folder is not None:
229 | return os.path.join(self.root_path, self._static_folder)
230 | else:
231 | return None
232 |
233 | @static_folder.setter
234 | def static_folder(self, value: str | os.PathLike[str] | None) -> None:
235 | if value is not None:
236 | value = os.fspath(value).rstrip(r"\/")
237 |
238 | self._static_folder = value
239 |
240 | @property
241 | def has_static_folder(self) -> bool:
242 | """``True`` if :attr:`static_folder` is set.
243 |
244 | .. versionadded:: 0.5
245 | """
246 | return self.static_folder is not None
247 |
248 | @property
249 | def static_url_path(self) -> str | None:
250 | """The URL prefix that the static route will be accessible from.
251 |
252 | If it was not configured during init, it is derived from
253 | :attr:`static_folder`.
254 | """
255 | if self._static_url_path is not None:
256 | return self._static_url_path
257 |
258 | if self.static_folder is not None:
259 | basename = os.path.basename(self.static_folder)
260 | return f"/{basename}".rstrip("/")
261 |
262 | return None
263 |
264 | @static_url_path.setter
265 | def static_url_path(self, value: str | None) -> None:
266 | if value is not None:
267 | value = value.rstrip("/")
268 |
269 | self._static_url_path = value
270 |
271 | @cached_property
272 | def jinja_loader(self) -> BaseLoader | None:
273 | """The Jinja loader for this object's templates. By default this
274 | is a class :class:`jinja2.loaders.FileSystemLoader` to
275 | :attr:`template_folder` if it is set.
276 |
277 | .. versionadded:: 0.5
278 | """
279 | if self.template_folder is not None:
280 | return FileSystemLoader(os.path.join(self.root_path, self.template_folder))
281 | else:
282 | return None
283 |
284 | def _method_route(
285 | self,
286 | method: str,
287 | rule: str,
288 | options: dict[str, t.Any],
289 | ) -> t.Callable[[T_route], T_route]:
290 | if "methods" in options:
291 | raise TypeError("Use the 'route' decorator to use the 'methods' argument.")
292 |
293 | return self.route(rule, methods=[method], **options)
294 |
295 | @setupmethod
296 | def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
297 | """Shortcut for :meth:`route` with ``methods=["GET"]``.
298 |
299 | .. versionadded:: 2.0
300 | """
301 | return self._method_route("GET", rule, options)
302 |
303 | @setupmethod
304 | def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
305 | """Shortcut for :meth:`route` with ``methods=["POST"]``.
306 |
307 | .. versionadded:: 2.0
308 | """
309 | return self._method_route("POST", rule, options)
310 |
311 | @setupmethod
312 | def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
313 | """Shortcut for :meth:`route` with ``methods=["PUT"]``.
314 |
315 | .. versionadded:: 2.0
316 | """
317 | return self._method_route("PUT", rule, options)
318 |
319 | @setupmethod
320 | def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
321 | """Shortcut for :meth:`route` with ``methods=["DELETE"]``.
322 |
323 | .. versionadded:: 2.0
324 | """
325 | return self._method_route("DELETE", rule, options)
326 |
327 | @setupmethod
328 | def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
329 | """Shortcut for :meth:`route` with ``methods=["PATCH"]``.
330 |
331 | .. versionadded:: 2.0
332 | """
333 | return self._method_route("PATCH", rule, options)
334 |
335 | @setupmethod
336 | def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
337 | """Decorate a view function to register it with the given URL
338 | rule and options. Calls :meth:`add_url_rule`, which has more
339 | details about the implementation.
340 |
341 | .. code-block:: python
342 |
343 | @app.route("/")
344 | def index():
345 | return "Hello, World!"
346 |
347 | See :ref:`url-route-registrations`.
348 |
349 | The endpoint name for the route defaults to the name of the view
350 | function if the ``endpoint`` parameter isn't passed.
351 |
352 | The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and
353 | ``OPTIONS`` are added automatically.
354 |
355 | :param rule: The URL rule string.
356 | :param options: Extra options passed to the
357 | :class:`~werkzeug.routing.Rule` object.
358 | """
359 |
360 | def decorator(f: T_route) -> T_route:
361 | endpoint = options.pop("endpoint", None)
362 | self.add_url_rule(rule, endpoint, f, **options)
363 | return f
364 |
365 | return decorator
366 |
367 | @setupmethod
368 | def add_url_rule(
369 | self,
370 | rule: str,
371 | endpoint: str | None = None,
372 | view_func: ft.RouteCallable | None = None,
373 | provide_automatic_options: bool | None = None,
374 | **options: t.Any,
375 | ) -> None:
376 | """Register a rule for routing incoming requests and building
377 | URLs. The :meth:`route` decorator is a shortcut to call this
378 | with the ``view_func`` argument. These are equivalent:
379 |
380 | .. code-block:: python
381 |
382 | @app.route("/")
383 | def index():
384 | ...
385 |
386 | .. code-block:: python
387 |
388 | def index():
389 | ...
390 |
391 | app.add_url_rule("/", view_func=index)
392 |
393 | See :ref:`url-route-registrations`.
394 |
395 | The endpoint name for the route defaults to the name of the view
396 | function if the ``endpoint`` parameter isn't passed. An error
397 | will be raised if a function has already been registered for the
398 | endpoint.
399 |
400 | The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is
401 | always added automatically, and ``OPTIONS`` is added
402 | automatically by default.
403 |
404 | ``view_func`` does not necessarily need to be passed, but if the
405 | rule should participate in routing an endpoint name must be
406 | associated with a view function at some point with the
407 | :meth:`endpoint` decorator.
408 |
409 | .. code-block:: python
410 |
411 | app.add_url_rule("/", endpoint="index")
412 |
413 | @app.endpoint("index")
414 | def index():
415 | ...
416 |
417 | If ``view_func`` has a ``required_methods`` attribute, those
418 | methods are added to the passed and automatic methods. If it
419 | has a ``provide_automatic_methods`` attribute, it is used as the
420 | default if the parameter is not passed.
421 |
422 | :param rule: The URL rule string.
423 | :param endpoint: The endpoint name to associate with the rule
424 | and view function. Used when routing and building URLs.
425 | Defaults to ``view_func.__name__``.
426 | :param view_func: The view function to associate with the
427 | endpoint name.
428 | :param provide_automatic_options: Add the ``OPTIONS`` method and
429 | respond to ``OPTIONS`` requests automatically.
430 | :param options: Extra options passed to the
431 | :class:`~werkzeug.routing.Rule` object.
432 | """
433 | raise NotImplementedError
434 |
435 | @setupmethod
436 | def endpoint(self, endpoint: str) -> t.Callable[[F], F]:
437 | """Decorate a view function to register it for the given
438 | endpoint. Used if a rule is added without a ``view_func`` with
439 | :meth:`add_url_rule`.
440 |
441 | .. code-block:: python
442 |
443 | app.add_url_rule("/ex", endpoint="example")
444 |
445 | @app.endpoint("example")
446 | def example():
447 | ...
448 |
449 | :param endpoint: The endpoint name to associate with the view
450 | function.
451 | """
452 |
453 | def decorator(f: F) -> F:
454 | self.view_functions[endpoint] = f
455 | return f
456 |
457 | return decorator
458 |
459 | @setupmethod
460 | def before_request(self, f: T_before_request) -> T_before_request:
461 | """Register a function to run before each request.
462 |
463 | For example, this can be used to open a database connection, or
464 | to load the logged in user from the session.
465 |
466 | .. code-block:: python
467 |
468 | @app.before_request
469 | def load_user():
470 | if "user_id" in session:
471 | g.user = db.session.get(session["user_id"])
472 |
473 | The function will be called without any arguments. If it returns
474 | a non-``None`` value, the value is handled as if it was the
475 | return value from the view, and further request handling is
476 | stopped.
477 |
478 | This is available on both app and blueprint objects. When used on an app, this
479 | executes before every request. When used on a blueprint, this executes before
480 | every request that the blueprint handles. To register with a blueprint and
481 | execute before every request, use :meth:`.Blueprint.before_app_request`.
482 | """
483 | self.before_request_funcs.setdefault(None, []).append(f)
484 | return f
485 |
486 | @setupmethod
487 | def after_request(self, f: T_after_request) -> T_after_request:
488 | """Register a function to run after each request to this object.
489 |
490 | The function is called with the response object, and must return
491 | a response object. This allows the functions to modify or
492 | replace the response before it is sent.
493 |
494 | If a function raises an exception, any remaining
495 | ``after_request`` functions will not be called. Therefore, this
496 | should not be used for actions that must execute, such as to
497 | close resources. Use :meth:`teardown_request` for that.
498 |
499 | This is available on both app and blueprint objects. When used on an app, this
500 | executes after every request. When used on a blueprint, this executes after
501 | every request that the blueprint handles. To register with a blueprint and
502 | execute after every request, use :meth:`.Blueprint.after_app_request`.
503 | """
504 | self.after_request_funcs.setdefault(None, []).append(f)
505 | return f
506 |
507 | @setupmethod
508 | def teardown_request(self, f: T_teardown) -> T_teardown:
509 | """Register a function to be called when the request context is
510 | popped. Typically this happens at the end of each request, but
511 | contexts may be pushed manually as well during testing.
512 |
513 | .. code-block:: python
514 |
515 | with app.test_request_context():
516 | ...
517 |
518 | When the ``with`` block exits (or ``ctx.pop()`` is called), the
519 | teardown functions are called just before the request context is
520 | made inactive.
521 |
522 | When a teardown function was called because of an unhandled
523 | exception it will be passed an error object. If an
524 | :meth:`errorhandler` is registered, it will handle the exception
525 | and the teardown will not receive it.
526 |
527 | Teardown functions must avoid raising exceptions. If they
528 | execute code that might fail they must surround that code with a
529 | ``try``/``except`` block and log any errors.
530 |
531 | The return values of teardown functions are ignored.
532 |
533 | This is available on both app and blueprint objects. When used on an app, this
534 | executes after every request. When used on a blueprint, this executes after
535 | every request that the blueprint handles. To register with a blueprint and
536 | execute after every request, use :meth:`.Blueprint.teardown_app_request`.
537 | """
538 | self.teardown_request_funcs.setdefault(None, []).append(f)
539 | return f
540 |
541 | @setupmethod
542 | def context_processor(
543 | self,
544 | f: T_template_context_processor,
545 | ) -> T_template_context_processor:
546 | """Registers a template context processor function. These functions run before
547 | rendering a template. The keys of the returned dict are added as variables
548 | available in the template.
549 |
550 | This is available on both app and blueprint objects. When used on an app, this
551 | is called for every rendered template. When used on a blueprint, this is called
552 | for templates rendered from the blueprint's views. To register with a blueprint
553 | and affect every template, use :meth:`.Blueprint.app_context_processor`.
554 | """
555 | self.template_context_processors[None].append(f)
556 | return f
557 |
558 | @setupmethod
559 | def url_value_preprocessor(
560 | self,
561 | f: T_url_value_preprocessor,
562 | ) -> T_url_value_preprocessor:
563 | """Register a URL value preprocessor function for all view
564 | functions in the application. These functions will be called before the
565 | :meth:`before_request` functions.
566 |
567 | The function can modify the values captured from the matched url before
568 | they are passed to the view. For example, this can be used to pop a
569 | common language code value and place it in ``g`` rather than pass it to
570 | every view.
571 |
572 | The function is passed the endpoint name and values dict. The return
573 | value is ignored.
574 |
575 | This is available on both app and blueprint objects. When used on an app, this
576 | is called for every request. When used on a blueprint, this is called for
577 | requests that the blueprint handles. To register with a blueprint and affect
578 | every request, use :meth:`.Blueprint.app_url_value_preprocessor`.
579 | """
580 | self.url_value_preprocessors[None].append(f)
581 | return f
582 |
583 | @setupmethod
584 | def url_defaults(self, f: T_url_defaults) -> T_url_defaults:
585 | """Callback function for URL defaults for all view functions of the
586 | application. It's called with the endpoint and values and should
587 | update the values passed in place.
588 |
589 | This is available on both app and blueprint objects. When used on an app, this
590 | is called for every request. When used on a blueprint, this is called for
591 | requests that the blueprint handles. To register with a blueprint and affect
592 | every request, use :meth:`.Blueprint.app_url_defaults`.
593 | """
594 | self.url_default_functions[None].append(f)
595 | return f
596 |
597 | @setupmethod
598 | def errorhandler(
599 | self, code_or_exception: type[Exception] | int
600 | ) -> t.Callable[[T_error_handler], T_error_handler]:
601 | """Register a function to handle errors by code or exception class.
602 |
603 | A decorator that is used to register a function given an
604 | error code. Example::
605 |
606 | @app.errorhandler(404)
607 | def page_not_found(error):
608 | return 'This page does not exist', 404
609 |
610 | You can also register handlers for arbitrary exceptions::
611 |
612 | @app.errorhandler(DatabaseError)
613 | def special_exception_handler(error):
614 | return 'Database connection failed', 500
615 |
616 | This is available on both app and blueprint objects. When used on an app, this
617 | can handle errors from every request. When used on a blueprint, this can handle
618 | errors from requests that the blueprint handles. To register with a blueprint
619 | and affect every request, use :meth:`.Blueprint.app_errorhandler`.
620 |
621 | .. versionadded:: 0.7
622 | Use :meth:`register_error_handler` instead of modifying
623 | :attr:`error_handler_spec` directly, for application wide error
624 | handlers.
625 |
626 | .. versionadded:: 0.7
627 | One can now additionally also register custom exception types
628 | that do not necessarily have to be a subclass of the
629 | :class:`~werkzeug.exceptions.HTTPException` class.
630 |
631 | :param code_or_exception: the code as integer for the handler, or
632 | an arbitrary exception
633 | """
634 |
635 | def decorator(f: T_error_handler) -> T_error_handler:
636 | self.register_error_handler(code_or_exception, f)
637 | return f
638 |
639 | return decorator
640 |
641 | @setupmethod
642 | def register_error_handler(
643 | self,
644 | code_or_exception: type[Exception] | int,
645 | f: ft.ErrorHandlerCallable,
646 | ) -> None:
647 | """Alternative error attach function to the :meth:`errorhandler`
648 | decorator that is more straightforward to use for non decorator
649 | usage.
650 |
651 | .. versionadded:: 0.7
652 | """
653 | exc_class, code = self._get_exc_class_and_code(code_or_exception)
654 | self.error_handler_spec[None][code][exc_class] = f
655 |
656 | @staticmethod
657 | def _get_exc_class_and_code(
658 | exc_class_or_code: type[Exception] | int,
659 | ) -> tuple[type[Exception], int | None]:
660 | """Get the exception class being handled. For HTTP status codes
661 | or ``HTTPException`` subclasses, return both the exception and
662 | status code.
663 |
664 | :param exc_class_or_code: Any exception class, or an HTTP status
665 | code as an integer.
666 | """
667 | exc_class: type[Exception]
668 |
669 | if isinstance(exc_class_or_code, int):
670 | try:
671 | exc_class = default_exceptions[exc_class_or_code]
672 | except KeyError:
673 | raise ValueError(
674 | f"'{exc_class_or_code}' is not a recognized HTTP"
675 | " error code. Use a subclass of HTTPException with"
676 | " that code instead."
677 | ) from None
678 | else:
679 | exc_class = exc_class_or_code
680 |
681 | if isinstance(exc_class, Exception):
682 | raise TypeError(
683 | f"{exc_class!r} is an instance, not a class. Handlers"
684 | " can only be registered for Exception classes or HTTP"
685 | " error codes."
686 | )
687 |
688 | if not issubclass(exc_class, Exception):
689 | raise ValueError(
690 | f"'{exc_class.__name__}' is not a subclass of Exception."
691 | " Handlers can only be registered for Exception classes"
692 | " or HTTP error codes."
693 | )
694 |
695 | if issubclass(exc_class, HTTPException):
696 | return exc_class, exc_class.code
697 | else:
698 | return exc_class, None
699 |
700 |
701 | def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str:
702 | """Internal helper that returns the default endpoint for a given
703 | function. This always is the function name.
704 | """
705 | assert view_func is not None, "expected view func if endpoint is not provided."
706 | return view_func.__name__
707 |
708 |
709 | def _path_is_relative_to(path: pathlib.PurePath, base: str) -> bool:
710 | # Path.is_relative_to doesn't exist until Python 3.9
711 | try:
712 | path.relative_to(base)
713 | return True
714 | except ValueError:
715 | return False
716 |
717 |
718 | def _find_package_path(import_name: str) -> str:
719 | """Find the path that contains the package or module."""
720 | root_mod_name, _, _ = import_name.partition(".")
721 |
722 | try:
723 | root_spec = importlib.util.find_spec(root_mod_name)
724 |
725 | if root_spec is None:
726 | raise ValueError("not found")
727 | except (ImportError, ValueError):
728 | # ImportError: the machinery told us it does not exist
729 | # ValueError:
730 | # - the module name was invalid
731 | # - the module name is __main__
732 | # - we raised `ValueError` due to `root_spec` being `None`
733 | return os.getcwd()
734 |
735 | if root_spec.submodule_search_locations:
736 | if root_spec.origin is None or root_spec.origin == "namespace":
737 | # namespace package
738 | package_spec = importlib.util.find_spec(import_name)
739 |
740 | if package_spec is not None and package_spec.submodule_search_locations:
741 | # Pick the path in the namespace that contains the submodule.
742 | package_path = pathlib.Path(
743 | os.path.commonpath(package_spec.submodule_search_locations)
744 | )
745 | search_location = next(
746 | location
747 | for location in root_spec.submodule_search_locations
748 | if _path_is_relative_to(package_path, location)
749 | )
750 | else:
751 | # Pick the first path.
752 | search_location = root_spec.submodule_search_locations[0]
753 |
754 | return os.path.dirname(search_location)
755 | else:
756 | # package with __init__.py
757 | return os.path.dirname(os.path.dirname(root_spec.origin))
758 | else:
759 | # module
760 | return os.path.dirname(root_spec.origin) # type: ignore[type-var, return-value]
761 |
762 |
763 | def find_package(import_name: str) -> tuple[str | None, str]:
764 | """Find the prefix that a package is installed under, and the path
765 | that it would be imported from.
766 |
767 | The prefix is the directory containing the standard directory
768 | hierarchy (lib, bin, etc.). If the package is not installed to the
769 | system (:attr:`sys.prefix`) or a virtualenv (``site-packages``),
770 | ``None`` is returned.
771 |
772 | The path is the entry in :attr:`sys.path` that contains the package
773 | for import. If the package is not installed, it's assumed that the
774 | package was imported from the current working directory.
775 | """
776 | package_path = _find_package_path(import_name)
777 | py_prefix = os.path.abspath(sys.prefix)
778 |
779 | # installed to the system
780 | if _path_is_relative_to(pathlib.PurePath(package_path), py_prefix):
781 | return py_prefix, package_path
782 |
783 | site_parent, site_folder = os.path.split(package_path)
784 |
785 | # installed to a virtualenv
786 | if site_folder.lower() == "site-packages":
787 | parent, folder = os.path.split(site_parent)
788 |
789 | # Windows (prefix/lib/site-packages)
790 | if folder.lower() == "lib":
791 | return parent, package_path
792 |
793 | # Unix (prefix/lib/pythonX.Y/site-packages)
794 | if os.path.basename(parent).lower() == "lib":
795 | return os.path.dirname(parent), package_path
796 |
797 | # something else (prefix/site-packages)
798 | return site_parent, package_path
799 |
800 | # not installed
801 | return None, package_path
802 |
```