#
tokens: 49932/50000 4/808 files (page 54/168)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 54 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/werkzeug/formparser.py:
--------------------------------------------------------------------------------

```python
  1 | from __future__ import annotations
  2 | 
  3 | import typing as t
  4 | from io import BytesIO
  5 | from urllib.parse import parse_qsl
  6 | 
  7 | from ._internal import _plain_int
  8 | from .datastructures import FileStorage
  9 | from .datastructures import Headers
 10 | from .datastructures import MultiDict
 11 | from .exceptions import RequestEntityTooLarge
 12 | from .http import parse_options_header
 13 | from .sansio.multipart import Data
 14 | from .sansio.multipart import Epilogue
 15 | from .sansio.multipart import Field
 16 | from .sansio.multipart import File
 17 | from .sansio.multipart import MultipartDecoder
 18 | from .sansio.multipart import NeedData
 19 | from .wsgi import get_content_length
 20 | from .wsgi import get_input_stream
 21 | 
 22 | # there are some platforms where SpooledTemporaryFile is not available.
 23 | # In that case we need to provide a fallback.
 24 | try:
 25 |     from tempfile import SpooledTemporaryFile
 26 | except ImportError:
 27 |     from tempfile import TemporaryFile
 28 | 
 29 |     SpooledTemporaryFile = None  # type: ignore
 30 | 
 31 | if t.TYPE_CHECKING:
 32 |     import typing as te
 33 | 
 34 |     from _typeshed.wsgi import WSGIEnvironment
 35 | 
 36 |     t_parse_result = t.Tuple[
 37 |         t.IO[bytes], MultiDict[str, str], MultiDict[str, FileStorage]
 38 |     ]
 39 | 
 40 |     class TStreamFactory(te.Protocol):
 41 |         def __call__(
 42 |             self,
 43 |             total_content_length: int | None,
 44 |             content_type: str | None,
 45 |             filename: str | None,
 46 |             content_length: int | None = None,
 47 |         ) -> t.IO[bytes]: ...
 48 | 
 49 | 
 50 | F = t.TypeVar("F", bound=t.Callable[..., t.Any])
 51 | 
 52 | 
 53 | def default_stream_factory(
 54 |     total_content_length: int | None,
 55 |     content_type: str | None,
 56 |     filename: str | None,
 57 |     content_length: int | None = None,
 58 | ) -> t.IO[bytes]:
 59 |     max_size = 1024 * 500
 60 | 
 61 |     if SpooledTemporaryFile is not None:
 62 |         return t.cast(t.IO[bytes], SpooledTemporaryFile(max_size=max_size, mode="rb+"))
 63 |     elif total_content_length is None or total_content_length > max_size:
 64 |         return t.cast(t.IO[bytes], TemporaryFile("rb+"))
 65 | 
 66 |     return BytesIO()
 67 | 
 68 | 
 69 | def parse_form_data(
 70 |     environ: WSGIEnvironment,
 71 |     stream_factory: TStreamFactory | None = None,
 72 |     max_form_memory_size: int | None = None,
 73 |     max_content_length: int | None = None,
 74 |     cls: type[MultiDict[str, t.Any]] | None = None,
 75 |     silent: bool = True,
 76 |     *,
 77 |     max_form_parts: int | None = None,
 78 | ) -> t_parse_result:
 79 |     """Parse the form data in the environ and return it as tuple in the form
 80 |     ``(stream, form, files)``.  You should only call this method if the
 81 |     transport method is `POST`, `PUT`, or `PATCH`.
 82 | 
 83 |     If the mimetype of the data transmitted is `multipart/form-data` the
 84 |     files multidict will be filled with `FileStorage` objects.  If the
 85 |     mimetype is unknown the input stream is wrapped and returned as first
 86 |     argument, else the stream is empty.
 87 | 
 88 |     This is a shortcut for the common usage of :class:`FormDataParser`.
 89 | 
 90 |     :param environ: the WSGI environment to be used for parsing.
 91 |     :param stream_factory: An optional callable that returns a new read and
 92 |                            writeable file descriptor.  This callable works
 93 |                            the same as :meth:`Response._get_file_stream`.
 94 |     :param max_form_memory_size: the maximum number of bytes to be accepted for
 95 |                            in-memory stored form data.  If the data
 96 |                            exceeds the value specified an
 97 |                            :exc:`~exceptions.RequestEntityTooLarge`
 98 |                            exception is raised.
 99 |     :param max_content_length: If this is provided and the transmitted data
100 |                                is longer than this value an
101 |                                :exc:`~exceptions.RequestEntityTooLarge`
102 |                                exception is raised.
103 |     :param cls: an optional dict class to use.  If this is not specified
104 |                        or `None` the default :class:`MultiDict` is used.
105 |     :param silent: If set to False parsing errors will not be caught.
106 |     :param max_form_parts: The maximum number of multipart parts to be parsed. If this
107 |         is exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised.
108 |     :return: A tuple in the form ``(stream, form, files)``.
109 | 
110 |     .. versionchanged:: 3.0
111 |         The ``charset`` and ``errors`` parameters were removed.
112 | 
113 |     .. versionchanged:: 2.3
114 |         Added the ``max_form_parts`` parameter.
115 | 
116 |     .. versionadded:: 0.5.1
117 |        Added the ``silent`` parameter.
118 | 
119 |     .. versionadded:: 0.5
120 |        Added the ``max_form_memory_size``, ``max_content_length``, and ``cls``
121 |        parameters.
122 |     """
123 |     return FormDataParser(
124 |         stream_factory=stream_factory,
125 |         max_form_memory_size=max_form_memory_size,
126 |         max_content_length=max_content_length,
127 |         max_form_parts=max_form_parts,
128 |         silent=silent,
129 |         cls=cls,
130 |     ).parse_from_environ(environ)
131 | 
132 | 
133 | class FormDataParser:
134 |     """This class implements parsing of form data for Werkzeug.  By itself
135 |     it can parse multipart and url encoded form data.  It can be subclassed
136 |     and extended but for most mimetypes it is a better idea to use the
137 |     untouched stream and expose it as separate attributes on a request
138 |     object.
139 | 
140 |     :param stream_factory: An optional callable that returns a new read and
141 |                            writeable file descriptor.  This callable works
142 |                            the same as :meth:`Response._get_file_stream`.
143 |     :param max_form_memory_size: the maximum number of bytes to be accepted for
144 |                            in-memory stored form data.  If the data
145 |                            exceeds the value specified an
146 |                            :exc:`~exceptions.RequestEntityTooLarge`
147 |                            exception is raised.
148 |     :param max_content_length: If this is provided and the transmitted data
149 |                                is longer than this value an
150 |                                :exc:`~exceptions.RequestEntityTooLarge`
151 |                                exception is raised.
152 |     :param cls: an optional dict class to use.  If this is not specified
153 |                        or `None` the default :class:`MultiDict` is used.
154 |     :param silent: If set to False parsing errors will not be caught.
155 |     :param max_form_parts: The maximum number of multipart parts to be parsed. If this
156 |         is exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised.
157 | 
158 |     .. versionchanged:: 3.0
159 |         The ``charset`` and ``errors`` parameters were removed.
160 | 
161 |     .. versionchanged:: 3.0
162 |         The ``parse_functions`` attribute and ``get_parse_func`` methods were removed.
163 | 
164 |     .. versionchanged:: 2.2.3
165 |         Added the ``max_form_parts`` parameter.
166 | 
167 |     .. versionadded:: 0.8
168 |     """
169 | 
170 |     def __init__(
171 |         self,
172 |         stream_factory: TStreamFactory | None = None,
173 |         max_form_memory_size: int | None = None,
174 |         max_content_length: int | None = None,
175 |         cls: type[MultiDict[str, t.Any]] | None = None,
176 |         silent: bool = True,
177 |         *,
178 |         max_form_parts: int | None = None,
179 |     ) -> None:
180 |         if stream_factory is None:
181 |             stream_factory = default_stream_factory
182 | 
183 |         self.stream_factory = stream_factory
184 |         self.max_form_memory_size = max_form_memory_size
185 |         self.max_content_length = max_content_length
186 |         self.max_form_parts = max_form_parts
187 | 
188 |         if cls is None:
189 |             cls = t.cast("type[MultiDict[str, t.Any]]", MultiDict)
190 | 
191 |         self.cls = cls
192 |         self.silent = silent
193 | 
194 |     def parse_from_environ(self, environ: WSGIEnvironment) -> t_parse_result:
195 |         """Parses the information from the environment as form data.
196 | 
197 |         :param environ: the WSGI environment to be used for parsing.
198 |         :return: A tuple in the form ``(stream, form, files)``.
199 |         """
200 |         stream = get_input_stream(environ, max_content_length=self.max_content_length)
201 |         content_length = get_content_length(environ)
202 |         mimetype, options = parse_options_header(environ.get("CONTENT_TYPE"))
203 |         return self.parse(
204 |             stream,
205 |             content_length=content_length,
206 |             mimetype=mimetype,
207 |             options=options,
208 |         )
209 | 
210 |     def parse(
211 |         self,
212 |         stream: t.IO[bytes],
213 |         mimetype: str,
214 |         content_length: int | None,
215 |         options: dict[str, str] | None = None,
216 |     ) -> t_parse_result:
217 |         """Parses the information from the given stream, mimetype,
218 |         content length and mimetype parameters.
219 | 
220 |         :param stream: an input stream
221 |         :param mimetype: the mimetype of the data
222 |         :param content_length: the content length of the incoming data
223 |         :param options: optional mimetype parameters (used for
224 |                         the multipart boundary for instance)
225 |         :return: A tuple in the form ``(stream, form, files)``.
226 | 
227 |         .. versionchanged:: 3.0
228 |             The invalid ``application/x-url-encoded`` content type is not
229 |             treated as ``application/x-www-form-urlencoded``.
230 |         """
231 |         if mimetype == "multipart/form-data":
232 |             parse_func = self._parse_multipart
233 |         elif mimetype == "application/x-www-form-urlencoded":
234 |             parse_func = self._parse_urlencoded
235 |         else:
236 |             return stream, self.cls(), self.cls()
237 | 
238 |         if options is None:
239 |             options = {}
240 | 
241 |         try:
242 |             return parse_func(stream, mimetype, content_length, options)
243 |         except ValueError:
244 |             if not self.silent:
245 |                 raise
246 | 
247 |         return stream, self.cls(), self.cls()
248 | 
249 |     def _parse_multipart(
250 |         self,
251 |         stream: t.IO[bytes],
252 |         mimetype: str,
253 |         content_length: int | None,
254 |         options: dict[str, str],
255 |     ) -> t_parse_result:
256 |         parser = MultiPartParser(
257 |             stream_factory=self.stream_factory,
258 |             max_form_memory_size=self.max_form_memory_size,
259 |             max_form_parts=self.max_form_parts,
260 |             cls=self.cls,
261 |         )
262 |         boundary = options.get("boundary", "").encode("ascii")
263 | 
264 |         if not boundary:
265 |             raise ValueError("Missing boundary")
266 | 
267 |         form, files = parser.parse(stream, boundary, content_length)
268 |         return stream, form, files
269 | 
270 |     def _parse_urlencoded(
271 |         self,
272 |         stream: t.IO[bytes],
273 |         mimetype: str,
274 |         content_length: int | None,
275 |         options: dict[str, str],
276 |     ) -> t_parse_result:
277 |         if (
278 |             self.max_form_memory_size is not None
279 |             and content_length is not None
280 |             and content_length > self.max_form_memory_size
281 |         ):
282 |             raise RequestEntityTooLarge()
283 | 
284 |         items = parse_qsl(
285 |             stream.read().decode(),
286 |             keep_blank_values=True,
287 |             errors="werkzeug.url_quote",
288 |         )
289 |         return stream, self.cls(items), self.cls()
290 | 
291 | 
292 | class MultiPartParser:
293 |     def __init__(
294 |         self,
295 |         stream_factory: TStreamFactory | None = None,
296 |         max_form_memory_size: int | None = None,
297 |         cls: type[MultiDict[str, t.Any]] | None = None,
298 |         buffer_size: int = 64 * 1024,
299 |         max_form_parts: int | None = None,
300 |     ) -> None:
301 |         self.max_form_memory_size = max_form_memory_size
302 |         self.max_form_parts = max_form_parts
303 | 
304 |         if stream_factory is None:
305 |             stream_factory = default_stream_factory
306 | 
307 |         self.stream_factory = stream_factory
308 | 
309 |         if cls is None:
310 |             cls = t.cast("type[MultiDict[str, t.Any]]", MultiDict)
311 | 
312 |         self.cls = cls
313 |         self.buffer_size = buffer_size
314 | 
315 |     def fail(self, message: str) -> te.NoReturn:
316 |         raise ValueError(message)
317 | 
318 |     def get_part_charset(self, headers: Headers) -> str:
319 |         # Figure out input charset for current part
320 |         content_type = headers.get("content-type")
321 | 
322 |         if content_type:
323 |             parameters = parse_options_header(content_type)[1]
324 |             ct_charset = parameters.get("charset", "").lower()
325 | 
326 |             # A safe list of encodings. Modern clients should only send ASCII or UTF-8.
327 |             # This list will not be extended further.
328 |             if ct_charset in {"ascii", "us-ascii", "utf-8", "iso-8859-1"}:
329 |                 return ct_charset
330 | 
331 |         return "utf-8"
332 | 
333 |     def start_file_streaming(
334 |         self, event: File, total_content_length: int | None
335 |     ) -> t.IO[bytes]:
336 |         content_type = event.headers.get("content-type")
337 | 
338 |         try:
339 |             content_length = _plain_int(event.headers["content-length"])
340 |         except (KeyError, ValueError):
341 |             content_length = 0
342 | 
343 |         container = self.stream_factory(
344 |             total_content_length=total_content_length,
345 |             filename=event.filename,
346 |             content_type=content_type,
347 |             content_length=content_length,
348 |         )
349 |         return container
350 | 
351 |     def parse(
352 |         self, stream: t.IO[bytes], boundary: bytes, content_length: int | None
353 |     ) -> tuple[MultiDict[str, str], MultiDict[str, FileStorage]]:
354 |         current_part: Field | File
355 |         container: t.IO[bytes] | list[bytes]
356 |         _write: t.Callable[[bytes], t.Any]
357 | 
358 |         parser = MultipartDecoder(
359 |             boundary,
360 |             max_form_memory_size=self.max_form_memory_size,
361 |             max_parts=self.max_form_parts,
362 |         )
363 | 
364 |         fields = []
365 |         files = []
366 | 
367 |         for data in _chunk_iter(stream.read, self.buffer_size):
368 |             parser.receive_data(data)
369 |             event = parser.next_event()
370 |             while not isinstance(event, (Epilogue, NeedData)):
371 |                 if isinstance(event, Field):
372 |                     current_part = event
373 |                     container = []
374 |                     _write = container.append
375 |                 elif isinstance(event, File):
376 |                     current_part = event
377 |                     container = self.start_file_streaming(event, content_length)
378 |                     _write = container.write
379 |                 elif isinstance(event, Data):
380 |                     _write(event.data)
381 |                     if not event.more_data:
382 |                         if isinstance(current_part, Field):
383 |                             value = b"".join(container).decode(
384 |                                 self.get_part_charset(current_part.headers), "replace"
385 |                             )
386 |                             fields.append((current_part.name, value))
387 |                         else:
388 |                             container = t.cast(t.IO[bytes], container)
389 |                             container.seek(0)
390 |                             files.append(
391 |                                 (
392 |                                     current_part.name,
393 |                                     FileStorage(
394 |                                         container,
395 |                                         current_part.filename,
396 |                                         current_part.name,
397 |                                         headers=current_part.headers,
398 |                                     ),
399 |                                 )
400 |                             )
401 | 
402 |                 event = parser.next_event()
403 | 
404 |         return self.cls(fields), self.cls(files)
405 | 
406 | 
407 | def _chunk_iter(read: t.Callable[[int], bytes], size: int) -> t.Iterator[bytes | None]:
408 |     """Read data in chunks for multipart/form-data parsing. Stop if no data is read.
409 |     Yield ``None`` at the end to signal end of parsing.
410 |     """
411 |     while True:
412 |         data = read(size)
413 | 
414 |         if not data:
415 |             break
416 | 
417 |         yield data
418 | 
419 |     yield None
420 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/bs4/tests/test_dammit.py:
--------------------------------------------------------------------------------

```python
  1 | # encoding: utf-8
  2 | import pytest
  3 | import logging
  4 | import bs4
  5 | from bs4 import BeautifulSoup
  6 | from bs4.dammit import (
  7 |     EntitySubstitution,
  8 |     EncodingDetector,
  9 |     UnicodeDammit,
 10 | )
 11 | 
 12 | class TestUnicodeDammit(object):
 13 |     """Standalone tests of UnicodeDammit."""
 14 | 
 15 |     def test_unicode_input(self):
 16 |         markup = "I'm already Unicode! \N{SNOWMAN}"
 17 |         dammit = UnicodeDammit(markup)
 18 |         assert dammit.unicode_markup == markup
 19 | 
 20 |     @pytest.mark.parametrize(
 21 |         "smart_quotes_to,expect_converted",
 22 |         [(None, "\u2018\u2019\u201c\u201d"),
 23 |          ("xml", "‘’“”"),
 24 |          ("html", "‘’“”"),
 25 |          ("ascii", "''" + '""'),
 26 |         ]
 27 |     )
 28 |     def test_smart_quotes_to(self, smart_quotes_to, expect_converted):
 29 |         """Verify the functionality of the smart_quotes_to argument
 30 |         to the UnicodeDammit constructor."""
 31 |         markup = b"<foo>\x91\x92\x93\x94</foo>"
 32 |         converted = UnicodeDammit(
 33 |             markup, known_definite_encodings=["windows-1252"],
 34 |             smart_quotes_to=smart_quotes_to
 35 |         ).unicode_markup
 36 |         assert converted == "<foo>{}</foo>".format(expect_converted)
 37 |         
 38 |     def test_detect_utf8(self):
 39 |         utf8 = b"Sacr\xc3\xa9 bleu! \xe2\x98\x83"
 40 |         dammit = UnicodeDammit(utf8)
 41 |         assert dammit.original_encoding.lower() == 'utf-8'
 42 |         assert dammit.unicode_markup == 'Sacr\xe9 bleu! \N{SNOWMAN}'
 43 | 
 44 |     def test_convert_hebrew(self):
 45 |         hebrew = b"\xed\xe5\xec\xf9"
 46 |         dammit = UnicodeDammit(hebrew, ["iso-8859-8"])
 47 |         assert dammit.original_encoding.lower() == 'iso-8859-8'
 48 |         assert dammit.unicode_markup == '\u05dd\u05d5\u05dc\u05e9'
 49 | 
 50 |     def test_dont_see_smart_quotes_where_there_are_none(self):
 51 |         utf_8 = b"\343\202\261\343\203\274\343\202\277\343\202\244 Watch"
 52 |         dammit = UnicodeDammit(utf_8)
 53 |         assert dammit.original_encoding.lower() == 'utf-8'
 54 |         assert dammit.unicode_markup.encode("utf-8") == utf_8
 55 | 
 56 |     def test_ignore_inappropriate_codecs(self):
 57 |         utf8_data = "Räksmörgås".encode("utf-8")
 58 |         dammit = UnicodeDammit(utf8_data, ["iso-8859-8"])
 59 |         assert dammit.original_encoding.lower() == 'utf-8'
 60 | 
 61 |     def test_ignore_invalid_codecs(self):
 62 |         utf8_data = "Räksmörgås".encode("utf-8")
 63 |         for bad_encoding in ['.utf8', '...', 'utF---16.!']:
 64 |             dammit = UnicodeDammit(utf8_data, [bad_encoding])
 65 |             assert dammit.original_encoding.lower() == 'utf-8'
 66 | 
 67 |     def test_exclude_encodings(self):
 68 |         # This is UTF-8.
 69 |         utf8_data = "Räksmörgås".encode("utf-8")
 70 | 
 71 |         # But if we exclude UTF-8 from consideration, the guess is
 72 |         # Windows-1252.
 73 |         dammit = UnicodeDammit(utf8_data, exclude_encodings=["utf-8"])
 74 |         assert dammit.original_encoding.lower() == 'windows-1252'
 75 | 
 76 |         # And if we exclude that, there is no valid guess at all.
 77 |         dammit = UnicodeDammit(
 78 |             utf8_data, exclude_encodings=["utf-8", "windows-1252"])
 79 |         assert dammit.original_encoding == None
 80 | 
 81 | class TestEncodingDetector(object):
 82 |         
 83 |     def test_encoding_detector_replaces_junk_in_encoding_name_with_replacement_character(self):
 84 |         detected = EncodingDetector(
 85 |             b'<?xml version="1.0" encoding="UTF-\xdb" ?>')
 86 |         encodings = list(detected.encodings)
 87 |         assert 'utf-\N{REPLACEMENT CHARACTER}' in encodings
 88 | 
 89 |     def test_detect_html5_style_meta_tag(self):
 90 | 
 91 |         for data in (
 92 |             b'<html><meta charset="euc-jp" /></html>',
 93 |             b"<html><meta charset='euc-jp' /></html>",
 94 |             b"<html><meta charset=euc-jp /></html>",
 95 |             b"<html><meta charset=euc-jp/></html>"):
 96 |             dammit = UnicodeDammit(data, is_html=True)
 97 |             assert "euc-jp" == dammit.original_encoding
 98 | 
 99 |     def test_last_ditch_entity_replacement(self):
