#
tokens: 48716/50000 2/808 files (page 97/168)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 97 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/pip/_vendor/packaging/metadata.py:
--------------------------------------------------------------------------------

```python
  1 | from __future__ import annotations
  2 | 
  3 | import email.feedparser
  4 | import email.header
  5 | import email.message
  6 | import email.parser
  7 | import email.policy
  8 | import typing
  9 | from typing import (
 10 |     Any,
 11 |     Callable,
 12 |     Generic,
 13 |     Literal,
 14 |     TypedDict,
 15 |     cast,
 16 | )
 17 | 
 18 | from . import requirements, specifiers, utils
 19 | from . import version as version_module
 20 | 
 21 | T = typing.TypeVar("T")
 22 | 
 23 | 
 24 | try:
 25 |     ExceptionGroup
 26 | except NameError:  # pragma: no cover
 27 | 
 28 |     class ExceptionGroup(Exception):
 29 |         """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11.
 30 | 
 31 |         If :external:exc:`ExceptionGroup` is already defined by Python itself,
 32 |         that version is used instead.
 33 |         """
 34 | 
 35 |         message: str
 36 |         exceptions: list[Exception]
 37 | 
 38 |         def __init__(self, message: str, exceptions: list[Exception]) -> None:
 39 |             self.message = message
 40 |             self.exceptions = exceptions
 41 | 
 42 |         def __repr__(self) -> str:
 43 |             return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})"
 44 | 
 45 | else:  # pragma: no cover
 46 |     ExceptionGroup = ExceptionGroup
 47 | 
 48 | 
 49 | class InvalidMetadata(ValueError):
 50 |     """A metadata field contains invalid data."""
 51 | 
 52 |     field: str
 53 |     """The name of the field that contains invalid data."""
 54 | 
 55 |     def __init__(self, field: str, message: str) -> None:
 56 |         self.field = field
 57 |         super().__init__(message)
 58 | 
 59 | 
 60 | # The RawMetadata class attempts to make as few assumptions about the underlying
 61 | # serialization formats as possible. The idea is that as long as a serialization
 62 | # formats offer some very basic primitives in *some* way then we can support
 63 | # serializing to and from that format.
 64 | class RawMetadata(TypedDict, total=False):
 65 |     """A dictionary of raw core metadata.
 66 | 
 67 |     Each field in core metadata maps to a key of this dictionary (when data is
 68 |     provided). The key is lower-case and underscores are used instead of dashes
 69 |     compared to the equivalent core metadata field. Any core metadata field that
 70 |     can be specified multiple times or can hold multiple values in a single
 71 |     field have a key with a plural name. See :class:`Metadata` whose attributes
 72 |     match the keys of this dictionary.
 73 | 
 74 |     Core metadata fields that can be specified multiple times are stored as a
 75 |     list or dict depending on which is appropriate for the field. Any fields
 76 |     which hold multiple values in a single field are stored as a list.
 77 | 
 78 |     """
 79 | 
 80 |     # Metadata 1.0 - PEP 241
 81 |     metadata_version: str
 82 |     name: str
 83 |     version: str
 84 |     platforms: list[str]
 85 |     summary: str
 86 |     description: str
 87 |     keywords: list[str]
 88 |     home_page: str
 89 |     author: str
 90 |     author_email: str
 91 |     license: str
 92 | 
 93 |     # Metadata 1.1 - PEP 314
 94 |     supported_platforms: list[str]
 95 |     download_url: str
 96 |     classifiers: list[str]
 97 |     requires: list[str]
 98 |     provides: list[str]
 99 |     obsoletes: list[str]
100 | 
101 |     # Metadata 1.2 - PEP 345
102 |     maintainer: str
103 |     maintainer_email: str
104 |     requires_dist: list[str]
105 |     provides_dist: list[str]
106 |     obsoletes_dist: list[str]
107 |     requires_python: str
108 |     requires_external: list[str]
109 |     project_urls: dict[str, str]
110 | 
111 |     # Metadata 2.0
112 |     # PEP 426 attempted to completely revamp the metadata format
113 |     # but got stuck without ever being able to build consensus on
114 |     # it and ultimately ended up withdrawn.
115 |     #
116 |     # However, a number of tools had started emitting METADATA with
117 |     # `2.0` Metadata-Version, so for historical reasons, this version
118 |     # was skipped.
119 | 
120 |     # Metadata 2.1 - PEP 566
121 |     description_content_type: str
122 |     provides_extra: list[str]
123 | 
124 |     # Metadata 2.2 - PEP 643
125 |     dynamic: list[str]
126 | 
127 |     # Metadata 2.3 - PEP 685
128 |     # No new fields were added in PEP 685, just some edge case were
129 |     # tightened up to provide better interoptability.
130 | 
131 | 
132 | _STRING_FIELDS = {
133 |     "author",
134 |     "author_email",
135 |     "description",
136 |     "description_content_type",
137 |     "download_url",
138 |     "home_page",
139 |     "license",
140 |     "maintainer",
141 |     "maintainer_email",
142 |     "metadata_version",
143 |     "name",
144 |     "requires_python",
145 |     "summary",
146 |     "version",
147 | }
148 | 
149 | _LIST_FIELDS = {
150 |     "classifiers",
151 |     "dynamic",
152 |     "obsoletes",
153 |     "obsoletes_dist",
154 |     "platforms",
155 |     "provides",
156 |     "provides_dist",
157 |     "provides_extra",
158 |     "requires",
159 |     "requires_dist",
160 |     "requires_external",
161 |     "supported_platforms",
162 | }
163 | 
164 | _DICT_FIELDS = {
165 |     "project_urls",
166 | }
167 | 
168 | 
169 | def _parse_keywords(data: str) -> list[str]:
170 |     """Split a string of comma-separate keyboards into a list of keywords."""
171 |     return [k.strip() for k in data.split(",")]
172 | 
173 | 
174 | def _parse_project_urls(data: list[str]) -> dict[str, str]:
175 |     """Parse a list of label/URL string pairings separated by a comma."""
176 |     urls = {}
177 |     for pair in data:
178 |         # Our logic is slightly tricky here as we want to try and do
179 |         # *something* reasonable with malformed data.
180 |         #
181 |         # The main thing that we have to worry about, is data that does
182 |         # not have a ',' at all to split the label from the Value. There
183 |         # isn't a singular right answer here, and we will fail validation
184 |         # later on (if the caller is validating) so it doesn't *really*
185 |         # matter, but since the missing value has to be an empty str
186 |         # and our return value is dict[str, str], if we let the key
187 |         # be the missing value, then they'd have multiple '' values that
188 |         # overwrite each other in a accumulating dict.
189 |         #
190 |         # The other potentional issue is that it's possible to have the
191 |         # same label multiple times in the metadata, with no solid "right"
192 |         # answer with what to do in that case. As such, we'll do the only
193 |         # thing we can, which is treat the field as unparseable and add it
194 |         # to our list of unparsed fields.
195 |         parts = [p.strip() for p in pair.split(",", 1)]
196 |         parts.extend([""] * (max(0, 2 - len(parts))))  # Ensure 2 items
197 | 
198 |         # TODO: The spec doesn't say anything about if the keys should be
199 |         #       considered case sensitive or not... logically they should
200 |         #       be case-preserving and case-insensitive, but doing that
201 |         #       would open up more cases where we might have duplicate
202 |         #       entries.
203 |         label, url = parts
204 |         if label in urls:
205 |             # The label already exists in our set of urls, so this field
206 |             # is unparseable, and we can just add the whole thing to our
207 |             # unparseable data and stop processing it.
208 |             raise KeyError("duplicate labels in project urls")
209 |         urls[label] = url
210 | 
211 |     return urls
212 | 
213 | 
214 | def _get_payload(msg: email.message.Message, source: bytes | str) -> str:
215 |     """Get the body of the message."""
216 |     # If our source is a str, then our caller has managed encodings for us,
217 |     # and we don't need to deal with it.
218 |     if isinstance(source, str):
219 |         payload: str = msg.get_payload()
220 |         return payload
221 |     # If our source is a bytes, then we're managing the encoding and we need
222 |     # to deal with it.
223 |     else:
224 |         bpayload: bytes = msg.get_payload(decode=True)
225 |         try:
226 |             return bpayload.decode("utf8", "strict")
227 |         except UnicodeDecodeError:
228 |             raise ValueError("payload in an invalid encoding")
229 | 
230 | 
231 | # The various parse_FORMAT functions here are intended to be as lenient as
232 | # possible in their parsing, while still returning a correctly typed
233 | # RawMetadata.
234 | #
235 | # To aid in this, we also generally want to do as little touching of the
236 | # data as possible, except where there are possibly some historic holdovers
237 | # that make valid data awkward to work with.
238 | #
239 | # While this is a lower level, intermediate format than our ``Metadata``
240 | # class, some light touch ups can make a massive difference in usability.
241 | 
242 | # Map METADATA fields to RawMetadata.
243 | _EMAIL_TO_RAW_MAPPING = {
244 |     "author": "author",
245 |     "author-email": "author_email",
246 |     "classifier": "classifiers",
247 |     "description": "description",
248 |     "description-content-type": "description_content_type",
249 |     "download-url": "download_url",
250 |     "dynamic": "dynamic",
251 |     "home-page": "home_page",
252 |     "keywords": "keywords",
253 |     "license": "license",
254 |     "maintainer": "maintainer",
255 |     "maintainer-email": "maintainer_email",
256 |     "metadata-version": "metadata_version",
257 |     "name": "name",
258 |     "obsoletes": "obsoletes",
259 |     "obsoletes-dist": "obsoletes_dist",
260 |     "platform": "platforms",
261 |     "project-url": "project_urls",
262 |     "provides": "provides",
263 |     "provides-dist": "provides_dist",
264 |     "provides-extra": "provides_extra",
265 |     "requires": "requires",
266 |     "requires-dist": "requires_dist",
267 |     "requires-external": "requires_external",
268 |     "requires-python": "requires_python",
269 |     "summary": "summary",
270 |     "supported-platform": "supported_platforms",
271 |     "version": "version",
272 | }
273 | _RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()}
274 | 
275 | 
276 | def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]:
277 |     """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``).
278 | 
279 |     This function returns a two-item tuple of dicts. The first dict is of
280 |     recognized fields from the core metadata specification. Fields that can be
281 |     parsed and translated into Python's built-in types are converted
282 |     appropriately. All other fields are left as-is. Fields that are allowed to
283 |     appear multiple times are stored as lists.
284 | 
285 |     The second dict contains all other fields from the metadata. This includes
286 |     any unrecognized fields. It also includes any fields which are expected to
287 |     be parsed into a built-in type but were not formatted appropriately. Finally,
288 |     any fields that are expected to appear only once but are repeated are
289 |     included in this dict.
290 | 
291 |     """
292 |     raw: dict[str, str | list[str] | dict[str, str]] = {}
293 |     unparsed: dict[str, list[str]] = {}
294 | 
295 |     if isinstance(data, str):
296 |         parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data)
297 |     else:
298 |         parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data)
299 | 
300 |     # We have to wrap parsed.keys() in a set, because in the case of multiple
301 |     # values for a key (a list), the key will appear multiple times in the
302 |     # list of keys, but we're avoiding that by using get_all().
303 |     for name in frozenset(parsed.keys()):
304 |         # Header names in RFC are case insensitive, so we'll normalize to all
305 |         # lower case to make comparisons easier.
306 |         name = name.lower()
307 | 
308 |         # We use get_all() here, even for fields that aren't multiple use,
309 |         # because otherwise someone could have e.g. two Name fields, and we
310 |         # would just silently ignore it rather than doing something about it.
311 |         headers = parsed.get_all(name) or []
312 | 
313 |         # The way the email module works when parsing bytes is that it
314 |         # unconditionally decodes the bytes as ascii using the surrogateescape
315 |         # handler. When you pull that data back out (such as with get_all() ),
316 |         # it looks to see if the str has any surrogate escapes, and if it does
317 |         # it wraps it in a Header object instead of returning the string.
318 |         #
319 |         # As such, we'll look for those Header objects, and fix up the encoding.
320 |         value = []
321 |         # Flag if we have run into any issues processing the headers, thus
322 |         # signalling that the data belongs in 'unparsed'.
323 |         valid_encoding = True
324 |         for h in headers:
325 |             # It's unclear if this can return more types than just a Header or
326 |             # a str, so we'll just assert here to make sure.
327 |             assert isinstance(h, (email.header.Header, str))
328 | 
329 |             # If it's a header object, we need to do our little dance to get
330 |             # the real data out of it. In cases where there is invalid data
331 |             # we're going to end up with mojibake, but there's no obvious, good
332 |             # way around that without reimplementing parts of the Header object
333 |             # ourselves.
334 |             #
335 |             # That should be fine since, if mojibacked happens, this key is
336 |             # going into the unparsed dict anyways.
337 |             if isinstance(h, email.header.Header):
338 |                 # The Header object stores it's data as chunks, and each chunk
339 |                 # can be independently encoded, so we'll need to check each
340 |                 # of them.
341 |                 chunks: list[tuple[bytes, str | None]] = []
342 |                 for bin, encoding in email.header.decode_header(h):
343 |                     try:
344 |                         bin.decode("utf8", "strict")
345 |                     except UnicodeDecodeError:
346 |                         # Enable mojibake.
347 |                         encoding = "latin1"
348 |                         valid_encoding = False
349 |                     else:
350 |                         encoding = "utf8"
351 |                     chunks.append((bin, encoding))
352 | 
353 |                 # Turn our chunks back into a Header object, then let that
354 |                 # Header object do the right thing to turn them into a
355 |                 # string for us.
356 |                 value.append(str(email.header.make_header(chunks)))
357 |             # This is already a string, so just add it.
358 |             else:
359 |                 value.append(h)
360 | 
361 |         # We've processed all of our values to get them into a list of str,
362 |         # but we may have mojibake data, in which case this is an unparsed
363 |         # field.
364 |         if not valid_encoding:
365 |             unparsed[name] = value
366 |             continue
367 | 
368 |         raw_name = _EMAIL_TO_RAW_MAPPING.get(name)
369 |         if raw_name is None:
370 |             # This is a bit of a weird situation, we've encountered a key that
371 |             # we don't know what it means, so we don't know whether it's meant
372 |             # to be a list or not.
373 |             #
374 |             # Since we can't really tell one way or another, we'll just leave it
375 |             # as a list, even though it may be a single item list, because that's
376 |             # what makes the most sense for email headers.
377 |             unparsed[name] = value
378 |             continue
379 | 
380 |         # If this is one of our string fields, then we'll check to see if our
381 |         # value is a list of a single item. If it is then we'll assume that
382 |         # it was emitted as a single string, and unwrap the str from inside
383 |         # the list.
384 |         #
385 |         # If it's any other kind of data, then we haven't the faintest clue
386 |         # what we should parse it as, and we have to just add it to our list
387 |         # of unparsed stuff.
388 |         if raw_name in _STRING_FIELDS and len(value) == 1:
389 |             raw[raw_name] = value[0]
390 |         # If this is one of our list of string fields, then we can just assign
391 |         # the value, since email *only* has strings, and our get_all() call
392 |         # above ensures that this is a list.
393 |         elif raw_name in _LIST_FIELDS:
394 |             raw[raw_name] = value
395 |         # Special Case: Keywords
396 |         # The keywords field is implemented in the metadata spec as a str,
397 |         # but it conceptually is a list of strings, and is serialized using
398 |         # ", ".join(keywords), so we'll do some light data massaging to turn
399 |         # this into what it logically is.
400 |         elif raw_name == "keywords" and len(value) == 1:
401 |             raw[raw_name] = _parse_keywords(value[0])
402 |         # Special Case: Project-URL
403 |         # The project urls is implemented in the metadata spec as a list of
404 |         # specially-formatted strings that represent a key and a value, which
405 |         # is fundamentally a mapping, however the email format doesn't support
406 |         # mappings in a sane way, so it was crammed into a list of strings
407 |         # instead.
408 |         #
409 |         # We will do a little light data massaging to turn this into a map as
410 |         # it logically should be.
411 |         elif raw_name == "project_urls":
412 |             try:
413 |                 raw[raw_name] = _parse_project_urls(value)
414 |             except KeyError:
415 |                 unparsed[name] = value
416 |         # Nothing that we've done has managed to parse this, so it'll just
417 |         # throw it in our unparseable data and move on.
418 |         else:
419 |             unparsed[name] = value
420 | 
421 |     # We need to support getting the Description from the message payload in
422 |     # addition to getting it from the the headers. This does mean, though, there
423 |     # is the possibility of it being set both ways, in which case we put both
424 |     # in 'unparsed' since we don't know which is right.
425 |     try:
426 |         payload = _get_payload(parsed, data)
427 |     except ValueError:
428 |         unparsed.setdefault("description", []).append(
429 |             parsed.get_payload(decode=isinstance(data, bytes))
430 |         )
431 |     else:
432 |         if payload:
433 |             # Check to see if we've already got a description, if so then both
434 |             # it, and this body move to unparseable.
435 |             if "description" in raw:
436 |                 description_header = cast(str, raw.pop("description"))
437 |                 unparsed.setdefault("description", []).extend(
438 |                     [description_header, payload]
439 |                 )
440 |             elif "description" in unparsed:
441 |                 unparsed["description"].append(payload)
442 |             else:
443 |                 raw["description"] = payload
444 | 
445 |     # We need to cast our `raw` to a metadata, because a TypedDict only support
446 |     # literal key names, but we're computing our key names on purpose, but the
447 |     # way this function is implemented, our `TypedDict` can only have valid key
448 |     # names.
449 |     return cast(RawMetadata, raw), unparsed
450 | 
451 | 
452 | _NOT_FOUND = object()
453 | 
454 | 
455 | # Keep the two values in sync.
456 | _VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]
457 | _MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"]
458 | 
459 | _REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"])
460 | 
461 | 
462 | class _Validator(Generic[T]):
463 |     """Validate a metadata field.
464 | 
465 |     All _process_*() methods correspond to a core metadata field. The method is
466 |     called with the field's raw value. If the raw value is valid it is returned
467 |     in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field).
468 |     If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause
469 |     as appropriate).
470 |     """
471 | 
472 |     name: str
473 |     raw_name: str
474 |     added: _MetadataVersion
475 | 
476 |     def __init__(
477 |         self,
478 |         *,
479 |         added: _MetadataVersion = "1.0",
480 |     ) -> None:
481 |         self.added = added
482 | 
483 |     def __set_name__(self, _owner: Metadata, name: str) -> None:
484 |         self.name = name
485 |         self.raw_name = _RAW_TO_EMAIL_MAPPING[name]
486 | 
487 |     def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T:
488 |         # With Python 3.8, the caching can be replaced with functools.cached_property().
489 |         # No need to check the cache as attribute lookup will resolve into the
490 |         # instance's __dict__ before __get__ is called.
491 |         cache = instance.__dict__
492 |         value = instance._raw.get(self.name)
493 | 
494 |         # To make the _process_* methods easier, we'll check if the value is None
495 |         # and if this field is NOT a required attribute, and if both of those
496 |         # things are true, we'll skip the the converter. This will mean that the
497 |         # converters never have to deal with the None union.
498 |         if self.name in _REQUIRED_ATTRS or value is not None:
499 |             try:
500 |                 converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}")
501 |             except AttributeError:
502 |                 pass
503 |             else:
504 |                 value = converter(value)
505 | 
506 |         cache[self.name] = value
507 |         try:
508 |             del instance._raw[self.name]  # type: ignore[misc]
509 |         except KeyError:
510 |             pass
511 | 
512 |         return cast(T, value)
513 | 
514 |     def _invalid_metadata(
515 |         self, msg: str, cause: Exception | None = None
516 |     ) -> InvalidMetadata:
517 |         exc = InvalidMetadata(
518 |             self.raw_name, msg.format_map({"field": repr(self.raw_name)})
519 |         )
520 |         exc.__cause__ = cause
521 |         return exc
522 | 
523 |     def _process_metadata_version(self, value: str) -> _MetadataVersion:
524 |         # Implicitly makes Metadata-Version required.
525 |         if value not in _VALID_METADATA_VERSIONS:
526 |             raise self._invalid_metadata(f"{value!r} is not a valid metadata version")
527 |         return cast(_MetadataVersion, value)
528 | 
529 |     def _process_name(self, value: str) -> str:
530 |         if not value:
531 |             raise self._invalid_metadata("{field} is a required field")
532 |         # Validate the name as a side-effect.
533 |         try:
534 |             utils.canonicalize_name(value, validate=True)
535 |         except utils.InvalidName as exc:
536 |             raise self._invalid_metadata(
537 |                 f"{value!r} is invalid for {{field}}", cause=exc
538 |             )
539 |         else:
540 |             return value
541 | 
542 |     def _process_version(self, value: str) -> version_module.Version:
543 |         if not value:
544 |             raise self._invalid_metadata("{field} is a required field")
545 |         try:
546 |             return version_module.parse(value)
547 |         except version_module.InvalidVersion as exc:
548 |             raise self._invalid_metadata(
549 |                 f"{value!r} is invalid for {{field}}", cause=exc
550 |             )
551 | 
552 |     def _process_summary(self, value: str) -> str:
553 |         """Check the field contains no newlines."""
554 |         if "\n" in value:
555 |             raise self._invalid_metadata("{field} must be a single line")
556 |         return value
557 | 
558 |     def _process_description_content_type(self, value: str) -> str:
559 |         content_types = {"text/plain", "text/x-rst", "text/markdown"}
560 |         message = email.message.EmailMessage()
561 |         message["content-type"] = value
562 | 
563 |         content_type, parameters = (
564 |             # Defaults to `text/plain` if parsing failed.
565 |             message.get_content_type().lower(),
566 |             message["content-type"].params,
567 |         )
568 |         # Check if content-type is valid or defaulted to `text/plain` and thus was
569 |         # not parseable.
570 |         if content_type not in content_types or content_type not in value.lower():
571 |             raise self._invalid_metadata(
572 |                 f"{{field}} must be one of {list(content_types)}, not {value!r}"
573 |             )
574 | 
575 |         charset = parameters.get("charset", "UTF-8")
576 |         if charset != "UTF-8":
577 |             raise self._invalid_metadata(
578 |                 f"{{field}} can only specify the UTF-8 charset, not {list(charset)}"
579 |             )
580 | 
581 |         markdown_variants = {"GFM", "CommonMark"}
582 |         variant = parameters.get("variant", "GFM")  # Use an acceptable default.
583 |         if content_type == "text/markdown" and variant not in markdown_variants:
584 |             raise self._invalid_metadata(
585 |                 f"valid Markdown variants for {{field}} are {list(markdown_variants)}, "
586 |                 f"not {variant!r}",
587 |             )
588 |         return value
589 | 
590 |     def _process_dynamic(self, value: list[str]) -> list[str]:
591 |         for dynamic_field in map(str.lower, value):
592 |             if dynamic_field in {"name", "version", "metadata-version"}:
593 |                 raise self._invalid_metadata(
594 |                     f"{value!r} is not allowed as a dynamic field"
595 |                 )
596 |             elif dynamic_field not in _EMAIL_TO_RAW_MAPPING:
597 |                 raise self._invalid_metadata(f"{value!r} is not a valid dynamic field")
598 |         return list(map(str.lower, value))
599 | 
600 |     def _process_provides_extra(
601 |         self,
602 |         value: list[str],
603 |     ) -> list[utils.NormalizedName]:
604 |         normalized_names = []
605 |         try:
606 |             for name in value:
607 |                 normalized_names.append(utils.canonicalize_name(name, validate=True))
608 |         except utils.InvalidName as exc:
609 |             raise self._invalid_metadata(
610 |                 f"{name!r} is invalid for {{field}}", cause=exc
611 |             )
612 |         else:
613 |             return normalized_names
614 | 
615 |     def _process_requires_python(self, value: str) -> specifiers.SpecifierSet:
616 |         try:
617 |             return specifiers.SpecifierSet(value)
618 |         except specifiers.InvalidSpecifier as exc:
619 |             raise self._invalid_metadata(
620 |                 f"{value!r} is invalid for {{field}}", cause=exc
621 |             )
622 | 
623 |     def _process_requires_dist(
624 |         self,
625 |         value: list[str],
626 |     ) -> list[requirements.Requirement]:
627 |         reqs = []
628 |         try:
629 |             for req in value:
630 |                 reqs.append(requirements.Requirement(req))
631 |         except requirements.InvalidRequirement as exc:
632 |             raise self._invalid_metadata(f"{req!r} is invalid for {{field}}", cause=exc)
633 |         else:
634 |             return reqs
635 | 
636 | 
637 | class Metadata:
638 |     """Representation of distribution metadata.
639 | 
640 |     Compared to :class:`RawMetadata`, this class provides objects representing
641 |     metadata fields instead of only using built-in types. Any invalid metadata
642 |     will cause :exc:`InvalidMetadata` to be raised (with a
643 |     :py:attr:`~BaseException.__cause__` attribute as appropriate).
644 |     """
645 | 
646 |     _raw: RawMetadata
647 | 
648 |     @classmethod
649 |     def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata:
650 |         """Create an instance from :class:`RawMetadata`.
651 | 
652 |         If *validate* is true, all metadata will be validated. All exceptions
653 |         related to validation will be gathered and raised as an :class:`ExceptionGroup`.
654 |         """
655 |         ins = cls()
656 |         ins._raw = data.copy()  # Mutations occur due to caching enriched values.
657 | 
658 |         if validate:
659 |             exceptions: list[Exception] = []
660 |             try:
661 |                 metadata_version = ins.metadata_version
662 |                 metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version)
663 |             except InvalidMetadata as metadata_version_exc:
664 |                 exceptions.append(metadata_version_exc)
665 |                 metadata_version = None
666 | 
667 |             # Make sure to check for the fields that are present, the required
668 |             # fields (so their absence can be reported).
669 |             fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS
670 |             # Remove fields that have already been checked.
671 |             fields_to_check -= {"metadata_version"}
672 | 
673 |             for key in fields_to_check:
674 |                 try:
675 |                     if metadata_version:
676 |                         # Can't use getattr() as that triggers descriptor protocol which
677 |                         # will fail due to no value for the instance argument.
678 |                         try:
679 |                             field_metadata_version = cls.__dict__[key].added
680 |                         except KeyError:
681 |                             exc = InvalidMetadata(key, f"unrecognized field: {key!r}")
682 |                             exceptions.append(exc)
683 |                             continue
684 |                         field_age = _VALID_METADATA_VERSIONS.index(
685 |                             field_metadata_version
686 |                         )
687 |                         if field_age > metadata_age:
688 |                             field = _RAW_TO_EMAIL_MAPPING[key]
689 |                             exc = InvalidMetadata(
690 |                                 field,
691 |                                 "{field} introduced in metadata version "
692 |                                 "{field_metadata_version}, not {metadata_version}",
693 |                             )
694 |                             exceptions.append(exc)
695 |                             continue
696 |                     getattr(ins, key)
697 |                 except InvalidMetadata as exc:
698 |                     exceptions.append(exc)
699 | 
700 |             if exceptions:
701 |                 raise ExceptionGroup("invalid metadata", exceptions)
702 | 
703 |         return ins
704 | 
705 |     @classmethod
706 |     def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata:
707 |         """Parse metadata from email headers.
708 | 
709 |         If *validate* is true, the metadata will be validated. All exceptions
710 |         related to validation will be gathered and raised as an :class:`ExceptionGroup`.
711 |         """
712 |         raw, unparsed = parse_email(data)
713 | 
714 |         if validate:
715 |             exceptions: list[Exception] = []
716 |             for unparsed_key in unparsed:
717 |                 if unparsed_key in _EMAIL_TO_RAW_MAPPING:
718 |                     message = f"{unparsed_key!r} has invalid data"
719 |                 else:
720 |                     message = f"unrecognized field: {unparsed_key!r}"
721 |                 exceptions.append(InvalidMetadata(unparsed_key, message))
722 | 
723 |             if exceptions:
724 |                 raise ExceptionGroup("unparsed", exceptions)
725 | 
726 |         try:
727 |             return cls.from_raw(raw, validate=validate)
728 |         except ExceptionGroup as exc_group:
729 |             raise ExceptionGroup(
730 |                 "invalid or unparsed metadata", exc_group.exceptions
731 |             ) from None
732 | 
733 |     metadata_version: _Validator[_MetadataVersion] = _Validator()
734 |     """:external:ref:`core-metadata-metadata-version`
735 |     (required; validated to be a valid metadata version)"""
736 |     name: _Validator[str] = _Validator()
737 |     """:external:ref:`core-metadata-name`
738 |     (required; validated using :func:`~packaging.utils.canonicalize_name` and its
739 |     *validate* parameter)"""
740 |     version: _Validator[version_module.Version] = _Validator()
741 |     """:external:ref:`core-metadata-version` (required)"""
742 |     dynamic: _Validator[list[str] | None] = _Validator(
743 |         added="2.2",
744 |     )
745 |     """:external:ref:`core-metadata-dynamic`
746 |     (validated against core metadata field names and lowercased)"""
747 |     platforms: _Validator[list[str] | None] = _Validator()
748 |     """:external:ref:`core-metadata-platform`"""
749 |     supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1")
750 |     """:external:ref:`core-metadata-supported-platform`"""
751 |     summary: _Validator[str | None] = _Validator()
752 |     """:external:ref:`core-metadata-summary` (validated to contain no newlines)"""
753 |     description: _Validator[str | None] = _Validator()  # TODO 2.1: can be in body
754 |     """:external:ref:`core-metadata-description`"""
755 |     description_content_type: _Validator[str | None] = _Validator(added="2.1")
756 |     """:external:ref:`core-metadata-description-content-type` (validated)"""
757 |     keywords: _Validator[list[str] | None] = _Validator()
758 |     """:external:ref:`core-metadata-keywords`"""
759 |     home_page: _Validator[str | None] = _Validator()
760 |     """:external:ref:`core-metadata-home-page`"""
761 |     download_url: _Validator[str | None] = _Validator(added="1.1")
762 |     """:external:ref:`core-metadata-download-url`"""
763 |     author: _Validator[str | None] = _Validator()
764 |     """:external:ref:`core-metadata-author`"""
765 |     author_email: _Validator[str | None] = _Validator()
766 |     """:external:ref:`core-metadata-author-email`"""
767 |     maintainer: _Validator[str | None] = _Validator(added="1.2")
768 |     """:external:ref:`core-metadata-maintainer`"""
769 |     maintainer_email: _Validator[str | None] = _Validator(added="1.2")
770 |     """:external:ref:`core-metadata-maintainer-email`"""
771 |     license: _Validator[str | None] = _Validator()
772 |     """:external:ref:`core-metadata-license`"""
773 |     classifiers: _Validator[list[str] | None] = _Validator(added="1.1")
774 |     """:external:ref:`core-metadata-classifier`"""
775 |     requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator(
776 |         added="1.2"
777 |     )
778 |     """:external:ref:`core-metadata-requires-dist`"""
779 |     requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator(
780 |         added="1.2"
781 |     )
782 |     """:external:ref:`core-metadata-requires-python`"""
783 |     # Because `Requires-External` allows for non-PEP 440 version specifiers, we
784 |     # don't do any processing on the values.
785 |     requires_external: _Validator[list[str] | None] = _Validator(added="1.2")
786 |     """:external:ref:`core-metadata-requires-external`"""
787 |     project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2")
788 |     """:external:ref:`core-metadata-project-url`"""
789 |     # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation
790 |     # regardless of metadata version.
791 |     provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator(
792 |         added="2.1",
793 |     )
794 |     """:external:ref:`core-metadata-provides-extra`"""
795 |     provides_dist: _Validator[list[str] | None] = _Validator(added="1.2")
796 |     """:external:ref:`core-metadata-provides-dist`"""
797 |     obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2")
798 |     """:external:ref:`core-metadata-obsoletes-dist`"""
799 |     requires: _Validator[list[str] | None] = _Validator(added="1.1")
800 |     """``Requires`` (deprecated)"""
801 |     provides: _Validator[list[str] | None] = _Validator(added="1.1")
802 |     """``Provides`` (deprecated)"""
803 |     obsoletes: _Validator[list[str] | None] = _Validator(added="1.1")
804 |     """``Obsoletes`` (deprecated)"""
805 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py:
--------------------------------------------------------------------------------

```python
  1 | import contextlib
  2 | import functools
  3 | import logging
  4 | from typing import (
  5 |     TYPE_CHECKING,
  6 |     Callable,
  7 |     Dict,
  8 |     FrozenSet,
  9 |     Iterable,
 10 |     Iterator,
 11 |     List,
 12 |     Mapping,
 13 |     NamedTuple,
 14 |     Optional,
 15 |     Protocol,
 16 |     Sequence,
 17 |     Set,
 18 |     Tuple,
 19 |     TypeVar,
 20 |     cast,
 21 | )
 22 | 
 23 | from pip._vendor.packaging.requirements import InvalidRequirement
 24 | from pip._vendor.packaging.specifiers import SpecifierSet
 25 | from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
 26 | from pip._vendor.packaging.version import Version
 27 | from pip._vendor.resolvelib import ResolutionImpossible
 28 | 
 29 | from pip._internal.cache import CacheEntry, WheelCache
 30 | from pip._internal.exceptions import (
 31 |     DistributionNotFound,
 32 |     InstallationError,
 33 |     MetadataInconsistent,
 34 |     MetadataInvalid,
 35 |     UnsupportedPythonVersion,
 36 |     UnsupportedWheel,
 37 | )
 38 | from pip._internal.index.package_finder import PackageFinder
 39 | from pip._internal.metadata import BaseDistribution, get_default_environment
 40 | from pip._internal.models.link import Link
 41 | from pip._internal.models.wheel import Wheel
 42 | from pip._internal.operations.prepare import RequirementPreparer
 43 | from pip._internal.req.constructors import (
 44 |     install_req_drop_extras,
 45 |     install_req_from_link_and_ireq,
 46 | )
 47 | from pip._internal.req.req_install import (
 48 |     InstallRequirement,
 49 |     check_invalid_constraint_type,
 50 | )
 51 | from pip._internal.resolution.base import InstallRequirementProvider
 52 | from pip._internal.utils.compatibility_tags import get_supported
 53 | from pip._internal.utils.hashes import Hashes
 54 | from pip._internal.utils.packaging import get_requirement
 55 | from pip._internal.utils.virtualenv import running_under_virtualenv
 56 | 
 57 | from .base import Candidate, Constraint, Requirement
 58 | from .candidates import (
 59 |     AlreadyInstalledCandidate,
 60 |     BaseCandidate,
 61 |     EditableCandidate,
 62 |     ExtrasCandidate,
 63 |     LinkCandidate,
 64 |     RequiresPythonCandidate,
 65 |     as_base_candidate,
 66 | )
 67 | from .found_candidates import FoundCandidates, IndexCandidateInfo
 68 | from .requirements import (
 69 |     ExplicitRequirement,
 70 |     RequiresPythonRequirement,
 71 |     SpecifierRequirement,
 72 |     SpecifierWithoutExtrasRequirement,
 73 |     UnsatisfiableRequirement,
 74 | )
 75 | 
 76 | if TYPE_CHECKING:
 77 | 
 78 |     class ConflictCause(Protocol):
 79 |         requirement: RequiresPythonRequirement
 80 |         parent: Candidate
 81 | 
 82 | 
 83 | logger = logging.getLogger(__name__)
 84 | 
 85 | C = TypeVar("C")
 86 | Cache = Dict[Link, C]
 87 | 
 88 | 
 89 | class CollectedRootRequirements(NamedTuple):
 90 |     requirements: List[Requirement]
 91 |     constraints: Dict[str, Constraint]
 92 |     user_requested: Dict[str, int]
 93 | 
 94 | 
 95 | class Factory:
 96 |     def __init__(
 97 |         self,
 98 |         finder: PackageFinder,
 99 |         preparer: RequirementPreparer,
100 |         make_install_req: InstallRequirementProvider,
101 |         wheel_cache: Optional[WheelCache],
102 |         use_user_site: bool,
103 |         force_reinstall: bool,
104 |         ignore_installed: bool,
105 |         ignore_requires_python: bool,
106 |         py_version_info: Optional[Tuple[int, ...]] = None,
107 |     ) -> None:
108 |         self._finder = finder
109 |         self.preparer = preparer
110 |         self._wheel_cache = wheel_cache
111 |         self._python_candidate = RequiresPythonCandidate(py_version_info)
112 |         self._make_install_req_from_spec = make_install_req
113 |         self._use_user_site = use_user_site
114 |         self._force_reinstall = force_reinstall
115 |         self._ignore_requires_python = ignore_requires_python
116 | 
117 |         self._build_failures: Cache[InstallationError] = {}
118 |         self._link_candidate_cache: Cache[LinkCandidate] = {}
119 |         self._editable_candidate_cache: Cache[EditableCandidate] = {}
120 |         self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {}
121 |         self._extras_candidate_cache: Dict[
122 |             Tuple[int, FrozenSet[NormalizedName]], ExtrasCandidate
123 |         ] = {}
124 |         self._supported_tags_cache = get_supported()
125 | 
126 |         if not ignore_installed:
127 |             env = get_default_environment()
128 |             self._installed_dists = {
129 |                 dist.canonical_name: dist
130 |                 for dist in env.iter_installed_distributions(local_only=False)
131 |             }
132 |         else:
133 |             self._installed_dists = {}
134 | 
135 |     @property
136 |     def force_reinstall(self) -> bool:
137 |         return self._force_reinstall
138 | 
139 |     def _fail_if_link_is_unsupported_wheel(self, link: Link) -> None:
140 |         if not link.is_wheel:
141 |             return
142 |         wheel = Wheel(link.filename)
143 |         if wheel.supported(self._finder.target_python.get_unsorted_tags()):
144 |             return
145 |         msg = f"{link.filename} is not a supported wheel on this platform."
146 |         raise UnsupportedWheel(msg)
147 | 
148 |     def _make_extras_candidate(
149 |         self,
150 |         base: BaseCandidate,
151 |         extras: FrozenSet[str],
152 |         *,
153 |         comes_from: Optional[InstallRequirement] = None,
154 |     ) -> ExtrasCandidate:
155 |         cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras))
156 |         try:
157 |             candidate = self._extras_candidate_cache[cache_key]
158 |         except KeyError:
159 |             candidate = ExtrasCandidate(base, extras, comes_from=comes_from)
160 |             self._extras_candidate_cache[cache_key] = candidate
161 |         return candidate
162 | 
163 |     def _make_candidate_from_dist(
164 |         self,
165 |         dist: BaseDistribution,
166 |         extras: FrozenSet[str],
167 |         template: InstallRequirement,
168 |     ) -> Candidate:
169 |         try:
170 |             base = self._installed_candidate_cache[dist.canonical_name]
171 |         except KeyError:
172 |             base = AlreadyInstalledCandidate(dist, template, factory=self)
173 |             self._installed_candidate_cache[dist.canonical_name] = base
174 |         if not extras:
175 |             return base
176 |         return self._make_extras_candidate(base, extras, comes_from=template)
177 | 
178 |     def _make_candidate_from_link(
179 |         self,
180 |         link: Link,
181 |         extras: FrozenSet[str],
182 |         template: InstallRequirement,
183 |         name: Optional[NormalizedName],
184 |         version: Optional[Version],
185 |     ) -> Optional[Candidate]:
186 |         base: Optional[BaseCandidate] = self._make_base_candidate_from_link(
187 |             link, template, name, version
188 |         )
189 |         if not extras or base is None:
190 |             return base
191 |         return self._make_extras_candidate(base, extras, comes_from=template)
192 | 
193 |     def _make_base_candidate_from_link(
194 |         self,
195 |         link: Link,
196 |         template: InstallRequirement,
197 |         name: Optional[NormalizedName],
198 |         version: Optional[Version],
199 |     ) -> Optional[BaseCandidate]:
200 |         # TODO: Check already installed candidate, and use it if the link and
201 |         # editable flag match.
202 | 
203 |         if link in self._build_failures:
204 |             # We already tried this candidate before, and it does not build.
205 |             # Don't bother trying again.
206 |             return None
207 | 
208 |         if template.editable:
209 |             if link not in self._editable_candidate_cache:
210 |                 try:
211 |                     self._editable_candidate_cache[link] = EditableCandidate(
212 |                         link,
213 |                         template,
214 |                         factory=self,
215 |                         name=name,
216 |                         version=version,
217 |                     )
218 |                 except (MetadataInconsistent, MetadataInvalid) as e:
219 |                     logger.info(
220 |                         "Discarding [blue underline]%s[/]: [yellow]%s[reset]",
221 |                         link,
222 |                         e,
223 |                         extra={"markup": True},
224 |                     )
225 |                     self._build_failures[link] = e
226 |                     return None
227 | 
228 |             return self._editable_candidate_cache[link]
229 |         else:
230 |             if link not in self._link_candidate_cache:
231 |                 try:
232 |                     self._link_candidate_cache[link] = LinkCandidate(
233 |                         link,
234 |                         template,
235 |                         factory=self,
236 |                         name=name,
237 |                         version=version,
238 |                     )
239 |                 except MetadataInconsistent as e:
240 |                     logger.info(
241 |                         "Discarding [blue underline]%s[/]: [yellow]%s[reset]",
242 |                         link,
243 |                         e,
244 |                         extra={"markup": True},
245 |                     )
246 |                     self._build_failures[link] = e
247 |                     return None
248 |             return self._link_candidate_cache[link]
249 | 
250 |     def _iter_found_candidates(
251 |         self,
252 |         ireqs: Sequence[InstallRequirement],
253 |         specifier: SpecifierSet,
254 |         hashes: Hashes,
255 |         prefers_installed: bool,
256 |         incompatible_ids: Set[int],
257 |     ) -> Iterable[Candidate]:
258 |         if not ireqs:
259 |             return ()
260 | 
261 |         # The InstallRequirement implementation requires us to give it a
262 |         # "template". Here we just choose the first requirement to represent
263 |         # all of them.
264 |         # Hopefully the Project model can correct this mismatch in the future.
265 |         template = ireqs[0]
266 |         assert template.req, "Candidates found on index must be PEP 508"
267 |         name = canonicalize_name(template.req.name)
268 | 
269 |         extras: FrozenSet[str] = frozenset()
270 |         for ireq in ireqs:
271 |             assert ireq.req, "Candidates found on index must be PEP 508"
272 |             specifier &= ireq.req.specifier
273 |             hashes &= ireq.hashes(trust_internet=False)
274 |             extras |= frozenset(ireq.extras)
275 | 
276 |         def _get_installed_candidate() -> Optional[Candidate]:
277 |             """Get the candidate for the currently-installed version."""
278 |             # If --force-reinstall is set, we want the version from the index
279 |             # instead, so we "pretend" there is nothing installed.
280 |             if self._force_reinstall:
281 |                 return None
282 |             try:
283 |                 installed_dist = self._installed_dists[name]
284 |             except KeyError:
285 |                 return None
286 |             # Don't use the installed distribution if its version does not fit
287 |             # the current dependency graph.
288 |             if not specifier.contains(installed_dist.version, prereleases=True):
289 |                 return None
290 |             candidate = self._make_candidate_from_dist(
291 |                 dist=installed_dist,
292 |                 extras=extras,
293 |                 template=template,
294 |             )
295 |             # The candidate is a known incompatibility. Don't use it.
296 |             if id(candidate) in incompatible_ids:
297 |                 return None
298 |             return candidate
299 | 
300 |         def iter_index_candidate_infos() -> Iterator[IndexCandidateInfo]:
301 |             result = self._finder.find_best_candidate(
302 |                 project_name=name,
303 |                 specifier=specifier,
304 |                 hashes=hashes,
305 |             )
306 |             icans = list(result.iter_applicable())
307 | 
308 |             # PEP 592: Yanked releases are ignored unless the specifier
309 |             # explicitly pins a version (via '==' or '===') that can be
310 |             # solely satisfied by a yanked release.
311 |             all_yanked = all(ican.link.is_yanked for ican in icans)
312 | 
313 |             def is_pinned(specifier: SpecifierSet) -> bool:
314 |                 for sp in specifier:
315 |                     if sp.operator == "===":
316 |                         return True
317 |                     if sp.operator != "==":
318 |                         continue
319 |                     if sp.version.endswith(".*"):
320 |                         continue
321 |                     return True
322 |                 return False
323 | 
324 |             pinned = is_pinned(specifier)
325 | 
326 |             # PackageFinder returns earlier versions first, so we reverse.
327 |             for ican in reversed(icans):
328 |                 if not (all_yanked and pinned) and ican.link.is_yanked:
329 |                     continue
330 |                 func = functools.partial(
331 |                     self._make_candidate_from_link,
332 |                     link=ican.link,
333 |                     extras=extras,
334 |                     template=template,
335 |                     name=name,
336 |                     version=ican.version,
337 |                 )
338 |                 yield ican.version, func
339 | 
340 |         return FoundCandidates(
341 |             iter_index_candidate_infos,
342 |             _get_installed_candidate(),
343 |             prefers_installed,
344 |             incompatible_ids,
345 |         )
346 | 
347 |     def _iter_explicit_candidates_from_base(
348 |         self,
349 |         base_requirements: Iterable[Requirement],
350 |         extras: FrozenSet[str],
351 |     ) -> Iterator[Candidate]:
352 |         """Produce explicit candidates from the base given an extra-ed package.
353 | 
354 |         :param base_requirements: Requirements known to the resolver. The
355 |             requirements are guaranteed to not have extras.
356 |         :param extras: The extras to inject into the explicit requirements'
357 |             candidates.
358 |         """
359 |         for req in base_requirements:
360 |             lookup_cand, _ = req.get_candidate_lookup()
361 |             if lookup_cand is None:  # Not explicit.
362 |                 continue
363 |             # We've stripped extras from the identifier, and should always
364 |             # get a BaseCandidate here, unless there's a bug elsewhere.
365 |             base_cand = as_base_candidate(lookup_cand)
366 |             assert base_cand is not None, "no extras here"
367 |             yield self._make_extras_candidate(base_cand, extras)
368 | 
369 |     def _iter_candidates_from_constraints(
370 |         self,
371 |         identifier: str,
372 |         constraint: Constraint,
373 |         template: InstallRequirement,
374 |     ) -> Iterator[Candidate]:
375 |         """Produce explicit candidates from constraints.
376 | 
377 |         This creates "fake" InstallRequirement objects that are basically clones
378 |         of what "should" be the template, but with original_link set to link.
379 |         """
380 |         for link in constraint.links:
381 |             self._fail_if_link_is_unsupported_wheel(link)
382 |             candidate = self._make_base_candidate_from_link(
383 |                 link,
384 |                 template=install_req_from_link_and_ireq(link, template),
385 |                 name=canonicalize_name(identifier),
386 |                 version=None,
387 |             )
388 |             if candidate:
389 |                 yield candidate
390 | 
391 |     def find_candidates(
392 |         self,
393 |         identifier: str,
394 |         requirements: Mapping[str, Iterable[Requirement]],
395 |         incompatibilities: Mapping[str, Iterator[Candidate]],
396 |         constraint: Constraint,
397 |         prefers_installed: bool,
398 |         is_satisfied_by: Callable[[Requirement, Candidate], bool],
399 |     ) -> Iterable[Candidate]:
400 |         # Collect basic lookup information from the requirements.
401 |         explicit_candidates: Set[Candidate] = set()
402 |         ireqs: List[InstallRequirement] = []
403 |         for req in requirements[identifier]:
404 |             cand, ireq = req.get_candidate_lookup()
405 |             if cand is not None:
406 |                 explicit_candidates.add(cand)
407 |             if ireq is not None:
408 |                 ireqs.append(ireq)
409 | 
410 |         # If the current identifier contains extras, add requires and explicit
411 |         # candidates from entries from extra-less identifier.
412 |         with contextlib.suppress(InvalidRequirement):
413 |             parsed_requirement = get_requirement(identifier)
414 |             if parsed_requirement.name != identifier:
415 |                 explicit_candidates.update(
416 |                     self._iter_explicit_candidates_from_base(
417 |                         requirements.get(parsed_requirement.name, ()),
418 |                         frozenset(parsed_requirement.extras),
419 |                     ),
420 |                 )
421 |                 for req in requirements.get(parsed_requirement.name, []):
422 |                     _, ireq = req.get_candidate_lookup()
423 |                     if ireq is not None:
424 |                         ireqs.append(ireq)
425 | 
426 |         # Add explicit candidates from constraints. We only do this if there are
427 |         # known ireqs, which represent requirements not already explicit. If
428 |         # there are no ireqs, we're constraining already-explicit requirements,
429 |         # which is handled later when we return the explicit candidates.
430 |         if ireqs:
431 |             try:
432 |                 explicit_candidates.update(
433 |                     self._iter_candidates_from_constraints(
434 |                         identifier,
435 |                         constraint,
436 |                         template=ireqs[0],
437 |                     ),
438 |                 )
439 |             except UnsupportedWheel:
440 |                 # If we're constrained to install a wheel incompatible with the
441 |                 # target architecture, no candidates will ever be valid.
442 |                 return ()
443 | 
444 |         # Since we cache all the candidates, incompatibility identification
445 |         # can be made quicker by comparing only the id() values.
446 |         incompat_ids = {id(c) for c in incompatibilities.get(identifier, ())}
447 | 
448 |         # If none of the requirements want an explicit candidate, we can ask
449 |         # the finder for candidates.
450 |         if not explicit_candidates:
451 |             return self._iter_found_candidates(
452 |                 ireqs,
453 |                 constraint.specifier,
454 |                 constraint.hashes,
455 |                 prefers_installed,
456 |                 incompat_ids,
457 |             )
458 | 
459 |         return (
460 |             c
461 |             for c in explicit_candidates
462 |             if id(c) not in incompat_ids
463 |             and constraint.is_satisfied_by(c)
464 |             and all(is_satisfied_by(req, c) for req in requirements[identifier])
465 |         )
466 | 
467 |     def _make_requirements_from_install_req(
468 |         self, ireq: InstallRequirement, requested_extras: Iterable[str]
469 |     ) -> Iterator[Requirement]:
470 |         """
471 |         Returns requirement objects associated with the given InstallRequirement. In
472 |         most cases this will be a single object but the following special cases exist:
473 |             - the InstallRequirement has markers that do not apply -> result is empty
474 |             - the InstallRequirement has both a constraint (or link) and extras
475 |                 -> result is split in two requirement objects: one with the constraint
476 |                 (or link) and one with the extra. This allows centralized constraint
477 |                 handling for the base, resulting in fewer candidate rejections.
478 |         """
479 |         if not ireq.match_markers(requested_extras):
480 |             logger.info(
481 |                 "Ignoring %s: markers '%s' don't match your environment",
482 |                 ireq.name,
483 |                 ireq.markers,
484 |             )
485 |         elif not ireq.link:
486 |             if ireq.extras and ireq.req is not None and ireq.req.specifier:
487 |                 yield SpecifierWithoutExtrasRequirement(ireq)
488 |             yield SpecifierRequirement(ireq)
489 |         else:
490 |             self._fail_if_link_is_unsupported_wheel(ireq.link)
491 |             # Always make the link candidate for the base requirement to make it
492 |             # available to `find_candidates` for explicit candidate lookup for any
493 |             # set of extras.
494 |             # The extras are required separately via a second requirement.
495 |             cand = self._make_base_candidate_from_link(
496 |                 ireq.link,
497 |                 template=install_req_drop_extras(ireq) if ireq.extras else ireq,
498 |                 name=canonicalize_name(ireq.name) if ireq.name else None,
499 |                 version=None,
500 |             )
501 |             if cand is None:
502 |                 # There's no way we can satisfy a URL requirement if the underlying
503 |                 # candidate fails to build. An unnamed URL must be user-supplied, so
504 |                 # we fail eagerly. If the URL is named, an unsatisfiable requirement
505 |                 # can make the resolver do the right thing, either backtrack (and
506 |                 # maybe find some other requirement that's buildable) or raise a
507 |                 # ResolutionImpossible eventually.
508 |                 if not ireq.name:
509 |                     raise self._build_failures[ireq.link]
510 |                 yield UnsatisfiableRequirement(canonicalize_name(ireq.name))
511 |             else:
512 |                 # require the base from the link
513 |                 yield self.make_requirement_from_candidate(cand)
514 |                 if ireq.extras:
515 |                     # require the extras on top of the base candidate
516 |                     yield self.make_requirement_from_candidate(
517 |                         self._make_extras_candidate(cand, frozenset(ireq.extras))
518 |                     )
519 | 
520 |     def collect_root_requirements(
521 |         self, root_ireqs: List[InstallRequirement]
522 |     ) -> CollectedRootRequirements:
523 |         collected = CollectedRootRequirements([], {}, {})
524 |         for i, ireq in enumerate(root_ireqs):
525 |             if ireq.constraint:
526 |                 # Ensure we only accept valid constraints
527 |                 problem = check_invalid_constraint_type(ireq)
528 |                 if problem:
529 |                     raise InstallationError(problem)
530 |                 if not ireq.match_markers():
531 |                     continue
532 |                 assert ireq.name, "Constraint must be named"
533 |                 name = canonicalize_name(ireq.name)
534 |                 if name in collected.constraints:
535 |                     collected.constraints[name] &= ireq
536 |                 else:
537 |                     collected.constraints[name] = Constraint.from_ireq(ireq)
538 |             else:
539 |                 reqs = list(
540 |                     self._make_requirements_from_install_req(
541 |                         ireq,
542 |                         requested_extras=(),
543 |                     )
544 |                 )
545 |                 if not reqs:
546 |                     continue
547 |                 template = reqs[0]
548 |                 if ireq.user_supplied and template.name not in collected.user_requested:
549 |                     collected.user_requested[template.name] = i
550 |                 collected.requirements.extend(reqs)
551 |         # Put requirements with extras at the end of the root requires. This does not
552 |         # affect resolvelib's picking preference but it does affect its initial criteria
553 |         # population: by putting extras at the end we enable the candidate finder to
554 |         # present resolvelib with a smaller set of candidates to resolvelib, already
555 |         # taking into account any non-transient constraints on the associated base. This
556 |         # means resolvelib will have fewer candidates to visit and reject.
557 |         # Python's list sort is stable, meaning relative order is kept for objects with
558 |         # the same key.
559 |         collected.requirements.sort(key=lambda r: r.name != r.project_name)
560 |         return collected
561 | 
562 |     def make_requirement_from_candidate(
563 |         self, candidate: Candidate
564 |     ) -> ExplicitRequirement:
565 |         return ExplicitRequirement(candidate)
566 | 
567 |     def make_requirements_from_spec(
568 |         self,
569 |         specifier: str,
570 |         comes_from: Optional[InstallRequirement],
571 |         requested_extras: Iterable[str] = (),
572 |     ) -> Iterator[Requirement]:
573 |         """
574 |         Returns requirement objects associated with the given specifier. In most cases
575 |         this will be a single object but the following special cases exist:
576 |             - the specifier has markers that do not apply -> result is empty
577 |             - the specifier has both a constraint and extras -> result is split
578 |                 in two requirement objects: one with the constraint and one with the
579 |                 extra. This allows centralized constraint handling for the base,
580 |                 resulting in fewer candidate rejections.
581 |         """
582 |         ireq = self._make_install_req_from_spec(specifier, comes_from)
583 |         return self._make_requirements_from_install_req(ireq, requested_extras)
584 | 
585 |     def make_requires_python_requirement(
586 |         self,
587 |         specifier: SpecifierSet,
588 |     ) -> Optional[Requirement]:
589 |         if self._ignore_requires_python:
590 |             return None
591 |         # Don't bother creating a dependency for an empty Requires-Python.
592 |         if not str(specifier):
593 |             return None
594 |         return RequiresPythonRequirement(specifier, self._python_candidate)
595 | 
596 |     def get_wheel_cache_entry(
597 |         self, link: Link, name: Optional[str]
598 |     ) -> Optional[CacheEntry]:
599 |         """Look up the link in the wheel cache.
600 | 
601 |         If ``preparer.require_hashes`` is True, don't use the wheel cache,
602 |         because cached wheels, always built locally, have different hashes
603 |         than the files downloaded from the index server and thus throw false
604 |         hash mismatches. Furthermore, cached wheels at present have
605 |         nondeterministic contents due to file modification times.
606 |         """
607 |         if self._wheel_cache is None:
608 |             return None
609 |         return self._wheel_cache.get_cache_entry(
610 |             link=link,
611 |             package_name=name,
612 |             supported_tags=self._supported_tags_cache,
613 |         )
614 | 
615 |     def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]:
616 |         # TODO: Are there more cases this needs to return True? Editable?
617 |         dist = self._installed_dists.get(candidate.project_name)
618 |         if dist is None:  # Not installed, no uninstallation required.
619 |             return None
620 | 
621 |         # We're installing into global site. The current installation must
622 |         # be uninstalled, no matter it's in global or user site, because the
623 |         # user site installation has precedence over global.
624 |         if not self._use_user_site:
625 |             return dist
626 | 
627 |         # We're installing into user site. Remove the user site installation.
628 |         if dist.in_usersite:
629 |             return dist
630 | 
631 |         # We're installing into user site, but the installed incompatible
632 |         # package is in global site. We can't uninstall that, and would let
633 |         # the new user installation to "shadow" it. But shadowing won't work
634 |         # in virtual environments, so we error out.
635 |         if running_under_virtualenv() and dist.in_site_packages:
636 |             message = (
637 |                 f"Will not install to the user site because it will lack "
638 |                 f"sys.path precedence to {dist.raw_name} in {dist.location}"
639 |             )
640 |             raise InstallationError(message)
641 |         return None
642 | 
643 |     def _report_requires_python_error(
644 |         self, causes: Sequence["ConflictCause"]
645 |     ) -> UnsupportedPythonVersion:
646 |         assert causes, "Requires-Python error reported with no cause"
647 | 
648 |         version = self._python_candidate.version
649 | 
650 |         if len(causes) == 1:
651 |             specifier = str(causes[0].requirement.specifier)
652 |             message = (
653 |                 f"Package {causes[0].parent.name!r} requires a different "
654 |                 f"Python: {version} not in {specifier!r}"
655 |             )
656 |             return UnsupportedPythonVersion(message)
657 | 
658 |         message = f"Packages require a different Python. {version} not in:"
659 |         for cause in causes:
660 |             package = cause.parent.format_for_error()
661 |             specifier = str(cause.requirement.specifier)
662 |             message += f"\n{specifier!r} (required by {package})"
663 |         return UnsupportedPythonVersion(message)
664 | 
665 |     def _report_single_requirement_conflict(
666 |         self, req: Requirement, parent: Optional[Candidate]
667 |     ) -> DistributionNotFound:
668 |         if parent is None:
669 |             req_disp = str(req)
670 |         else:
671 |             req_disp = f"{req} (from {parent.name})"
672 | 
673 |         cands = self._finder.find_all_candidates(req.project_name)
674 |         skipped_by_requires_python = self._finder.requires_python_skipped_reasons()
675 | 
676 |         versions_set: Set[Version] = set()
677 |         yanked_versions_set: Set[Version] = set()
678 |         for c in cands:
679 |             is_yanked = c.link.is_yanked if c.link else False
680 |             if is_yanked:
681 |                 yanked_versions_set.add(c.version)
682 |             else:
683 |                 versions_set.add(c.version)
684 | 
685 |         versions = [str(v) for v in sorted(versions_set)]
686 |         yanked_versions = [str(v) for v in sorted(yanked_versions_set)]
687 | 
688 |         if yanked_versions:
689 |             # Saying "version X is yanked" isn't entirely accurate.
690 |             # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842
691 |             logger.critical(
692 |                 "Ignored the following yanked versions: %s",
693 |                 ", ".join(yanked_versions) or "none",
694 |             )
695 |         if skipped_by_requires_python:
696 |             logger.critical(
697 |                 "Ignored the following versions that require a different python "
698 |                 "version: %s",
699 |                 "; ".join(skipped_by_requires_python) or "none",
700 |             )
701 |         logger.critical(
702 |             "Could not find a version that satisfies the requirement %s "
703 |             "(from versions: %s)",
704 |             req_disp,
705 |             ", ".join(versions) or "none",
706 |         )
707 |         if str(req) == "requirements.txt":
708 |             logger.info(
709 |                 "HINT: You are attempting to install a package literally "
710 |                 'named "requirements.txt" (which cannot exist). Consider '
711 |                 "using the '-r' flag to install the packages listed in "
712 |                 "requirements.txt"
713 |             )
714 | 
715 |         return DistributionNotFound(f"No matching distribution found for {req}")
716 | 
717 |     def get_installation_error(
718 |         self,
719 |         e: "ResolutionImpossible[Requirement, Candidate]",
720 |         constraints: Dict[str, Constraint],
721 |     ) -> InstallationError:
722 |         assert e.causes, "Installation error reported with no cause"
723 | 
724 |         # If one of the things we can't solve is "we need Python X.Y",
725 |         # that is what we report.
726 |         requires_python_causes = [
727 |             cause
728 |             for cause in e.causes
729 |             if isinstance(cause.requirement, RequiresPythonRequirement)
730 |             and not cause.requirement.is_satisfied_by(self._python_candidate)
731 |         ]
732 |         if requires_python_causes:
733 |             # The comprehension above makes sure all Requirement instances are
734 |             # RequiresPythonRequirement, so let's cast for convenience.
735 |             return self._report_requires_python_error(
736 |                 cast("Sequence[ConflictCause]", requires_python_causes),
737 |             )
738 | 
739 |         # Otherwise, we have a set of causes which can't all be satisfied
740 |         # at once.
741 | 
742 |         # The simplest case is when we have *one* cause that can't be
743 |         # satisfied. We just report that case.
744 |         if len(e.causes) == 1:
745 |             req, parent = e.causes[0]
746 |             if req.name not in constraints:
747 |                 return self._report_single_requirement_conflict(req, parent)
748 | 
749 |         # OK, we now have a list of requirements that can't all be
750 |         # satisfied at once.
751 | 
752 |         # A couple of formatting helpers
753 |         def text_join(parts: List[str]) -> str:
754 |             if len(parts) == 1:
755 |                 return parts[0]
756 | 
757 |             return ", ".join(parts[:-1]) + " and " + parts[-1]
758 | 
759 |         def describe_trigger(parent: Candidate) -> str:
760 |             ireq = parent.get_install_requirement()
761 |             if not ireq or not ireq.comes_from:
762 |                 return f"{parent.name}=={parent.version}"
763 |             if isinstance(ireq.comes_from, InstallRequirement):
764 |                 return str(ireq.comes_from.name)
765 |             return str(ireq.comes_from)
766 | 
767 |         triggers = set()
768 |         for req, parent in e.causes:
769 |             if parent is None:
770 |                 # This is a root requirement, so we can report it directly
771 |                 trigger = req.format_for_error()
772 |             else:
773 |                 trigger = describe_trigger(parent)
774 |             triggers.add(trigger)
775 | 
776 |         if triggers:
777 |             info = text_join(sorted(triggers))
778 |         else:
779 |             info = "the requested packages"
780 | 
781 |         msg = (
782 |             f"Cannot install {info} because these package versions "
783 |             "have conflicting dependencies."
784 |         )
785 |         logger.critical(msg)
786 |         msg = "\nThe conflict is caused by:"
787 | 
788 |         relevant_constraints = set()
789 |         for req, parent in e.causes:
790 |             if req.name in constraints:
791 |                 relevant_constraints.add(req.name)
792 |             msg = msg + "\n    "
793 |             if parent:
794 |                 msg = msg + f"{parent.name} {parent.version} depends on "
795 |             else:
796 |                 msg = msg + "The user requested "
797 |             msg = msg + req.format_for_error()
798 |         for key in relevant_constraints:
799 |             spec = constraints[key].specifier
800 |             msg += f"\n    The user requested (constraint) {key}{spec}"
801 | 
802 |         msg = (
803 |             msg
804 |             + "\n\n"
805 |             + "To fix this you could try to:\n"
806 |             + "1. loosen the range of package versions you've specified\n"
807 |             + "2. remove package versions to allow pip to attempt to solve "
808 |             + "the dependency conflict\n"
809 |         )
810 | 
811 |         logger.info(msg)
812 | 
813 |         return DistributionNotFound(
814 |             "ResolutionImpossible: for help visit "
815 |             "https://pip.pypa.io/en/latest/topics/dependency-resolution/"
816 |             "#dealing-with-dependency-conflicts"
817 |         )
818 | 
```
Page 97/168FirstPrevNextLast