100 |         # This is a UTF-8 document that contains bytestrings
101 |         # completely incompatible with UTF-8 (ie. encoded with some other
102 |         # encoding).
103 |         #
104 |         # Since there is no consistent encoding for the document,
105 |         # Unicode, Dammit will eventually encode the document as UTF-8
106 |         # and encode the incompatible characters as REPLACEMENT
107 |         # CHARACTER.
108 |         #
109 |         # If chardet is installed, it will detect that the document
110 |         # can be converted into ISO-8859-1 without errors. This happens
111 |         # to be the wrong encoding, but it is a consistent encoding, so the
112 |         # code we're testing here won't run.
113 |         #
114 |         # So we temporarily disable chardet if it's present.
115 |         doc = b"""\357\273\277<?xml version="1.0" encoding="UTF-8"?>
116 | <html><b>\330\250\330\252\330\261</b>
117 | <i>\310\322\321\220\312\321\355\344</i></html>"""
118 |         chardet = bs4.dammit.chardet_dammit
119 |         logging.disable(logging.WARNING)
120 |         try:
121 |             def noop(str):
122 |                 return None
123 |             bs4.dammit.chardet_dammit = noop
124 |             dammit = UnicodeDammit(doc)
125 |             assert True == dammit.contains_replacement_characters
126 |             assert "\ufffd" in dammit.unicode_markup
127 | 
128 |             soup = BeautifulSoup(doc, "html.parser")
129 |             assert soup.contains_replacement_characters
130 |         finally:
131 |             logging.disable(logging.NOTSET)
132 |             bs4.dammit.chardet_dammit = chardet
133 | 
134 |     def test_byte_order_mark_removed(self):
135 |         # A document written in UTF-16LE will have its byte order marker stripped.
136 |         data = b'\xff\xfe<\x00a\x00>\x00\xe1\x00\xe9\x00<\x00/\x00a\x00>\x00'
137 |         dammit = UnicodeDammit(data)
138 |         assert "<a>áé</a>" == dammit.unicode_markup
139 |         assert "utf-16le" == dammit.original_encoding
140 |        
141 |     def test_known_definite_versus_user_encodings(self):
142 |         # The known_definite_encodings are used before sniffing the
143 |         # byte-order mark; the user_encodings are used afterwards.
144 | 
145 |         # Here's a document in UTF-16LE.
146 |         data = b'\xff\xfe<\x00a\x00>\x00\xe1\x00\xe9\x00<\x00/\x00a\x00>\x00'
147 |         dammit = UnicodeDammit(data)
148 | 
149 |         # We can process it as UTF-16 by passing it in as a known
150 |         # definite encoding.
151 |         before = UnicodeDammit(data, known_definite_encodings=["utf-16"])
152 |         assert "utf-16" == before.original_encoding
153 |         
154 |         # If we pass UTF-18 as a user encoding, it's not even
155 |         # tried--the encoding sniffed from the byte-order mark takes
156 |         # precedence.
157 |         after = UnicodeDammit(data, user_encodings=["utf-8"])
158 |         assert "utf-16le" == after.original_encoding
159 |         assert ["utf-16le"] == [x[0] for x in dammit.tried_encodings]
160 |         
161 |         # Here's a document in ISO-8859-8.
162 |         hebrew = b"\xed\xe5\xec\xf9"
163 |         dammit = UnicodeDammit(hebrew, known_definite_encodings=["utf-8"],
164 |                                user_encodings=["iso-8859-8"])
165 |         
166 |         # The known_definite_encodings don't work, BOM sniffing does
167 |         # nothing (it only works for a few UTF encodings), but one of
168 |         # the user_encodings does work.
169 |         assert "iso-8859-8" == dammit.original_encoding
170 |         assert ["utf-8", "iso-8859-8"] == [x[0] for x in dammit.tried_encodings]
171 |         
172 |     def test_deprecated_override_encodings(self):
173 |         # override_encodings is a deprecated alias for
174 |         # known_definite_encodings.
175 |         hebrew = b"\xed\xe5\xec\xf9"
176 |         dammit = UnicodeDammit(
177 |             hebrew,
178 |             known_definite_encodings=["shift-jis"],
179 |             override_encodings=["utf-8"],
180 |             user_encodings=["iso-8859-8"],
181 |         )
182 |         assert "iso-8859-8" == dammit.original_encoding
183 | 
184 |         # known_definite_encodings and override_encodings were tried
185 |         # before user_encodings.
186 |         assert ["shift-jis", "utf-8", "iso-8859-8"] == (
187 |             [x[0] for x in dammit.tried_encodings]
188 |         )
189 | 
190 |     def test_detwingle(self):
191 |         # Here's a UTF8 document.
192 |         utf8 = ("\N{SNOWMAN}" * 3).encode("utf8")
193 | 
194 |         # Here's a Windows-1252 document.
195 |         windows_1252 = (
196 |             "\N{LEFT DOUBLE QUOTATION MARK}Hi, I like Windows!"
197 |             "\N{RIGHT DOUBLE QUOTATION MARK}").encode("windows_1252")
198 | 
199 |         # Through some unholy alchemy, they've been stuck together.
200 |         doc = utf8 + windows_1252 + utf8
201 | 
202 |         # The document can't be turned into UTF-8:
203 |         with pytest.raises(UnicodeDecodeError):
204 |             doc.decode("utf8")
205 | 
206 |         # Unicode, Dammit thinks the whole document is Windows-1252,
207 |         # and decodes it into "☃☃☃“Hi, I like Windows!”☃☃☃"
208 | 
209 |         # But if we run it through fix_embedded_windows_1252, it's fixed:
210 |         fixed = UnicodeDammit.detwingle(doc)
211 |         assert "☃☃☃“Hi, I like Windows!”☃☃☃" == fixed.decode("utf8")
212 | 
213 |     def test_detwingle_ignores_multibyte_characters(self):
214 |         # Each of these characters has a UTF-8 representation ending
215 |         # in \x93. \x93 is a smart quote if interpreted as
216 |         # Windows-1252. But our code knows to skip over multibyte
217 |         # UTF-8 characters, so they'll survive the process unscathed.
218 |         for tricky_unicode_char in (
219 |             "\N{LATIN SMALL LIGATURE OE}", # 2-byte char '\xc5\x93'
220 |             "\N{LATIN SUBSCRIPT SMALL LETTER X}", # 3-byte char '\xe2\x82\x93'
221 |             "\xf0\x90\x90\x93", # This is a CJK character, not sure which one.
222 |             ):
223 |             input = tricky_unicode_char.encode("utf8")
224 |             assert input.endswith(b'\x93')
225 |             output = UnicodeDammit.detwingle(input)
226 |             assert output == input
227 | 
228 |     def test_find_declared_encoding(self):
229 |         # Test our ability to find a declared encoding inside an
230 |         # XML or HTML document.
231 |         #
232 |         # Even if the document comes in as Unicode, it may be
233 |         # interesting to know what encoding was claimed
234 |         # originally.
235 | 
236 |         html_unicode = '<html><head><meta charset="utf-8"></head></html>'
237 |         html_bytes = html_unicode.encode("ascii")
238 | 
239 |         xml_unicode= '<?xml version="1.0" encoding="ISO-8859-1" ?>'
240 |         xml_bytes = xml_unicode.encode("ascii")
241 | 
242 |         m = EncodingDetector.find_declared_encoding
243 |         assert m(html_unicode, is_html=False) is None
244 |         assert "utf-8" == m(html_unicode, is_html=True)
245 |         assert "utf-8" == m(html_bytes, is_html=True)
246 | 
247 |         assert "iso-8859-1" == m(xml_unicode)
248 |         assert "iso-8859-1" == m(xml_bytes)
249 | 
250 |         # Normally, only the first few kilobytes of a document are checked for
251 |         # an encoding.
252 |         spacer = b' ' * 5000
253 |         assert m(spacer + html_bytes) is None
254 |         assert m(spacer + xml_bytes) is None
255 | 
256 |         # But you can tell find_declared_encoding to search an entire
257 |         # HTML document.
258 |         assert (
259 |             m(spacer + html_bytes, is_html=True, search_entire_document=True)
260 |             == "utf-8"
261 |         )
262 | 
263 |         # The XML encoding declaration has to be the very first thing
264 |         # in the document. We'll allow whitespace before the document
265 |         # starts, but nothing else.
266 |         assert m(xml_bytes, search_entire_document=True) == "iso-8859-1"
267 |         assert m(b' ' + xml_bytes, search_entire_document=True) == "iso-8859-1"
268 |         assert m(b'a' + xml_bytes, search_entire_document=True) is None
269 | 
270 | 
271 | class TestEntitySubstitution(object):
272 |     """Standalone tests of the EntitySubstitution class."""
273 |     def setup_method(self):
274 |         self.sub = EntitySubstitution
275 | 
276 | 
277 |     @pytest.mark.parametrize(
278 |         "original,substituted",
279 |         [
280 |             # Basic case. Unicode characters corresponding to named
281 |             # HTML entites are substituted; others are not.
282 |             ("foo\u2200\N{SNOWMAN}\u00f5bar",
283 |              "foo&forall;\N{SNOWMAN}&otilde;bar"),
284 | 
285 |             # MS smart quotes are a common source of frustration, so we
286 |             # give them a special test.
287 |             ('‘’foo“”', "&lsquo;&rsquo;foo&ldquo;&rdquo;"),           
288 |         ]
289 |     )
290 |     def test_substitute_html(self, original, substituted):
291 |         assert self.sub.substitute_html(original) == substituted
292 |         
293 |     def test_html5_entity(self):
294 |         for entity, u in (
295 |             # A few spot checks of our ability to recognize
296 |             # special character sequences and convert them
297 |             # to named entities.
298 |             ('&models;', '\u22a7'),
299 |             ('&Nfr;', '\U0001d511'),
300 |             ('&ngeqq;', '\u2267\u0338'),
301 |             ('&not;', '\xac'),
302 |             ('&Not;', '\u2aec'),
303 |                 
304 |             # We _could_ convert | to &verbarr;, but we don't, because
305 |             # | is an ASCII character.
306 |             ('|' '|'),
307 | 
308 |             # Similarly for the fj ligature, which we could convert to
309 |             # &fjlig;, but we don't.
310 |             ("fj", "fj"),
311 | 
312 |             # We do convert _these_ ASCII characters to HTML entities,
313 |             # because that's required to generate valid HTML.
314 |             ('&gt;', '>'),
315 |             ('&lt;', '<'),
316 |             ('&amp;', '&'),
317 |         ):
318 |             template = '3 %s 4'
319 |             raw = template % u
320 |             with_entities = template % entity
321 |             assert self.sub.substitute_html(raw) == with_entities
322 |             
323 |     def test_html5_entity_with_variation_selector(self):
324 |         # Some HTML5 entities correspond either to a single-character
325 |         # Unicode sequence _or_ to the same character plus U+FE00,
326 |         # VARIATION SELECTOR 1. We can handle this.
327 |         data = "fjords \u2294 penguins"
328 |         markup = "fjords &sqcup; penguins"
329 |         assert self.sub.substitute_html(data) == markup
330 | 
331 |         data = "fjords \u2294\ufe00 penguins"
332 |         markup = "fjords &sqcups; penguins"
333 |         assert self.sub.substitute_html(data) == markup
334 |         
335 |     def test_xml_converstion_includes_no_quotes_if_make_quoted_attribute_is_false(self):
336 |         s = 'Welcome to "my bar"'
337 |         assert self.sub.substitute_xml(s, False) == s
338 | 
339 |     def test_xml_attribute_quoting_normally_uses_double_quotes(self):
340 |         assert self.sub.substitute_xml("Welcome", True) == '"Welcome"'
341 |         assert self.sub.substitute_xml("Bob's Bar", True) == '"Bob\'s Bar"'
342 | 
343 |     def test_xml_attribute_quoting_uses_single_quotes_when_value_contains_double_quotes(self):
344 |         s = 'Welcome to "my bar"'
345 |         assert self.sub.substitute_xml(s, True) == "'Welcome to \"my bar\"'"
346 | 
347 |     def test_xml_attribute_quoting_escapes_single_quotes_when_value_contains_both_single_and_double_quotes(self):
348 |         s = 'Welcome to "Bob\'s Bar"'
349 |         assert self.sub.substitute_xml(s, True) == '"Welcome to &quot;Bob\'s Bar&quot;"'
350 | 
351 |     def test_xml_quotes_arent_escaped_when_value_is_not_being_quoted(self):
352 |         quoted = 'Welcome to "Bob\'s Bar"'
353 |         assert self.sub.substitute_xml(quoted) == quoted
354 | 
355 |     def test_xml_quoting_handles_angle_brackets(self):
356 |         assert self.sub.substitute_xml("foo<bar>") == "foo&lt;bar&gt;"
357 | 
358 |     def test_xml_quoting_handles_ampersands(self):
359 |         assert self.sub.substitute_xml("AT&T") == "AT&amp;T"
360 | 
361 |     def test_xml_quoting_including_ampersands_when_they_are_part_of_an_entity(self):
362 |         assert self.sub.substitute_xml("&Aacute;T&T") == "&amp;Aacute;T&amp;T"
363 | 
364 |     def test_xml_quoting_ignoring_ampersands_when_they_are_part_of_an_entity(self):
365 |         assert self.sub.substitute_xml_containing_entities("&Aacute;T&T") == "&Aacute;T&amp;T"
366 |        
367 |     def test_quotes_not_html_substituted(self):
368 |         """There's no need to do this except inside attribute values."""
369 |         text = 'Bob\'s "bar"'
370 |         assert self.sub.substitute_html(text) == text
371 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/itsdangerous/serializer.py:
--------------------------------------------------------------------------------

```python
  1 | from __future__ import annotations
  2 | 
  3 | import collections.abc as cabc
  4 | import json
  5 | import typing as t
  6 | 
  7 | from .encoding import want_bytes
  8 | from .exc import BadPayload
  9 | from .exc import BadSignature
 10 | from .signer import _make_keys_list
 11 | from .signer import Signer
 12 | 
 13 | if t.TYPE_CHECKING:
 14 |     import typing_extensions as te
 15 | 
 16 |     # This should be either be str or bytes. To avoid having to specify the
 17 |     # bound type, it falls back to a union if structural matching fails.
 18 |     _TSerialized = te.TypeVar(
 19 |         "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes]
 20 |     )
 21 | else:
 22 |     # Still available at runtime on Python < 3.13, but without the default.
 23 |     _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes])
 24 | 
 25 | 
 26 | class _PDataSerializer(t.Protocol[_TSerialized]):
 27 |     def loads(self, payload: _TSerialized, /) -> t.Any: ...
 28 |     # A signature with additional arguments is not handled correctly by type
 29 |     # checkers right now, so an overload is used below for serializers that
 30 |     # don't match this strict protocol.
 31 |     def dumps(self, obj: t.Any, /) -> _TSerialized: ...
 32 | 
 33 | 
 34 | # Use TypeIs once it's available in typing_extensions or 3.13.
 35 | def is_text_serializer(
 36 |     serializer: _PDataSerializer[t.Any],
 37 | ) -> te.TypeGuard[_PDataSerializer[str]]:
 38 |     """Checks whether a serializer generates text or binary."""
 39 |     return isinstance(serializer.dumps({}), str)
 40 | 
 41 | 
 42 | class Serializer(t.Generic[_TSerialized]):
 43 |     """A serializer wraps a :class:`~itsdangerous.signer.Signer` to
 44 |     enable serializing and securely signing data other than bytes. It
 45 |     can unsign to verify that the data hasn't been changed.
 46 | 
 47 |     The serializer provides :meth:`dumps` and :meth:`loads`, similar to
 48 |     :mod:`json`, and by default uses :mod:`json` internally to serialize
 49 |     the data to bytes.
 50 | 
 51 |     The secret key should be a random string of ``bytes`` and should not
 52 |     be saved to code or version control. Different salts should be used
 53 |     to distinguish signing in different contexts. See :doc:`/concepts`
 54 |     for information about the security of the secret key and salt.
 55 | 
 56 |     :param secret_key: The secret key to sign and verify with. Can be a
 57 |         list of keys, oldest to newest, to support key rotation.
 58 |     :param salt: Extra key to combine with ``secret_key`` to distinguish
 59 |         signatures in different contexts.
 60 |     :param serializer: An object that provides ``dumps`` and ``loads``
 61 |         methods for serializing data to a string. Defaults to
 62 |         :attr:`default_serializer`, which defaults to :mod:`json`.
 63 |     :param serializer_kwargs: Keyword arguments to pass when calling
 64 |         ``serializer.dumps``.
 65 |     :param signer: A ``Signer`` class to instantiate when signing data.
 66 |         Defaults to :attr:`default_signer`, which defaults to
 67 |         :class:`~itsdangerous.signer.Signer`.
 68 |     :param signer_kwargs: Keyword arguments to pass when instantiating
 69 |         the ``Signer`` class.
 70 |     :param fallback_signers: List of signer parameters to try when
 71 |         unsigning with the default signer fails. Each item can be a dict
 72 |         of ``signer_kwargs``, a ``Signer`` class, or a tuple of
 73 |         ``(signer, signer_kwargs)``. Defaults to
 74 |         :attr:`default_fallback_signers`.
 75 | 
 76 |     .. versionchanged:: 2.0
 77 |         Added support for key rotation by passing a list to
 78 |         ``secret_key``.
 79 | 
 80 |     .. versionchanged:: 2.0
 81 |         Removed the default SHA-512 fallback signer from
 82 |         ``default_fallback_signers``.
 83 | 
 84 |     .. versionchanged:: 1.1
 85 |         Added support for ``fallback_signers`` and configured a default
 86 |         SHA-512 fallback. This fallback is for users who used the yanked
 87 |         1.0.0 release which defaulted to SHA-512.
 88 | 
 89 |     .. versionchanged:: 0.14
 90 |         The ``signer`` and ``signer_kwargs`` parameters were added to
 91 |         the constructor.
 92 |     """
 93 | 
 94 |     #: The default serialization module to use to serialize data to a
 95 |     #: string internally. The default is :mod:`json`, but can be changed
 96 |     #: to any object that provides ``dumps`` and ``loads`` methods.
 97 |     default_serializer: _PDataSerializer[t.Any] = json
 98 | 
 99 |     #: The default ``Signer`` class to instantiate when signing data.
100 |     #: The default is :class:`itsdangerous.signer.Signer`.
101 |     default_signer: type[Signer] = Signer
102 | 
103 |     #: The default fallback signers to try when unsigning fails.
104 |     default_fallback_signers: list[
105 |         dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
106 |     ] = []
107 | 
108 |     # Serializer[str] if no data serializer is provided, or if it returns str.
109 |     @t.overload
110 |     def __init__(
111 |         self: Serializer[str],
112 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
113 |         salt: str | bytes | None = b"itsdangerous",
114 |         serializer: None | _PDataSerializer[str] = None,
115 |         serializer_kwargs: dict[str, t.Any] | None = None,
116 |         signer: type[Signer] | None = None,
117 |         signer_kwargs: dict[str, t.Any] | None = None,
118 |         fallback_signers: list[
119 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
120 |         ]
121 |         | None = None,
122 |     ): ...
123 | 
124 |     # Serializer[bytes] with a bytes data serializer positional argument.
125 |     @t.overload
126 |     def __init__(
127 |         self: Serializer[bytes],
128 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
129 |         salt: str | bytes | None,
130 |         serializer: _PDataSerializer[bytes],
131 |         serializer_kwargs: dict[str, t.Any] | None = None,
132 |         signer: type[Signer] | None = None,
133 |         signer_kwargs: dict[str, t.Any] | None = None,
134 |         fallback_signers: list[
135 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
136 |         ]
137 |         | None = None,
138 |     ): ...
139 | 
140 |     # Serializer[bytes] with a bytes data serializer keyword argument.
141 |     @t.overload
142 |     def __init__(
143 |         self: Serializer[bytes],
144 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
145 |         salt: str | bytes | None = b"itsdangerous",
146 |         *,
147 |         serializer: _PDataSerializer[bytes],
148 |         serializer_kwargs: dict[str, t.Any] | None = None,
149 |         signer: type[Signer] | None = None,
150 |         signer_kwargs: dict[str, t.Any] | None = None,
151 |         fallback_signers: list[
152 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
153 |         ]
154 |         | None = None,
155 |     ): ...
156 | 
157 |     # Fall back with a positional argument. If the strict signature of
158 |     # _PDataSerializer doesn't match, fall back to a union, requiring the user
159 |     # to specify the type.
160 |     @t.overload
161 |     def __init__(
162 |         self,
163 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
164 |         salt: str | bytes | None,
165 |         serializer: t.Any,
166 |         serializer_kwargs: dict[str, t.Any] | None = None,
167 |         signer: type[Signer] | None = None,
168 |         signer_kwargs: dict[str, t.Any] | None = None,
169 |         fallback_signers: list[
170 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
171 |         ]
172 |         | None = None,
173 |     ): ...
174 | 
175 |     # Fall back with a keyword argument.
176 |     @t.overload
177 |     def __init__(
178 |         self,
179 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
180 |         salt: str | bytes | None = b"itsdangerous",
181 |         *,
182 |         serializer: t.Any,
183 |         serializer_kwargs: dict[str, t.Any] | None = None,
184 |         signer: type[Signer] | None = None,
185 |         signer_kwargs: dict[str, t.Any] | None = None,
186 |         fallback_signers: list[
187 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
188 |         ]
189 |         | None = None,
190 |     ): ...
191 | 
192 |     def __init__(
193 |         self,
194 |         secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes],
195 |         salt: str | bytes | None = b"itsdangerous",
196 |         serializer: t.Any | None = None,
197 |         serializer_kwargs: dict[str, t.Any] | None = None,
198 |         signer: type[Signer] | None = None,
199 |         signer_kwargs: dict[str, t.Any] | None = None,
200 |         fallback_signers: list[
201 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
202 |         ]
203 |         | None = None,
204 |     ):
205 |         #: The list of secret keys to try for verifying signatures, from
206 |         #: oldest to newest. The newest (last) key is used for signing.
207 |         #:
208 |         #: This allows a key rotation system to keep a list of allowed
209 |         #: keys and remove expired ones.
210 |         self.secret_keys: list[bytes] = _make_keys_list(secret_key)
211 | 
212 |         if salt is not None:
213 |             salt = want_bytes(salt)
214 |             # if salt is None then the signer's default is used
215 | 
216 |         self.salt = salt
217 | 
218 |         if serializer is None:
219 |             serializer = self.default_serializer
220 | 
221 |         self.serializer: _PDataSerializer[_TSerialized] = serializer
222 |         self.is_text_serializer: bool = is_text_serializer(serializer)
223 | 
224 |         if signer is None:
225 |             signer = self.default_signer
226 | 
227 |         self.signer: type[Signer] = signer
228 |         self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {}
229 | 
230 |         if fallback_signers is None:
231 |             fallback_signers = list(self.default_fallback_signers)
232 | 
233 |         self.fallback_signers: list[
234 |             dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer]
235 |         ] = fallback_signers
236 |         self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {}
237 | 
238 |     @property
239 |     def secret_key(self) -> bytes:
240 |         """The newest (last) entry in the :attr:`secret_keys` list. This
241 |         is for compatibility from before key rotation support was added.
242 |         """
243 |         return self.secret_keys[-1]
244 | 
245 |     def load_payload(
246 |         self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None
247 |     ) -> t.Any:
248 |         """Loads the encoded object. This function raises
249 |         :class:`.BadPayload` if the payload is not valid. The
250 |         ``serializer`` parameter can be used to override the serializer
251 |         stored on the class. The encoded ``payload`` should always be
252 |         bytes.
253 |         """
254 |         if serializer is None:
255 |             use_serializer = self.serializer
256 |             is_text = self.is_text_serializer
257 |         else:
258 |             use_serializer = serializer
259 |             is_text = is_text_serializer(serializer)
260 | 
261 |         try:
262 |             if is_text:
263 |                 return use_serializer.loads(payload.decode("utf-8"))  # type: ignore[arg-type]
264 | 
265 |             return use_serializer.loads(payload)  # type: ignore[arg-type]
266 |         except Exception as e:
267 |             raise BadPayload(
268 |                 "Could not load the payload because an exception"
269 |                 " occurred on unserializing the data.",
270 |                 original_error=e,
271 |             ) from e
272 | 
273 |     def dump_payload(self, obj: t.Any) -> bytes:
274 |         """Dumps the encoded object. The return value is always bytes.
275 |         If the internal serializer returns text, the value will be
276 |         encoded as UTF-8.
277 |         """
278 |         return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs))
279 | 
280 |     def make_signer(self, salt: str | bytes | None = None) -> Signer:
281 |         """Creates a new instance of the signer to be used. The default
282 |         implementation uses the :class:`.Signer` base class.
283 |         """
284 |         if salt is None:
285 |             salt = self.salt
286 | 
287 |         return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs)
288 | 
289 |     def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]:
290 |         """Iterates over all signers to be tried for unsigning. Starts
291 |         with the configured signer, then constructs each signer
292 |         specified in ``fallback_signers``.
293 |         """
294 |         if salt is None:
295 |             salt = self.salt
296 | 
297 |         yield self.make_signer(salt)
298 | 
299 |         for fallback in self.fallback_signers:
300 |             if isinstance(fallback, dict):
301 |                 kwargs = fallback
302 |                 fallback = self.signer
303 |             elif isinstance(fallback, tuple):
304 |                 fallback, kwargs = fallback
305 |             else:
306 |                 kwargs = self.signer_kwargs
307 | 
308 |             for secret_key in self.secret_keys:
309 |                 yield fallback(secret_key, salt=salt, **kwargs)
310 | 
311 |     def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized:
312 |         """Returns a signed string serialized with the internal
313 |         serializer. The return value can be either a byte or unicode
314 |         string depending on the format of the internal serializer.
315 |         """
316 |         payload = want_bytes(self.dump_payload(obj))
317 |         rv = self.make_signer(salt).sign(payload)
318 | 
319 |         if self.is_text_serializer:
320 |             return rv.decode("utf-8")  # type: ignore[return-value]
321 | 
322 |         return rv  # type: ignore[return-value]
323 | 
324 |     def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None:
325 |         """Like :meth:`dumps` but dumps into a file. The file handle has
326 |         to be compatible with what the internal serializer expects.
327 |         """
328 |         f.write(self.dumps(obj, salt))
329 | 
330 |     def loads(
331 |         self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any
332 |     ) -> t.Any:
333 |         """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the
334 |         signature validation fails.
335 |         """
336 |         s = want_bytes(s)
337 |         last_exception = None
338 | 
339 |         for signer in self.iter_unsigners(salt):
340 |             try:
341 |                 return self.load_payload(signer.unsign(s))
342 |             except BadSignature as err:
343 |                 last_exception = err
344 | 
345 |         raise t.cast(BadSignature, last_exception)
346 | 
347 |     def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any:
348 |         """Like :meth:`loads` but loads from a file."""
349 |         return self.loads(f.read(), salt)
350 | 
351 |     def loads_unsafe(
352 |         self, s: str | bytes, salt: str | bytes | None = None
353 |     ) -> tuple[bool, t.Any]:
354 |         """Like :meth:`loads` but without verifying the signature. This
355 |         is potentially very dangerous to use depending on how your
356 |         serializer works. The return value is ``(signature_valid,
357 |         payload)`` instead of just the payload. The first item will be a
358 |         boolean that indicates if the signature is valid. This function
359 |         never fails.
360 | 
361 |         Use it for debugging only and if you know that your serializer
362 |         module is not exploitable (for example, do not use it with a
363 |         pickle serializer).
364 | 
365 |         .. versionadded:: 0.15
366 |         """
367 |         return self._loads_unsafe_impl(s, salt)
368 | 
369 |     def _loads_unsafe_impl(
370 |         self,
371 |         s: str | bytes,
372 |         salt: str | bytes | None,
373 |         load_kwargs: dict[str, t.Any] | None = None,
374 |         load_payload_kwargs: dict[str, t.Any] | None = None,
375 |     ) -> tuple[bool, t.Any]:
376 |         """Low level helper function to implement :meth:`loads_unsafe`
377 |         in serializer subclasses.
378 |         """
379 |         if load_kwargs is None:
380 |             load_kwargs = {}
381 | 
382 |         try:
383 |             return True, self.loads(s, salt=salt, **load_kwargs)
384 |         except BadSignature as e:
385 |             if e.payload is None:
386 |                 return False, None
387 | 
388 |             if load_payload_kwargs is None:
389 |                 load_payload_kwargs = {}
390 | 
391 |             try:
392 |                 return (
393 |                     False,
394 |                     self.load_payload(e.payload, **load_payload_kwargs),
395 |                 )
396 |             except BadPayload:
397 |                 return False, None
398 | 
399 |     def load_unsafe(
400 |         self, f: t.IO[t.Any], salt: str | bytes | None = None
401 |     ) -> tuple[bool, t.Any]:
402 |         """Like :meth:`loads_unsafe` but loads from a file.
403 | 
404 |         .. versionadded:: 0.15
405 |         """
406 |         return self.loads_unsafe(f.read(), salt=salt)
407 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/click/testing.py:
--------------------------------------------------------------------------------

```python
  1 | import contextlib
  2 | import io
  3 | import os
  4 | import shlex
  5 | import shutil
  6 | import sys
  7 | import tempfile
  8 | import typing as t
  9 | from types import TracebackType
 10 | 
 11 | from . import formatting
 12 | from . import termui
 13 | from . import utils
 14 | from ._compat import _find_binary_reader
 15 | 
 16 | if t.TYPE_CHECKING:
 17 |     from .core import BaseCommand
 18 | 
 19 | 
 20 | class EchoingStdin:
 21 |     def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None:
 22 |         self._input = input
 23 |         self._output = output
 24 |         self._paused = False
 25 | 
 26 |     def __getattr__(self, x: str) -> t.Any:
 27 |         return getattr(self._input, x)
 28 | 
 29 |     def _echo(self, rv: bytes) -> bytes:
 30 |         if not self._paused:
 31 |             self._output.write(rv)
 32 | 
 33 |         return rv
 34 | 
 35 |     def read(self, n: int = -1) -> bytes:
 36 |         return self._echo(self._input.read(n))
 37 | 
 38 |     def read1(self, n: int = -1) -> bytes:
 39 |         return self._echo(self._input.read1(n))  # type: ignore
 40 | 
 41 |     def readline(self, n: int = -1) -> bytes:
 42 |         return self._echo(self._input.readline(n))
 43 | 
 44 |     def readlines(self) -> t.List[bytes]:
 45 |         return [self._echo(x) for x in self._input.readlines()]
 46 | 
 47 |     def __iter__(self) -> t.Iterator[bytes]:
 48 |         return iter(self._echo(x) for x in self._input)
 49 | 
 50 |     def __repr__(self) -> str:
 51 |         return repr(self._input)
 52 | 
 53 | 
 54 | @contextlib.contextmanager
 55 | def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]:
 56 |     if stream is None:
 57 |         yield
 58 |     else:
 59 |         stream._paused = True
 60 |         yield
 61 |         stream._paused = False
 62 | 
 63 | 
 64 | class _NamedTextIOWrapper(io.TextIOWrapper):
 65 |     def __init__(
 66 |         self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any
 67 |     ) -> None:
 68 |         super().__init__(buffer, **kwargs)
 69 |         self._name = name
 70 |         self._mode = mode
 71 | 
 72 |     @property
 73 |     def name(self) -> str:
 74 |         return self._name
 75 | 
 76 |     @property
 77 |     def mode(self) -> str:
 78 |         return self._mode
 79 | 
 80 | 
 81 | def make_input_stream(
 82 |     input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str
 83 | ) -> t.BinaryIO:
 84 |     # Is already an input stream.
 85 |     if hasattr(input, "read"):
 86 |         rv = _find_binary_reader(t.cast(t.IO[t.Any], input))
 87 | 
 88 |         if rv is not None:
 89 |             return rv
 90 | 
 91 |         raise TypeError("Could not find binary reader for input stream.")
 92 | 
 93 |     if input is None:
 94 |         input = b""
 95 |     elif isinstance(input, str):
 96 |         input = input.encode(charset)
 97 | 
 98 |     return io.BytesIO(input)
 99 | 
100 | 
101 | class Result:
102 |     """Holds the captured result of an invoked CLI script."""
103 | 
104 |     def __init__(
105 |         self,
106 |         runner: "CliRunner",
107 |         stdout_bytes: bytes,
108 |         stderr_bytes: t.Optional[bytes],
109 |         return_value: t.Any,
110 |         exit_code: int,
111 |         exception: t.Optional[BaseException],
112 |         exc_info: t.Optional[
113 |             t.Tuple[t.Type[BaseException], BaseException, TracebackType]
114 |         ] = None,
115 |     ):
116 |         #: The runner that created the result
117 |         self.runner = runner
118 |         #: The standard output as bytes.
119 |         self.stdout_bytes = stdout_bytes
120 |         #: The standard error as bytes, or None if not available
121 |         self.stderr_bytes = stderr_bytes
122 |         #: The value returned from the invoked command.
123 |         #:
124 |         #: .. versionadded:: 8.0
125 |         self.return_value = return_value
126 |         #: The exit code as integer.
127 |         self.exit_code = exit_code
128 |         #: The exception that happened if one did.
129 |         self.exception = exception
130 |         #: The traceback
131 |         self.exc_info = exc_info
132 | 
133 |     @property
134 |     def output(self) -> str:
135 |         """The (standard) output as unicode string."""
136 |         return self.stdout
137 | 
138 |     @property
139 |     def stdout(self) -> str:
140 |         """The standard output as unicode string."""
141 |         return self.stdout_bytes.decode(self.runner.charset, "replace").replace(
142 |             "\r\n", "\n"
143 |         )
144 | 
145 |     @property
146 |     def stderr(self) -> str:
147 |         """The standard error as unicode string."""
148 |         if self.stderr_bytes is None:
149 |             raise ValueError("stderr not separately captured")
150 |         return self.stderr_bytes.decode(self.runner.charset, "replace").replace(
151 |             "\r\n", "\n"
152 |         )
153 | 
154 |     def __repr__(self) -> str:
155 |         exc_str = repr(self.exception) if self.exception else "okay"
156 |         return f"<{type(self).__name__} {exc_str}>"
157 | 
158 | 
159 | class CliRunner:
160 |     """The CLI runner provides functionality to invoke a Click command line
161 |     script for unittesting purposes in a isolated environment.  This only
162 |     works in single-threaded systems without any concurrency as it changes the
163 |     global interpreter state.
164 | 
165 |     :param charset: the character set for the input and output data.
166 |     :param env: a dictionary with environment variables for overriding.
167 |     :param echo_stdin: if this is set to `True`, then reading from stdin writes
168 |                        to stdout.  This is useful for showing examples in
169 |                        some circumstances.  Note that regular prompts
170 |                        will automatically echo the input.
171 |     :param mix_stderr: if this is set to `False`, then stdout and stderr are
172 |                        preserved as independent streams.  This is useful for
173 |                        Unix-philosophy apps that have predictable stdout and
174 |                        noisy stderr, such that each may be measured
175 |                        independently
176 |     """
177 | 
178 |     def __init__(
179 |         self,
180 |         charset: str = "utf-8",
181 |         env: t.Optional[t.Mapping[str, t.Optional[str]]] = None,
182 |         echo_stdin: bool = False,
183 |         mix_stderr: bool = True,
184 |     ) -> None:
185 |         self.charset = charset
186 |         self.env: t.Mapping[str, t.Optional[str]] = env or {}
187 |         self.echo_stdin = echo_stdin
188 |         self.mix_stderr = mix_stderr
189 | 
190 |     def get_default_prog_name(self, cli: "BaseCommand") -> str:
191 |         """Given a command object it will return the default program name
192 |         for it.  The default is the `name` attribute or ``"root"`` if not
193 |         set.
194 |         """
195 |         return cli.name or "root"
196 | 
197 |     def make_env(
198 |         self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None
199 |     ) -> t.Mapping[str, t.Optional[str]]:
200 |         """Returns the environment overrides for invoking a script."""
201 |         rv = dict(self.env)
202 |         if overrides:
203 |             rv.update(overrides)
204 |         return rv
205 | 
206 |     @contextlib.contextmanager
207 |     def isolation(
208 |         self,
209 |         input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None,
210 |         env: t.Optional[t.Mapping[str, t.Optional[str]]] = None,
211 |         color: bool = False,
212 |     ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]:
213 |         """A context manager that sets up the isolation for invoking of a
214 |         command line tool.  This sets up stdin with the given input data
215 |         and `os.environ` with the overrides from the given dictionary.
216 |         This also rebinds some internals in Click to be mocked (like the
217 |         prompt functionality).
218 | 
219 |         This is automatically done in the :meth:`invoke` method.
220 | 
221 |         :param input: the input stream to put into sys.stdin.
222 |         :param env: the environment overrides as dictionary.
223 |         :param color: whether the output should contain color codes. The
224 |                       application can still override this explicitly.
225 | 
226 |         .. versionchanged:: 8.0
227 |             ``stderr`` is opened with ``errors="backslashreplace"``
228 |             instead of the default ``"strict"``.
229 | 
230 |         .. versionchanged:: 4.0
231 |             Added the ``color`` parameter.
232 |         """
233 |         bytes_input = make_input_stream(input, self.charset)
234 |         echo_input = None
235 | 
236 |         old_stdin = sys.stdin
237 |         old_stdout = sys.stdout
238 |         old_stderr = sys.stderr
239 |         old_forced_width = formatting.FORCED_WIDTH
240 |         formatting.FORCED_WIDTH = 80
241 | 
242 |         env = self.make_env(env)
243 | 
244 |         bytes_output = io.BytesIO()
245 | 
246 |         if self.echo_stdin:
247 |             bytes_input = echo_input = t.cast(
248 |                 t.BinaryIO, EchoingStdin(bytes_input, bytes_output)
249 |             )
250 | 
251 |         sys.stdin = text_input = _NamedTextIOWrapper(
252 |             bytes_input, encoding=self.charset, name="<stdin>", mode="r"
253 |         )
254 | 
255 |         if self.echo_stdin:
256 |             # Force unbuffered reads, otherwise TextIOWrapper reads a
257 |             # large chunk which is echoed early.
258 |             text_input._CHUNK_SIZE = 1  # type: ignore
259 | 
260 |         sys.stdout = _NamedTextIOWrapper(
261 |             bytes_output, encoding=self.charset, name="<stdout>", mode="w"
262 |         )
263 | 
264 |         bytes_error = None
265 |         if self.mix_stderr:
266 |             sys.stderr = sys.stdout
267 |         else:
268 |             bytes_error = io.BytesIO()
269 |             sys.stderr = _NamedTextIOWrapper(
270 |                 bytes_error,
271 |                 encoding=self.charset,
272 |                 name="<stderr>",
273 |                 mode="w",
274 |                 errors="backslashreplace",
275 |             )
276 | 
277 |         @_pause_echo(echo_input)  # type: ignore
278 |         def visible_input(prompt: t.Optional[str] = None) -> str:
279 |             sys.stdout.write(prompt or "")
280 |             val = text_input.readline().rstrip("\r\n")
281 |             sys.stdout.write(f"{val}\n")
282 |             sys.stdout.flush()
283 |             return val
284 | 
285 |         @_pause_echo(echo_input)  # type: ignore
286 |         def hidden_input(prompt: t.Optional[str] = None) -> str:
287 |             sys.stdout.write(f"{prompt or ''}\n")
288 |             sys.stdout.flush()
289 |             return text_input.readline().rstrip("\r\n")
290 | 
291 |         @_pause_echo(echo_input)  # type: ignore
292 |         def _getchar(echo: bool) -> str:
293 |             char = sys.stdin.read(1)
294 | 
295 |             if echo:
296 |                 sys.stdout.write(char)
297 | 
298 |             sys.stdout.flush()
299 |             return char
300 | 
301 |         default_color = color
302 | 
303 |         def should_strip_ansi(
304 |             stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None
305 |         ) -> bool:
306 |             if color is None:
307 |                 return not default_color
308 |             return not color
309 | 
310 |         old_visible_prompt_func = termui.visible_prompt_func
311 |         old_hidden_prompt_func = termui.hidden_prompt_func
312 |         old__getchar_func = termui._getchar
313 |         old_should_strip_ansi = utils.should_strip_ansi  # type: ignore
314 |         termui.visible_prompt_func = visible_input
315 |         termui.hidden_prompt_func = hidden_input
316 |         termui._getchar = _getchar
317 |         utils.should_strip_ansi = should_strip_ansi  # type: ignore
318 | 
319 |         old_env = {}
320 |         try:
321 |             for key, value in env.items():
322 |                 old_env[key] = os.environ.get(key)
323 |                 if value is None:
324 |                     try:
325 |                         del os.environ[key]
326 |                     except Exception:
327 |                         pass
328 |                 else:
329 |                     os.environ[key] = value
330 |             yield (bytes_output, bytes_error)
331 |         finally:
332 |             for key, value in old_env.items():
333 |                 if value is None:
334 |                     try:
335 |                         del os.environ[key]
336 |                     except Exception:
337 |                         pass
338 |                 else:
339 |                     os.environ[key] = value
340 |             sys.stdout = old_stdout
341 |             sys.stderr = old_stderr
342 |             sys.stdin = old_stdin
343 |             termui.visible_prompt_func = old_visible_prompt_func
344 |             termui.hidden_prompt_func = old_hidden_prompt_func
345 |             termui._getchar = old__getchar_func
346 |             utils.should_strip_ansi = old_should_strip_ansi  # type: ignore
347 |             formatting.FORCED_WIDTH = old_forced_width
348 | 
349 |     def invoke(
350 |         self,
351 |         cli: "BaseCommand",
352 |         args: t.Optional[t.Union[str, t.Sequence[str]]] = None,
353 |         input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None,
354 |         env: t.Optional[t.Mapping[str, t.Optional[str]]] = None,
355 |         catch_exceptions: bool = True,
356 |         color: bool = False,
357 |         **extra: t.Any,
358 |     ) -> Result:
359 |         """Invokes a command in an isolated environment.  The arguments are
360 |         forwarded directly to the command line script, the `extra` keyword
361 |         arguments are passed to the :meth:`~clickpkg.Command.main` function of
362 |         the command.
363 | 
364 |         This returns a :class:`Result` object.
365 | 
366 |         :param cli: the command to invoke
367 |         :param args: the arguments to invoke. It may be given as an iterable
368 |                      or a string. When given as string it will be interpreted
369 |                      as a Unix shell command. More details at
370 |                      :func:`shlex.split`.
371 |         :param input: the input data for `sys.stdin`.
372 |         :param env: the environment overrides.
373 |         :param catch_exceptions: Whether to catch any other exceptions than
374 |                                  ``SystemExit``.
375 |         :param extra: the keyword arguments to pass to :meth:`main`.
376 |         :param color: whether the output should contain color codes. The
377 |                       application can still override this explicitly.
378 | 
379 |         .. versionchanged:: 8.0
380 |             The result object has the ``return_value`` attribute with
381 |             the value returned from the invoked command.
382 | 
383 |         .. versionchanged:: 4.0
384 |             Added the ``color`` parameter.
385 | 
386 |         .. versionchanged:: 3.0
387 |             Added the ``catch_exceptions`` parameter.
388 | 
389 |         .. versionchanged:: 3.0
390 |             The result object has the ``exc_info`` attribute with the
391 |             traceback if available.
392 |         """
393 |         exc_info = None
394 |         with self.isolation(input=input, env=env, color=color) as outstreams:
395 |             return_value = None
396 |             exception: t.Optional[BaseException] = None
397 |             exit_code = 0
398 | 
399 |             if isinstance(args, str):
400 |                 args = shlex.split(args)
401 | 
402 |             try:
403 |                 prog_name = extra.pop("prog_name")
404 |             except KeyError:
405 |                 prog_name = self.get_default_prog_name(cli)
406 | 
407 |             try:
408 |                 return_value = cli.main(args=args or (), prog_name=prog_name, **extra)
409 |             except SystemExit as e:
410 |                 exc_info = sys.exc_info()
411 |                 e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code)
412 | 
413 |                 if e_code is None:
414 |                     e_code = 0
415 | 
416 |                 if e_code != 0:
417 |                     exception = e
418 | 
419 |                 if not isinstance(e_code, int):
420 |                     sys.stdout.write(str(e_code))
421 |                     sys.stdout.write("\n")
422 |                     e_code = 1
423 | 
424 |                 exit_code = e_code
425 | 
426 |             except Exception as e:
427 |                 if not catch_exceptions:
428 |                     raise
429 |                 exception = e
430 |                 exit_code = 1
431 |                 exc_info = sys.exc_info()
432 |             finally:
433 |                 sys.stdout.flush()
434 |                 stdout = outstreams[0].getvalue()
435 |                 if self.mix_stderr:
436 |                     stderr = None
437 |                 else:
438 |                     stderr = outstreams[1].getvalue()  # type: ignore
439 | 
440 |         return Result(
441 |             runner=self,
442 |             stdout_bytes=stdout,
443 |             stderr_bytes=stderr,
444 |             return_value=return_value,
445 |             exit_code=exit_code,
446 |             exception=exception,
447 |             exc_info=exc_info,  # type: ignore
448 |         )
449 | 
450 |     @contextlib.contextmanager
451 |     def isolated_filesystem(
452 |         self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None
453 |     ) -> t.Iterator[str]:
454 |         """A context manager that creates a temporary directory and
455 |         changes the current working directory to it. This isolates tests
456 |         that affect the contents of the CWD to prevent them from
457 |         interfering with each other.
458 | 
459 |         :param temp_dir: Create the temporary directory under this
460 |             directory. If given, the created directory is not removed
461 |             when exiting.
462 | 
463 |         .. versionchanged:: 8.0
464 |             Added the ``temp_dir`` parameter.
465 |         """
466 |         cwd = os.getcwd()
467 |         dt = tempfile.mkdtemp(dir=temp_dir)
468 |         os.chdir(dt)
469 | 
470 |         try:
471 |             yield dt
472 |         finally:
473 |             os.chdir(cwd)
474 | 
475 |             if temp_dir is None:
476 |                 try:
477 |                     shutil.rmtree(dt)
478 |                 except OSError:  # noqa: B014
479 |                     pass
480 | 
```
Page 54/168FirstPrevNextLast