This is page 43 of 168. Use http://codebase.md/romanshablio/mcp_server?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .DS_Store
├── .venv
│ ├── __pycache__
│ │ └── hello.cpython-312.pyc
│ ├── bin
│ │ ├── activate
│ │ ├── activate.csh
│ │ ├── activate.fish
│ │ ├── Activate.ps1
│ │ ├── flask
│ │ ├── normalizer
│ │ ├── pip
│ │ ├── pip3
│ │ ├── pip3.12
│ │ ├── python
│ │ ├── python3
│ │ └── python3.12
│ ├── hello.py
│ ├── lib
│ │ └── python3.12
│ │ └── site-packages
│ │ ├── beautifulsoup4-4.12.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ ├── AUTHORS
│ │ │ │ └── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── blinker
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _utilities.cpython-312.pyc
│ │ │ │ └── base.cpython-312.pyc
│ │ │ ├── _utilities.py
│ │ │ ├── base.py
│ │ │ └── py.typed
│ │ ├── blinker-1.8.2.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── bs4
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── css.cpython-312.pyc
│ │ │ │ ├── dammit.cpython-312.pyc
│ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ ├── element.cpython-312.pyc
│ │ │ │ └── formatter.cpython-312.pyc
│ │ │ ├── builder
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _html5lib.cpython-312.pyc
│ │ │ │ │ ├── _htmlparser.cpython-312.pyc
│ │ │ │ │ └── _lxml.cpython-312.pyc
│ │ │ │ ├── _html5lib.py
│ │ │ │ ├── _htmlparser.py
│ │ │ │ └── _lxml.py
│ │ │ ├── css.py
│ │ │ ├── dammit.py
│ │ │ ├── diagnose.py
│ │ │ ├── element.py
│ │ │ ├── formatter.py
│ │ │ └── tests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── test_builder_registry.cpython-312.pyc
│ │ │ │ ├── test_builder.cpython-312.pyc
│ │ │ │ ├── test_css.cpython-312.pyc
│ │ │ │ ├── test_dammit.cpython-312.pyc
│ │ │ │ ├── test_docs.cpython-312.pyc
│ │ │ │ ├── test_element.cpython-312.pyc
│ │ │ │ ├── test_formatter.cpython-312.pyc
│ │ │ │ ├── test_fuzz.cpython-312.pyc
│ │ │ │ ├── test_html5lib.cpython-312.pyc
│ │ │ │ ├── test_htmlparser.cpython-312.pyc
│ │ │ │ ├── test_lxml.cpython-312.pyc
│ │ │ │ ├── test_navigablestring.cpython-312.pyc
│ │ │ │ ├── test_pageelement.cpython-312.pyc
│ │ │ │ ├── test_soup.cpython-312.pyc
│ │ │ │ ├── test_tag.cpython-312.pyc
│ │ │ │ └── test_tree.cpython-312.pyc
│ │ │ ├── fuzz
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase
│ │ │ │ ├── crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase
│ │ │ │ └── crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase
│ │ │ ├── test_builder_registry.py
│ │ │ ├── test_builder.py
│ │ │ ├── test_css.py
│ │ │ ├── test_dammit.py
│ │ │ ├── test_docs.py
│ │ │ ├── test_element.py
│ │ │ ├── test_formatter.py
│ │ │ ├── test_fuzz.py
│ │ │ ├── test_html5lib.py
│ │ │ ├── test_htmlparser.py
│ │ │ ├── test_lxml.py
│ │ │ ├── test_navigablestring.py
│ │ │ ├── test_pageelement.py
│ │ │ ├── test_soup.py
│ │ │ ├── test_tag.py
│ │ │ └── test_tree.py
│ │ ├── certifi
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── core.cpython-312.pyc
│ │ │ ├── cacert.pem
│ │ │ ├── core.py
│ │ │ └── py.typed
│ │ ├── certifi-2024.8.30.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── charset_normalizer
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── cd.cpython-312.pyc
│ │ │ │ ├── constant.cpython-312.pyc
│ │ │ │ ├── legacy.cpython-312.pyc
│ │ │ │ ├── md.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── version.cpython-312.pyc
│ │ │ ├── api.py
│ │ │ ├── cd.py
│ │ │ ├── cli
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ └── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── __main__.cpython-312.pyc
│ │ │ ├── constant.py
│ │ │ ├── legacy.py
│ │ │ ├── md__mypyc.cpython-312-darwin.so
│ │ │ ├── md.cpython-312-darwin.so
│ │ │ ├── md.py
│ │ │ ├── models.py
│ │ │ ├── py.typed
│ │ │ ├── utils.py
│ │ │ └── version.py
│ │ ├── charset_normalizer-3.4.0.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── click
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ ├── _termui_impl.cpython-312.pyc
│ │ │ │ ├── _textwrap.cpython-312.pyc
│ │ │ │ ├── _winconsole.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── decorators.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formatting.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── shell_completion.cpython-312.pyc
│ │ │ │ ├── termui.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── types.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── _compat.py
│ │ │ ├── _termui_impl.py
│ │ │ ├── _textwrap.py
│ │ │ ├── _winconsole.py
│ │ │ ├── core.py
│ │ │ ├── decorators.py
│ │ │ ├── exceptions.py
│ │ │ ├── formatting.py
│ │ │ ├── globals.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── shell_completion.py
│ │ │ ├── termui.py
│ │ │ ├── testing.py
│ │ │ ├── types.py
│ │ │ └── utils.py
│ │ ├── click-8.1.7.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.rst
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── fake_useragent
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ ├── fake.cpython-312.pyc
│ │ │ │ ├── log.cpython-312.pyc
│ │ │ │ ├── settings.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── data
│ │ │ │ └── browsers.json
│ │ │ ├── errors.py
│ │ │ ├── fake.py
│ │ │ ├── log.py
│ │ │ ├── settings.py
│ │ │ └── utils.py
│ │ ├── fake_useragent-1.5.1.dist-info
│ │ │ ├── AUTHORS
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── flask
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ ├── cli.cpython-312.pyc
│ │ │ │ ├── config.cpython-312.pyc
│ │ │ │ ├── ctx.cpython-312.pyc
│ │ │ │ ├── debughelpers.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── helpers.cpython-312.pyc
│ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── signals.cpython-312.pyc
│ │ │ │ ├── templating.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── typing.cpython-312.pyc
│ │ │ │ ├── views.cpython-312.pyc
│ │ │ │ └── wrappers.cpython-312.pyc
│ │ │ ├── app.py
│ │ │ ├── blueprints.py
│ │ │ ├── cli.py
│ │ │ ├── config.py
│ │ │ ├── ctx.py
│ │ │ ├── debughelpers.py
│ │ │ ├── globals.py
│ │ │ ├── helpers.py
│ │ │ ├── json
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ └── tag.cpython-312.pyc
│ │ │ │ ├── provider.py
│ │ │ │ └── tag.py
│ │ │ ├── logging.py
│ │ │ ├── py.typed
│ │ │ ├── sansio
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ │ └── scaffold.cpython-312.pyc
│ │ │ │ ├── app.py
│ │ │ │ ├── blueprints.py
│ │ │ │ ├── README.md
│ │ │ │ └── scaffold.py
│ │ │ ├── sessions.py
│ │ │ ├── signals.py
│ │ │ ├── templating.py
│ │ │ ├── testing.py
│ │ │ ├── typing.py
│ │ │ ├── views.py
│ │ │ └── wrappers.py
│ │ ├── flask-3.0.3.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── idna
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ ├── codec.py
│ │ │ ├── compat.py
│ │ │ ├── core.py
│ │ │ ├── idnadata.py
│ │ │ ├── intranges.py
│ │ │ ├── package_data.py
│ │ │ ├── py.typed
│ │ │ └── uts46data.py
│ │ ├── idna-3.10.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── itsdangerous
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ ├── exc.cpython-312.pyc
│ │ │ │ ├── serializer.cpython-312.pyc
│ │ │ │ ├── signer.cpython-312.pyc
│ │ │ │ ├── timed.cpython-312.pyc
│ │ │ │ └── url_safe.cpython-312.pyc
│ │ │ ├── _json.py
│ │ │ ├── encoding.py
│ │ │ ├── exc.py
│ │ │ ├── py.typed
│ │ │ ├── serializer.py
│ │ │ ├── signer.py
│ │ │ ├── timed.py
│ │ │ └── url_safe.py
│ │ ├── itsdangerous-2.2.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── jinja2
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _identifier.cpython-312.pyc
│ │ │ │ ├── async_utils.cpython-312.pyc
│ │ │ │ ├── bccache.cpython-312.pyc
│ │ │ │ ├── compiler.cpython-312.pyc
│ │ │ │ ├── constants.cpython-312.pyc
│ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ ├── defaults.cpython-312.pyc
│ │ │ │ ├── environment.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ ├── filters.cpython-312.pyc
│ │ │ │ ├── idtracking.cpython-312.pyc
│ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ ├── loaders.cpython-312.pyc
│ │ │ │ ├── meta.cpython-312.pyc
│ │ │ │ ├── nativetypes.cpython-312.pyc
│ │ │ │ ├── nodes.cpython-312.pyc
│ │ │ │ ├── optimizer.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── runtime.cpython-312.pyc
│ │ │ │ ├── sandbox.cpython-312.pyc
│ │ │ │ ├── tests.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── visitor.cpython-312.pyc
│ │ │ ├── _identifier.py
│ │ │ ├── async_utils.py
│ │ │ ├── bccache.py
│ │ │ ├── compiler.py
│ │ │ ├── constants.py
│ │ │ ├── debug.py
│ │ │ ├── defaults.py
│ │ │ ├── environment.py
│ │ │ ├── exceptions.py
│ │ │ ├── ext.py
│ │ │ ├── filters.py
│ │ │ ├── idtracking.py
│ │ │ ├── lexer.py
│ │ │ ├── loaders.py
│ │ │ ├── meta.py
│ │ │ ├── nativetypes.py
│ │ │ ├── nodes.py
│ │ │ ├── optimizer.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── runtime.py
│ │ │ ├── sandbox.py
│ │ │ ├── tests.py
│ │ │ ├── utils.py
│ │ │ └── visitor.py
│ │ ├── jinja2-3.1.4.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── lxml
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _elementpath.cpython-312.pyc
│ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ ├── cssselect.cpython-312.pyc
│ │ │ │ ├── doctestcompare.cpython-312.pyc
│ │ │ │ ├── ElementInclude.cpython-312.pyc
│ │ │ │ ├── pyclasslookup.cpython-312.pyc
│ │ │ │ ├── sax.cpython-312.pyc
│ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ ├── _elementpath.cpython-312-darwin.so
│ │ │ ├── _elementpath.py
│ │ │ ├── apihelpers.pxi
│ │ │ ├── builder.cpython-312-darwin.so
│ │ │ ├── builder.py
│ │ │ ├── classlookup.pxi
│ │ │ ├── cleanup.pxi
│ │ │ ├── cssselect.py
│ │ │ ├── debug.pxi
│ │ │ ├── docloader.pxi
│ │ │ ├── doctestcompare.py
│ │ │ ├── dtd.pxi
│ │ │ ├── ElementInclude.py
│ │ │ ├── etree_api.h
│ │ │ ├── etree.cpython-312-darwin.so
│ │ │ ├── etree.h
│ │ │ ├── etree.pyx
│ │ │ ├── extensions.pxi
│ │ │ ├── html
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _diffcommand.cpython-312.pyc
│ │ │ │ │ ├── _html5builder.cpython-312.pyc
│ │ │ │ │ ├── _setmixin.cpython-312.pyc
│ │ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ │ ├── clean.cpython-312.pyc
│ │ │ │ │ ├── defs.cpython-312.pyc
│ │ │ │ │ ├── diff.cpython-312.pyc
│ │ │ │ │ ├── ElementSoup.cpython-312.pyc
│ │ │ │ │ ├── formfill.cpython-312.pyc
│ │ │ │ │ ├── html5parser.cpython-312.pyc
│ │ │ │ │ ├── soupparser.cpython-312.pyc
│ │ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ │ ├── _diffcommand.py
│ │ │ │ ├── _html5builder.py
│ │ │ │ ├── _setmixin.py
│ │ │ │ ├── builder.py
│ │ │ │ ├── clean.py
│ │ │ │ ├── defs.py
│ │ │ │ ├── diff.cpython-312-darwin.so
│ │ │ │ ├── diff.py
│ │ │ │ ├── ElementSoup.py
│ │ │ │ ├── formfill.py
│ │ │ │ ├── html5parser.py
│ │ │ │ ├── soupparser.py
│ │ │ │ └── usedoctest.py
│ │ │ ├── includes
│ │ │ │ ├── __init__.pxd
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── c14n.pxd
│ │ │ │ ├── config.pxd
│ │ │ │ ├── dtdvalid.pxd
│ │ │ │ ├── etree_defs.h
│ │ │ │ ├── etreepublic.pxd
│ │ │ │ ├── extlibs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── libcharset.h
│ │ │ │ │ ├── localcharset.h
│ │ │ │ │ ├── zconf.h
│ │ │ │ │ └── zlib.h
│ │ │ │ ├── htmlparser.pxd
│ │ │ │ ├── libexslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── exslt.h
│ │ │ │ │ ├── exsltconfig.h
│ │ │ │ │ └── exsltexports.h
│ │ │ │ ├── libxml
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── c14n.h
│ │ │ │ │ ├── catalog.h
│ │ │ │ │ ├── chvalid.h
│ │ │ │ │ ├── debugXML.h
│ │ │ │ │ ├── dict.h
│ │ │ │ │ ├── encoding.h
│ │ │ │ │ ├── entities.h
│ │ │ │ │ ├── globals.h
│ │ │ │ │ ├── hash.h
│ │ │ │ │ ├── HTMLparser.h
│ │ │ │ │ ├── HTMLtree.h
│ │ │ │ │ ├── list.h
│ │ │ │ │ ├── nanoftp.h
│ │ │ │ │ ├── nanohttp.h
│ │ │ │ │ ├── parser.h
│ │ │ │ │ ├── parserInternals.h
│ │ │ │ │ ├── relaxng.h
│ │ │ │ │ ├── SAX.h
│ │ │ │ │ ├── SAX2.h
│ │ │ │ │ ├── schemasInternals.h
│ │ │ │ │ ├── schematron.h
│ │ │ │ │ ├── threads.h
│ │ │ │ │ ├── tree.h
│ │ │ │ │ ├── uri.h
│ │ │ │ │ ├── valid.h
│ │ │ │ │ ├── xinclude.h
│ │ │ │ │ ├── xlink.h
│ │ │ │ │ ├── xmlautomata.h
│ │ │ │ │ ├── xmlerror.h
│ │ │ │ │ ├── xmlexports.h
│ │ │ │ │ ├── xmlIO.h
│ │ │ │ │ ├── xmlmemory.h
│ │ │ │ │ ├── xmlmodule.h
│ │ │ │ │ ├── xmlreader.h
│ │ │ │ │ ├── xmlregexp.h
│ │ │ │ │ ├── xmlsave.h
│ │ │ │ │ ├── xmlschemas.h
│ │ │ │ │ ├── xmlschemastypes.h
│ │ │ │ │ ├── xmlstring.h
│ │ │ │ │ ├── xmlunicode.h
│ │ │ │ │ ├── xmlversion.h
│ │ │ │ │ ├── xmlwriter.h
│ │ │ │ │ ├── xpath.h
│ │ │ │ │ ├── xpathInternals.h
│ │ │ │ │ └── xpointer.h
│ │ │ │ ├── libxslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── attributes.h
│ │ │ │ │ ├── documents.h
│ │ │ │ │ ├── extensions.h
│ │ │ │ │ ├── extra.h
│ │ │ │ │ ├── functions.h
│ │ │ │ │ ├── imports.h
│ │ │ │ │ ├── keys.h
│ │ │ │ │ ├── namespaces.h
│ │ │ │ │ ├── numbersInternals.h
│ │ │ │ │ ├── pattern.h
│ │ │ │ │ ├── preproc.h
│ │ │ │ │ ├── security.h
│ │ │ │ │ ├── templates.h
│ │ │ │ │ ├── transform.h
│ │ │ │ │ ├── variables.h
│ │ │ │ │ ├── xslt.h
│ │ │ │ │ ├── xsltconfig.h
│ │ │ │ │ ├── xsltexports.h
│ │ │ │ │ ├── xsltInternals.h
│ │ │ │ │ ├── xsltlocale.h
│ │ │ │ │ └── xsltutils.h
│ │ │ │ ├── lxml-version.h
│ │ │ │ ├── relaxng.pxd
│ │ │ │ ├── schematron.pxd
│ │ │ │ ├── tree.pxd
│ │ │ │ ├── uri.pxd
│ │ │ │ ├── xinclude.pxd
│ │ │ │ ├── xmlerror.pxd
│ │ │ │ ├── xmlparser.pxd
│ │ │ │ ├── xmlschema.pxd
│ │ │ │ ├── xpath.pxd
│ │ │ │ └── xslt.pxd
│ │ │ ├── isoschematron
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ └── resources
│ │ │ │ ├── rng
│ │ │ │ │ └── iso-schematron.rng
│ │ │ │ └── xsl
│ │ │ │ ├── iso-schematron-xslt1
│ │ │ │ │ ├── iso_abstract_expand.xsl
│ │ │ │ │ ├── iso_dsdl_include.xsl
│ │ │ │ │ ├── iso_schematron_message.xsl
│ │ │ │ │ ├── iso_schematron_skeleton_for_xslt1.xsl
│ │ │ │ │ ├── iso_svrl_for_xslt1.xsl
│ │ │ │ │ └── readme.txt
│ │ │ │ ├── RNG2Schtrn.xsl
│ │ │ │ └── XSD2Schtrn.xsl
│ │ │ ├── iterparse.pxi
│ │ │ ├── lxml.etree_api.h
│ │ │ ├── lxml.etree.h
│ │ │ ├── nsclasses.pxi
│ │ │ ├── objectify.cpython-312-darwin.so
│ │ │ ├── objectify.pyx
│ │ │ ├── objectpath.pxi
│ │ │ ├── parser.pxi
│ │ │ ├── parsertarget.pxi
│ │ │ ├── proxy.pxi
│ │ │ ├── public-api.pxi
│ │ │ ├── pyclasslookup.py
│ │ │ ├── readonlytree.pxi
│ │ │ ├── relaxng.pxi
│ │ │ ├── sax.cpython-312-darwin.so
│ │ │ ├── sax.py
│ │ │ ├── saxparser.pxi
│ │ │ ├── schematron.pxi
│ │ │ ├── serializer.pxi
│ │ │ ├── usedoctest.py
│ │ │ ├── xinclude.pxi
│ │ │ ├── xmlerror.pxi
│ │ │ ├── xmlid.pxi
│ │ │ ├── xmlschema.pxi
│ │ │ ├── xpath.pxi
│ │ │ ├── xslt.pxi
│ │ │ └── xsltext.pxi
│ │ ├── lxml-5.3.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── LICENSES.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── markupsafe
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── _native.cpython-312.pyc
│ │ │ ├── _native.py
│ │ │ ├── _speedups.c
│ │ │ ├── _speedups.cpython-312-darwin.so
│ │ │ ├── _speedups.pyi
│ │ │ └── py.typed
│ │ ├── MarkupSafe-3.0.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── pip
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pip-runner__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── __pip-runner__.cpython-312.pyc
│ │ │ ├── _internal
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── build_env.cpython-312.pyc
│ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ ├── pyproject.cpython-312.pyc
│ │ │ │ │ ├── self_outdated_check.cpython-312.pyc
│ │ │ │ │ └── wheel_builder.cpython-312.pyc
│ │ │ │ ├── build_env.py
│ │ │ │ ├── cache.py
│ │ │ │ ├── cli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── autocompletion.cpython-312.pyc
│ │ │ │ │ │ ├── base_command.cpython-312.pyc
│ │ │ │ │ │ ├── cmdoptions.cpython-312.pyc
│ │ │ │ │ │ ├── command_context.cpython-312.pyc
│ │ │ │ │ │ ├── index_command.cpython-312.pyc
│ │ │ │ │ │ ├── main_parser.cpython-312.pyc
│ │ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bars.cpython-312.pyc
│ │ │ │ │ │ ├── req_command.cpython-312.pyc
│ │ │ │ │ │ ├── spinners.cpython-312.pyc
│ │ │ │ │ │ └── status_codes.cpython-312.pyc
│ │ │ │ │ ├── autocompletion.py
│ │ │ │ │ ├── base_command.py
│ │ │ │ │ ├── cmdoptions.py
│ │ │ │ │ ├── command_context.py
│ │ │ │ │ ├── index_command.py
│ │ │ │ │ ├── main_parser.py
│ │ │ │ │ ├── main.py
│ │ │ │ │ ├── parser.py
│ │ │ │ │ ├── progress_bars.py
│ │ │ │ │ ├── req_command.py
│ │ │ │ │ ├── spinners.py
│ │ │ │ │ └── status_codes.py
│ │ │ │ ├── commands
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── completion.cpython-312.pyc
│ │ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ ├── hash.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── inspect.cpython-312.pyc
│ │ │ │ │ │ ├── install.cpython-312.pyc
│ │ │ │ │ │ ├── list.cpython-312.pyc
│ │ │ │ │ │ ├── search.cpython-312.pyc
│ │ │ │ │ │ ├── show.cpython-312.pyc
│ │ │ │ │ │ ├── uninstall.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── completion.py
│ │ │ │ │ ├── configuration.py
│ │ │ │ │ ├── debug.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── hash.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── inspect.py
│ │ │ │ │ ├── install.py
│ │ │ │ │ ├── list.py
│ │ │ │ │ ├── search.py
│ │ │ │ │ ├── show.py
│ │ │ │ │ ├── uninstall.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── configuration.py
│ │ │ │ ├── distributions
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── installed.cpython-312.pyc
│ │ │ │ │ │ ├── sdist.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── installed.py
│ │ │ │ │ ├── sdist.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── index
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── collector.cpython-312.pyc
│ │ │ │ │ │ ├── package_finder.cpython-312.pyc
│ │ │ │ │ │ └── sources.cpython-312.pyc
│ │ │ │ │ ├── collector.py
│ │ │ │ │ ├── package_finder.py
│ │ │ │ │ └── sources.py
│ │ │ │ ├── locations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _distutils.cpython-312.pyc
│ │ │ │ │ │ ├── _sysconfig.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── _distutils.py
│ │ │ │ │ ├── _sysconfig.py
│ │ │ │ │ └── base.py
│ │ │ │ ├── main.py
│ │ │ │ ├── metadata
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ └── pkg_resources.cpython-312.pyc
│ │ │ │ │ ├── _json.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── importlib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ │ ├── _dists.cpython-312.pyc
│ │ │ │ │ │ │ └── _envs.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.py
│ │ │ │ │ │ ├── _dists.py
│ │ │ │ │ │ └── _envs.py
│ │ │ │ │ └── pkg_resources.py
│ │ │ │ ├── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── candidate.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url.cpython-312.pyc
│ │ │ │ │ │ ├── format_control.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── installation_report.cpython-312.pyc
│ │ │ │ │ │ ├── link.cpython-312.pyc
│ │ │ │ │ │ ├── scheme.cpython-312.pyc
│ │ │ │ │ │ ├── search_scope.cpython-312.pyc
│ │ │ │ │ │ ├── selection_prefs.cpython-312.pyc
│ │ │ │ │ │ ├── target_python.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── candidate.py
│ │ │ │ │ ├── direct_url.py
│ │ │ │ │ ├── format_control.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── installation_report.py
│ │ │ │ │ ├── link.py
│ │ │ │ │ ├── scheme.py
│ │ │ │ │ ├── search_scope.py
│ │ │ │ │ ├── selection_prefs.py
│ │ │ │ │ ├── target_python.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── network
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── lazy_wheel.cpython-312.pyc
│ │ │ │ │ │ ├── session.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── xmlrpc.cpython-312.pyc
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── lazy_wheel.py
│ │ │ │ │ ├── session.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── xmlrpc.py
│ │ │ │ ├── operations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ └── prepare.cpython-312.pyc
│ │ │ │ │ ├── build
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── build_tracker.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_legacy.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── build_tracker.py
│ │ │ │ │ │ ├── metadata_editable.py
│ │ │ │ │ │ ├── metadata_legacy.py
│ │ │ │ │ │ ├── metadata.py
│ │ │ │ │ │ ├── wheel_editable.py
│ │ │ │ │ │ ├── wheel_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── install
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── editable_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── editable_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ └── prepare.py
│ │ │ │ ├── pyproject.py
│ │ │ │ ├── req
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── constructors.cpython-312.pyc
│ │ │ │ │ │ ├── req_file.cpython-312.pyc
│ │ │ │ │ │ ├── req_install.cpython-312.pyc
│ │ │ │ │ │ ├── req_set.cpython-312.pyc
│ │ │ │ │ │ └── req_uninstall.cpython-312.pyc
│ │ │ │ │ ├── constructors.py
│ │ │ │ │ ├── req_file.py
│ │ │ │ │ ├── req_install.py
│ │ │ │ │ ├── req_set.py
│ │ │ │ │ └── req_uninstall.py
│ │ │ │ ├── resolution
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── legacy
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ │ └── resolver.py
│ │ │ │ │ └── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── candidates.cpython-312.pyc
│ │ │ │ │ │ ├── factory.cpython-312.pyc
│ │ │ │ │ │ ├── found_candidates.cpython-312.pyc
│ │ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ │ ├── reporter.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── candidates.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── found_candidates.py
│ │ │ │ │ ├── provider.py
│ │ │ │ │ ├── reporter.py
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ └── resolver.py
│ │ │ │ ├── self_outdated_check.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _jaraco_text.cpython-312.pyc
│ │ │ │ │ │ ├── _log.cpython-312.pyc
│ │ │ │ │ │ ├── appdirs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── compatibility_tags.cpython-312.pyc
│ │ │ │ │ │ ├── datetime.cpython-312.pyc
│ │ │ │ │ │ ├── deprecation.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url_helpers.cpython-312.pyc
│ │ │ │ │ │ ├── egg_link.cpython-312.pyc
│ │ │ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ │ │ ├── entrypoints.cpython-312.pyc
│ │ │ │ │ │ ├── filesystem.cpython-312.pyc
│ │ │ │ │ │ ├── filetypes.cpython-312.pyc
│ │ │ │ │ │ ├── glibc.cpython-312.pyc
│ │ │ │ │ │ ├── hashes.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── misc.cpython-312.pyc
│ │ │ │ │ │ ├── packaging.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── setuptools_build.cpython-312.pyc
│ │ │ │ │ │ ├── subprocess.cpython-312.pyc
│ │ │ │ │ │ ├── temp_dir.cpython-312.pyc
│ │ │ │ │ │ ├── unpacking.cpython-312.pyc
│ │ │ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ │ │ ├── virtualenv.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── _jaraco_text.py
│ │ │ │ │ ├── _log.py
│ │ │ │ │ ├── appdirs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── compatibility_tags.py
│ │ │ │ │ ├── datetime.py
│ │ │ │ │ ├── deprecation.py
│ │ │ │ │ ├── direct_url_helpers.py
│ │ │ │ │ ├── egg_link.py
│ │ │ │ │ ├── encoding.py
│ │ │ │ │ ├── entrypoints.py
│ │ │ │ │ ├── filesystem.py
│ │ │ │ │ ├── filetypes.py
│ │ │ │ │ ├── glibc.py
│ │ │ │ │ ├── hashes.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── packaging.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── setuptools_build.py
│ │ │ │ │ ├── subprocess.py
│ │ │ │ │ ├── temp_dir.py
│ │ │ │ │ ├── unpacking.py
│ │ │ │ │ ├── urls.py
│ │ │ │ │ ├── virtualenv.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── vcs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── bazaar.cpython-312.pyc
│ │ │ │ │ │ ├── git.cpython-312.pyc
│ │ │ │ │ │ ├── mercurial.cpython-312.pyc
│ │ │ │ │ │ ├── subversion.cpython-312.pyc
│ │ │ │ │ │ └── versioncontrol.cpython-312.pyc
│ │ │ │ │ ├── bazaar.py
│ │ │ │ │ ├── git.py
│ │ │ │ │ ├── mercurial.py
│ │ │ │ │ ├── subversion.py
│ │ │ │ │ └── versioncontrol.py
│ │ │ │ └── wheel_builder.py
│ │ │ ├── _vendor
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ └── typing_extensions.cpython-312.pyc
│ │ │ │ ├── cachecontrol
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _cmd.cpython-312.pyc
│ │ │ │ │ │ ├── adapter.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── controller.cpython-312.pyc
│ │ │ │ │ │ ├── filewrapper.cpython-312.pyc
│ │ │ │ │ │ ├── heuristics.cpython-312.pyc
│ │ │ │ │ │ ├── serialize.cpython-312.pyc
│ │ │ │ │ │ └── wrapper.cpython-312.pyc
│ │ │ │ │ ├── _cmd.py
│ │ │ │ │ ├── adapter.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── caches
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── file_cache.cpython-312.pyc
│ │ │ │ │ │ │ └── redis_cache.cpython-312.pyc
│ │ │ │ │ │ ├── file_cache.py
│ │ │ │ │ │ └── redis_cache.py
│ │ │ │ │ ├── controller.py
│ │ │ │ │ ├── filewrapper.py
│ │ │ │ │ ├── heuristics.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── serialize.py
│ │ │ │ │ └── wrapper.py
│ │ │ │ ├── certifi
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── core.cpython-312.pyc
│ │ │ │ │ ├── cacert.pem
│ │ │ │ │ ├── core.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── distlib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── database.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── locators.cpython-312.pyc
│ │ │ │ │ │ ├── manifest.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── resources.cpython-312.pyc
│ │ │ │ │ │ ├── scripts.cpython-312.pyc
│ │ │ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── database.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── locators.py
│ │ │ │ │ ├── manifest.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ ├── scripts.py
│ │ │ │ │ ├── t32.exe
│ │ │ │ │ ├── t64-arm.exe
│ │ │ │ │ ├── t64.exe
│ │ │ │ │ ├── util.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ ├── w32.exe
│ │ │ │ │ ├── w64-arm.exe
│ │ │ │ │ ├── w64.exe
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── distro
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── distro.cpython-312.pyc
│ │ │ │ │ ├── distro.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── idna
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ │ │ ├── codec.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── core.py
│ │ │ │ │ ├── idnadata.py
│ │ │ │ │ ├── intranges.py
│ │ │ │ │ ├── package_data.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ └── uts46data.py
│ │ │ │ ├── msgpack
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ │ │ └── fallback.cpython-312.pyc
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── ext.py
│ │ │ │ │ └── fallback.py
│ │ │ │ ├── packaging
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _elffile.cpython-312.pyc
│ │ │ │ │ │ ├── _manylinux.cpython-312.pyc
│ │ │ │ │ │ ├── _musllinux.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _structures.cpython-312.pyc
│ │ │ │ │ │ ├── _tokenizer.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ ├── specifiers.cpython-312.pyc
│ │ │ │ │ │ ├── tags.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── version.cpython-312.pyc
│ │ │ │ │ ├── _elffile.py
│ │ │ │ │ ├── _manylinux.py
│ │ │ │ │ ├── _musllinux.py
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _structures.py
│ │ │ │ │ ├── _tokenizer.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ ├── specifiers.py
│ │ │ │ │ ├── tags.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── version.py
│ │ │ │ ├── pkg_resources
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── platformdirs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── android.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── macos.cpython-312.pyc
│ │ │ │ │ │ ├── unix.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── windows.cpython-312.pyc
│ │ │ │ │ ├── android.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── unix.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── pygments
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── cmdline.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── filter.cpython-312.pyc
│ │ │ │ │ │ ├── formatter.cpython-312.pyc
│ │ │ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ │ │ ├── modeline.cpython-312.pyc
│ │ │ │ │ │ ├── plugin.cpython-312.pyc
│ │ │ │ │ │ ├── regexopt.cpython-312.pyc
│ │ │ │ │ │ ├── scanner.cpython-312.pyc
│ │ │ │ │ │ ├── sphinxext.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── token.cpython-312.pyc
│ │ │ │ │ │ ├── unistring.cpython-312.pyc
│ │ │ │ │ │ └── util.cpython-312.pyc
│ │ │ │ │ ├── cmdline.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── filter.py
│ │ │ │ │ ├── filters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── formatter.py
│ │ │ │ │ ├── formatters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ ├── bbcode.cpython-312.pyc
│ │ │ │ │ │ │ ├── groff.cpython-312.pyc
│ │ │ │ │ │ │ ├── html.cpython-312.pyc
│ │ │ │ │ │ │ ├── img.cpython-312.pyc
│ │ │ │ │ │ │ ├── irc.cpython-312.pyc
│ │ │ │ │ │ │ ├── latex.cpython-312.pyc
│ │ │ │ │ │ │ ├── other.cpython-312.pyc
│ │ │ │ │ │ │ ├── pangomarkup.cpython-312.pyc
│ │ │ │ │ │ │ ├── rtf.cpython-312.pyc
│ │ │ │ │ │ │ ├── svg.cpython-312.pyc
│ │ │ │ │ │ │ ├── terminal.cpython-312.pyc
│ │ │ │ │ │ │ └── terminal256.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ ├── bbcode.py
│ │ │ │ │ │ ├── groff.py
│ │ │ │ │ │ ├── html.py
│ │ │ │ │ │ ├── img.py
│ │ │ │ │ │ ├── irc.py
│ │ │ │ │ │ ├── latex.py
│ │ │ │ │ │ ├── other.py
│ │ │ │ │ │ ├── pangomarkup.py
│ │ │ │ │ │ ├── rtf.py
│ │ │ │ │ │ ├── svg.py
│ │ │ │ │ │ ├── terminal.py
│ │ │ │ │ │ └── terminal256.py
│ │ │ │ │ ├── lexer.py
│ │ │ │ │ ├── lexers
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ └── python.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ └── python.py
│ │ │ │ │ ├── modeline.py
│ │ │ │ │ ├── plugin.py
│ │ │ │ │ ├── regexopt.py
│ │ │ │ │ ├── scanner.py
│ │ │ │ │ ├── sphinxext.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styles
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── _mapping.cpython-312.pyc
│ │ │ │ │ │ └── _mapping.py
│ │ │ │ │ ├── token.py
│ │ │ │ │ ├── unistring.py
│ │ │ │ │ └── util.py
│ │ │ │ ├── pyproject_hooks
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ └── _impl.cpython-312.pyc
│ │ │ │ │ ├── _compat.py
│ │ │ │ │ ├── _impl.py
│ │ │ │ │ └── _in_process
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── _in_process.cpython-312.pyc
│ │ │ │ │ └── _in_process.py
│ │ │ │ ├── requests
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ │ ├── __version__.py
│ │ │ │ │ ├── _internal_utils.py
│ │ │ │ │ ├── adapters.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── certs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── cookies.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── hooks.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ ├── packages.py
│ │ │ │ │ ├── sessions.py
│ │ │ │ │ ├── status_codes.py
│ │ │ │ │ ├── structures.py
│ │ │ │ │ └── utils.py
│ │ │ │ ├── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── providers.cpython-312.pyc
│ │ │ │ │ │ ├── reporters.cpython-312.pyc
│ │ │ │ │ │ ├── resolvers.cpython-312.pyc
│ │ │ │ │ │ └── structs.cpython-312.pyc
│ │ │ │ │ ├── compat
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── collections_abc.cpython-312.pyc
│ │ │ │ │ │ └── collections_abc.py
│ │ │ │ │ ├── providers.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── reporters.py
│ │ │ │ │ ├── resolvers.py
│ │ │ │ │ └── structs.py
│ │ │ │ ├── rich
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── _cell_widths.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_codes.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_replace.cpython-312.pyc
│ │ │ │ │ │ ├── _export_format.cpython-312.pyc
│ │ │ │ │ │ ├── _extension.cpython-312.pyc
│ │ │ │ │ │ ├── _fileno.cpython-312.pyc
│ │ │ │ │ │ ├── _inspect.cpython-312.pyc
│ │ │ │ │ │ ├── _log_render.cpython-312.pyc
│ │ │ │ │ │ ├── _loop.cpython-312.pyc
│ │ │ │ │ │ ├── _null_file.cpython-312.pyc
│ │ │ │ │ │ ├── _palettes.cpython-312.pyc
│ │ │ │ │ │ ├── _pick.cpython-312.pyc
│ │ │ │ │ │ ├── _ratio.cpython-312.pyc
│ │ │ │ │ │ ├── _spinners.cpython-312.pyc
│ │ │ │ │ │ ├── _stack.cpython-312.pyc
│ │ │ │ │ │ ├── _timer.cpython-312.pyc
│ │ │ │ │ │ ├── _win32_console.cpython-312.pyc
│ │ │ │ │ │ ├── _windows_renderer.cpython-312.pyc
│ │ │ │ │ │ ├── _windows.cpython-312.pyc
│ │ │ │ │ │ ├── _wrap.cpython-312.pyc
│ │ │ │ │ │ ├── abc.cpython-312.pyc
│ │ │ │ │ │ ├── align.cpython-312.pyc
│ │ │ │ │ │ ├── ansi.cpython-312.pyc
│ │ │ │ │ │ ├── bar.cpython-312.pyc
│ │ │ │ │ │ ├── box.cpython-312.pyc
│ │ │ │ │ │ ├── cells.cpython-312.pyc
│ │ │ │ │ │ ├── color_triplet.cpython-312.pyc
│ │ │ │ │ │ ├── color.cpython-312.pyc
│ │ │ │ │ │ ├── columns.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── constrain.cpython-312.pyc
│ │ │ │ │ │ ├── containers.cpython-312.pyc
│ │ │ │ │ │ ├── control.cpython-312.pyc
│ │ │ │ │ │ ├── default_styles.cpython-312.pyc
│ │ │ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ │ │ ├── emoji.cpython-312.pyc
│ │ │ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ │ │ ├── file_proxy.cpython-312.pyc
│ │ │ │ │ │ ├── filesize.cpython-312.pyc
│ │ │ │ │ │ ├── highlighter.cpython-312.pyc
│ │ │ │ │ │ ├── json.cpython-312.pyc
│ │ │ │ │ │ ├── jupyter.cpython-312.pyc
│ │ │ │ │ │ ├── layout.cpython-312.pyc
│ │ │ │ │ │ ├── live_render.cpython-312.pyc
│ │ │ │ │ │ ├── live.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── markup.cpython-312.pyc
│ │ │ │ │ │ ├── measure.cpython-312.pyc
│ │ │ │ │ │ ├── padding.cpython-312.pyc
│ │ │ │ │ │ ├── pager.cpython-312.pyc
│ │ │ │ │ │ ├── palette.cpython-312.pyc
│ │ │ │ │ │ ├── panel.cpython-312.pyc
│ │ │ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bar.cpython-312.pyc
│ │ │ │ │ │ ├── progress.cpython-312.pyc
│ │ │ │ │ │ ├── prompt.cpython-312.pyc
│ │ │ │ │ │ ├── protocol.cpython-312.pyc
│ │ │ │ │ │ ├── region.cpython-312.pyc
│ │ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ │ ├── rule.cpython-312.pyc
│ │ │ │ │ │ ├── scope.cpython-312.pyc
│ │ │ │ │ │ ├── screen.cpython-312.pyc
│ │ │ │ │ │ ├── segment.cpython-312.pyc
│ │ │ │ │ │ ├── spinner.cpython-312.pyc
│ │ │ │ │ │ ├── status.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── styled.cpython-312.pyc
│ │ │ │ │ │ ├── syntax.cpython-312.pyc
│ │ │ │ │ │ ├── table.cpython-312.pyc
│ │ │ │ │ │ ├── terminal_theme.cpython-312.pyc
│ │ │ │ │ │ ├── text.cpython-312.pyc
│ │ │ │ │ │ ├── theme.cpython-312.pyc
│ │ │ │ │ │ ├── themes.cpython-312.pyc
│ │ │ │ │ │ ├── traceback.cpython-312.pyc
│ │ │ │ │ │ └── tree.cpython-312.pyc
│ │ │ │ │ ├── _cell_widths.py
│ │ │ │ │ ├── _emoji_codes.py
│ │ │ │ │ ├── _emoji_replace.py
│ │ │ │ │ ├── _export_format.py
│ │ │ │ │ ├── _extension.py
│ │ │ │ │ ├── _fileno.py
│ │ │ │ │ ├── _inspect.py
│ │ │ │ │ ├── _log_render.py
│ │ │ │ │ ├── _loop.py
│ │ │ │ │ ├── _null_file.py
│ │ │ │ │ ├── _palettes.py
│ │ │ │ │ ├── _pick.py
│ │ │ │ │ ├── _ratio.py
│ │ │ │ │ ├── _spinners.py
│ │ │ │ │ ├── _stack.py
│ │ │ │ │ ├── _timer.py
│ │ │ │ │ ├── _win32_console.py
│ │ │ │ │ ├── _windows_renderer.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ ├── _wrap.py
│ │ │ │ │ ├── abc.py
│ │ │ │ │ ├── align.py
│ │ │ │ │ ├── ansi.py
│ │ │ │ │ ├── bar.py
│ │ │ │ │ ├── box.py
│ │ │ │ │ ├── cells.py
│ │ │ │ │ ├── color_triplet.py
│ │ │ │ │ ├── color.py
│ │ │ │ │ ├── columns.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── constrain.py
│ │ │ │ │ ├── containers.py
│ │ │ │ │ ├── control.py
│ │ │ │ │ ├── default_styles.py
│ │ │ │ │ ├── diagnose.py
│ │ │ │ │ ├── emoji.py
│ │ │ │ │ ├── errors.py
│ │ │ │ │ ├── file_proxy.py
│ │ │ │ │ ├── filesize.py
│ │ │ │ │ ├── highlighter.py
│ │ │ │ │ ├── json.py
│ │ │ │ │ ├── jupyter.py
│ │ │ │ │ ├── layout.py
│ │ │ │ │ ├── live_render.py
│ │ │ │ │ ├── live.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── markup.py
│ │ │ │ │ ├── measure.py
│ │ │ │ │ ├── padding.py
│ │ │ │ │ ├── pager.py
│ │ │ │ │ ├── palette.py
│ │ │ │ │ ├── panel.py
│ │ │ │ │ ├── pretty.py
│ │ │ │ │ ├── progress_bar.py
│ │ │ │ │ ├── progress.py
│ │ │ │ │ ├── prompt.py
│ │ │ │ │ ├── protocol.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── region.py
│ │ │ │ │ ├── repr.py
│ │ │ │ │ ├── rule.py
│ │ │ │ │ ├── scope.py
│ │ │ │ │ ├── screen.py
│ │ │ │ │ ├── segment.py
│ │ │ │ │ ├── spinner.py
│ │ │ │ │ ├── status.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styled.py
│ │ │ │ │ ├── syntax.py
│ │ │ │ │ ├── table.py
│ │ │ │ │ ├── terminal_theme.py
│ │ │ │ │ ├── text.py
│ │ │ │ │ ├── theme.py
│ │ │ │ │ ├── themes.py
│ │ │ │ │ ├── traceback.py
│ │ │ │ │ └── tree.py
│ │ │ │ ├── tomli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _re.cpython-312.pyc
│ │ │ │ │ │ └── _types.cpython-312.pyc
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _re.py
│ │ │ │ │ ├── _types.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── truststore
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _api.cpython-312.pyc
│ │ │ │ │ │ ├── _macos.cpython-312.pyc
│ │ │ │ │ │ ├── _openssl.cpython-312.pyc
│ │ │ │ │ │ ├── _ssl_constants.cpython-312.pyc
│ │ │ │ │ │ └── _windows.cpython-312.pyc
│ │ │ │ │ ├── _api.py
│ │ │ │ │ ├── _macos.py
│ │ │ │ │ ├── _openssl.py
│ │ │ │ │ ├── _ssl_constants.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── typing_extensions.py
│ │ │ │ ├── urllib3
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── _collections.py
│ │ │ │ │ ├── _version.py
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── connectionpool.py
│ │ │ │ │ ├── contrib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _appengine_environ.cpython-312.pyc
│ │ │ │ │ │ │ ├── appengine.cpython-312.pyc
│ │ │ │ │ │ │ ├── ntlmpool.cpython-312.pyc
│ │ │ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ │ │ ├── securetransport.cpython-312.pyc
│ │ │ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ │ │ ├── _appengine_environ.py
│ │ │ │ │ │ ├── _securetransport
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── bindings.cpython-312.pyc
│ │ │ │ │ │ │ │ └── low_level.cpython-312.pyc
│ │ │ │ │ │ │ ├── bindings.py
│ │ │ │ │ │ │ └── low_level.py
│ │ │ │ │ │ ├── appengine.py
│ │ │ │ │ │ ├── ntlmpool.py
│ │ │ │ │ │ ├── pyopenssl.py
│ │ │ │ │ │ ├── securetransport.py
│ │ │ │ │ │ └── socks.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── fields.py
│ │ │ │ │ ├── filepost.py
│ │ │ │ │ ├── packages
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── six.cpython-312.pyc
│ │ │ │ │ │ ├── backports
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── makefile.cpython-312.pyc
│ │ │ │ │ │ │ │ └── weakref_finalize.cpython-312.pyc
│ │ │ │ │ │ │ ├── makefile.py
│ │ │ │ │ │ │ └── weakref_finalize.py
│ │ │ │ │ │ └── six.py
│ │ │ │ │ ├── poolmanager.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ └── util
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ │ │ ├── queue.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ │ │ └── wait.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── proxy.py
│ │ │ │ │ ├── queue.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── ssl_.py
│ │ │ │ │ ├── ssl_match_hostname.py
│ │ │ │ │ ├── ssltransport.py
│ │ │ │ │ ├── timeout.py
│ │ │ │ │ ├── url.py
│ │ │ │ │ └── wait.py
│ │ │ │ └── vendor.txt
│ │ │ └── py.typed
│ │ ├── pip-24.2.dist-info
│ │ │ ├── AUTHORS.txt
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── requests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── __version__.py
│ │ │ ├── _internal_utils.py
│ │ │ ├── adapters.py
│ │ │ ├── api.py
│ │ │ ├── auth.py
│ │ │ ├── certs.py
│ │ │ ├── compat.py
│ │ │ ├── cookies.py
│ │ │ ├── exceptions.py
│ │ │ ├── help.py
│ │ │ ├── hooks.py
│ │ │ ├── models.py
│ │ │ ├── packages.py
│ │ │ ├── sessions.py
│ │ │ ├── status_codes.py
│ │ │ ├── structures.py
│ │ │ └── utils.py
│ │ ├── requests-2.32.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── soupsieve
│ │ │ ├── __init__.py
│ │ │ ├── __meta__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __meta__.cpython-312.pyc
│ │ │ │ ├── css_match.cpython-312.pyc
│ │ │ │ ├── css_parser.cpython-312.pyc
│ │ │ │ ├── css_types.cpython-312.pyc
│ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ └── util.cpython-312.pyc
│ │ │ ├── css_match.py
│ │ │ ├── css_parser.py
│ │ │ ├── css_types.py
│ │ │ ├── pretty.py
│ │ │ ├── py.typed
│ │ │ └── util.py
│ │ ├── soupsieve-2.6.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── urllib3
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _base_connection.cpython-312.pyc
│ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ ├── _request_methods.cpython-312.pyc
│ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ └── response.cpython-312.pyc
│ │ │ ├── _base_connection.py
│ │ │ ├── _collections.py
│ │ │ ├── _request_methods.py
│ │ │ ├── _version.py
│ │ │ ├── connection.py
│ │ │ ├── connectionpool.py
│ │ │ ├── contrib
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ ├── emscripten
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── fetch.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── emscripten_fetch_worker.js
│ │ │ │ │ ├── fetch.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ └── response.py
│ │ │ │ ├── pyopenssl.py
│ │ │ │ └── socks.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── filepost.py
│ │ │ ├── http2
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ └── probe.cpython-312.pyc
│ │ │ │ ├── connection.py
│ │ │ │ └── probe.py
│ │ │ ├── poolmanager.py
│ │ │ ├── py.typed
│ │ │ ├── response.py
│ │ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ └── wait.cpython-312.pyc
│ │ │ ├── connection.py
│ │ │ ├── proxy.py
│ │ │ ├── request.py
│ │ │ ├── response.py
│ │ │ ├── retry.py
│ │ │ ├── ssl_.py
│ │ │ ├── ssl_match_hostname.py
│ │ │ ├── ssltransport.py
│ │ │ ├── timeout.py
│ │ │ ├── url.py
│ │ │ ├── util.py
│ │ │ └── wait.py
│ │ ├── urllib3-2.2.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── useragent
│ │ │ ├── __init__.py
│ │ │ ├── __init__.pyc
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── resources
│ │ │ │ └── user_agent_data.json
│ │ │ └── test
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── test_additional_os.json
│ │ │ ├── test_browser.json
│ │ │ ├── test_device.json
│ │ │ ├── test_firefox.json
│ │ │ ├── test_os.json
│ │ │ └── test_pgts_browser.json
│ │ ├── useragent-0.1.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── werkzeug
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _internal.cpython-312.pyc
│ │ │ │ ├── _reloader.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formparser.cpython-312.pyc
│ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ ├── local.cpython-312.pyc
│ │ │ │ ├── security.cpython-312.pyc
│ │ │ │ ├── serving.cpython-312.pyc
│ │ │ │ ├── test.cpython-312.pyc
│ │ │ │ ├── testapp.cpython-312.pyc
│ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ ├── user_agent.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── wsgi.cpython-312.pyc
│ │ │ ├── _internal.py
│ │ │ ├── _reloader.py
│ │ │ ├── datastructures
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── accept.cpython-312.pyc
│ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ ├── cache_control.cpython-312.pyc
│ │ │ │ │ ├── csp.cpython-312.pyc
│ │ │ │ │ ├── etag.cpython-312.pyc
│ │ │ │ │ ├── file_storage.cpython-312.pyc
│ │ │ │ │ ├── headers.cpython-312.pyc
│ │ │ │ │ ├── mixins.cpython-312.pyc
│ │ │ │ │ ├── range.cpython-312.pyc
│ │ │ │ │ └── structures.cpython-312.pyc
│ │ │ │ ├── accept.py
│ │ │ │ ├── accept.pyi
│ │ │ │ ├── auth.py
│ │ │ │ ├── cache_control.py
│ │ │ │ ├── cache_control.pyi
│ │ │ │ ├── csp.py
│ │ │ │ ├── csp.pyi
│ │ │ │ ├── etag.py
│ │ │ │ ├── etag.pyi
│ │ │ │ ├── file_storage.py
│ │ │ │ ├── file_storage.pyi
│ │ │ │ ├── headers.py
│ │ │ │ ├── headers.pyi
│ │ │ │ ├── mixins.py
│ │ │ │ ├── mixins.pyi
│ │ │ │ ├── range.py
│ │ │ │ ├── range.pyi
│ │ │ │ ├── structures.py
│ │ │ │ └── structures.pyi
│ │ │ ├── debug
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ └── tbtools.cpython-312.pyc
│ │ │ │ ├── console.py
│ │ │ │ ├── repr.py
│ │ │ │ ├── shared
│ │ │ │ │ ├── console.png
│ │ │ │ │ ├── debugger.js
│ │ │ │ │ ├── ICON_LICENSE.md
│ │ │ │ │ ├── less.png
│ │ │ │ │ ├── more.png
│ │ │ │ │ └── style.css
│ │ │ │ └── tbtools.py
│ │ │ ├── exceptions.py
│ │ │ ├── formparser.py
│ │ │ ├── http.py
│ │ │ ├── local.py
│ │ │ ├── middleware
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── dispatcher.cpython-312.pyc
│ │ │ │ │ ├── http_proxy.cpython-312.pyc
│ │ │ │ │ ├── lint.cpython-312.pyc
│ │ │ │ │ ├── profiler.cpython-312.pyc
│ │ │ │ │ ├── proxy_fix.cpython-312.pyc
│ │ │ │ │ └── shared_data.cpython-312.pyc
│ │ │ │ ├── dispatcher.py
│ │ │ │ ├── http_proxy.py
│ │ │ │ ├── lint.py
│ │ │ │ ├── profiler.py
│ │ │ │ ├── proxy_fix.py
│ │ │ │ └── shared_data.py
│ │ │ ├── py.typed
│ │ │ ├── routing
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── converters.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── map.cpython-312.pyc
│ │ │ │ │ ├── matcher.cpython-312.pyc
│ │ │ │ │ └── rules.cpython-312.pyc
│ │ │ │ ├── converters.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── map.py
│ │ │ │ ├── matcher.py
│ │ │ │ └── rules.py
│ │ │ ├── sansio
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ │ ├── multipart.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ ├── http.py
│ │ │ │ ├── multipart.py
│ │ │ │ ├── request.py
│ │ │ │ ├── response.py
│ │ │ │ └── utils.py
│ │ │ ├── security.py
│ │ │ ├── serving.py
│ │ │ ├── test.py
│ │ │ ├── testapp.py
│ │ │ ├── urls.py
│ │ │ ├── user_agent.py
│ │ │ ├── utils.py
│ │ │ ├── wrappers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ ├── request.py
│ │ │ │ └── response.py
│ │ │ └── wsgi.py
│ │ └── werkzeug-3.0.4.dist-info
│ │ ├── INSTALLER
│ │ ├── LICENSE.txt
│ │ ├── METADATA
│ │ ├── RECORD
│ │ └── WHEEL
│ ├── pyvenv.cfg
│ ├── static
│ │ └── styles.css
│ ├── templates
│ │ └── index.html
│ └── test.py
├── cline_config.json
├── mcp_server.py
├── README.md
├── search_results.json
├── settings.json
└── test_files
├── text1.txt
└── text2.txt
```
# Files
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/werkzeug/sansio/multipart.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import re
4 | import typing as t
5 | from dataclasses import dataclass
6 | from enum import auto
7 | from enum import Enum
8 |
9 | from ..datastructures import Headers
10 | from ..exceptions import RequestEntityTooLarge
11 | from ..http import parse_options_header
12 |
13 |
14 | class Event:
15 | pass
16 |
17 |
18 | @dataclass(frozen=True)
19 | class Preamble(Event):
20 | data: bytes
21 |
22 |
23 | @dataclass(frozen=True)
24 | class Field(Event):
25 | name: str
26 | headers: Headers
27 |
28 |
29 | @dataclass(frozen=True)
30 | class File(Event):
31 | name: str
32 | filename: str
33 | headers: Headers
34 |
35 |
36 | @dataclass(frozen=True)
37 | class Data(Event):
38 | data: bytes
39 | more_data: bool
40 |
41 |
42 | @dataclass(frozen=True)
43 | class Epilogue(Event):
44 | data: bytes
45 |
46 |
47 | class NeedData(Event):
48 | pass
49 |
50 |
51 | NEED_DATA = NeedData()
52 |
53 |
54 | class State(Enum):
55 | PREAMBLE = auto()
56 | PART = auto()
57 | DATA = auto()
58 | DATA_START = auto()
59 | EPILOGUE = auto()
60 | COMPLETE = auto()
61 |
62 |
63 | # Multipart line breaks MUST be CRLF (\r\n) by RFC-7578, except that
64 | # many implementations break this and either use CR or LF alone.
65 | LINE_BREAK = b"(?:\r\n|\n|\r)"
66 | BLANK_LINE_RE = re.compile(b"(?:\r\n\r\n|\r\r|\n\n)", re.MULTILINE)
67 | LINE_BREAK_RE = re.compile(LINE_BREAK, re.MULTILINE)
68 | # Header values can be continued via a space or tab after the linebreak, as
69 | # per RFC2231
70 | HEADER_CONTINUATION_RE = re.compile(b"%s[ \t]" % LINE_BREAK, re.MULTILINE)
71 | # This must be long enough to contain any line breaks plus any
72 | # additional boundary markers (--) such that they will be found in a
73 | # subsequent search
74 | SEARCH_EXTRA_LENGTH = 8
75 |
76 |
77 | class MultipartDecoder:
78 | """Decodes a multipart message as bytes into Python events.
79 |
80 | The part data is returned as available to allow the caller to save
81 | the data from memory to disk, if desired.
82 | """
83 |
84 | def __init__(
85 | self,
86 | boundary: bytes,
87 | max_form_memory_size: int | None = None,
88 | *,
89 | max_parts: int | None = None,
90 | ) -> None:
91 | self.buffer = bytearray()
92 | self.complete = False
93 | self.max_form_memory_size = max_form_memory_size
94 | self.max_parts = max_parts
95 | self.state = State.PREAMBLE
96 | self.boundary = boundary
97 |
98 | # Note in the below \h i.e. horizontal whitespace is used
99 | # as [^\S\n\r] as \h isn't supported in python.
100 |
101 | # The preamble must end with a boundary where the boundary is
102 | # prefixed by a line break, RFC2046. Except that many
103 | # implementations including Werkzeug's tests omit the line
104 | # break prefix. In addition the first boundary could be the
105 | # epilogue boundary (for empty form-data) hence the matching
106 | # group to understand if it is an epilogue boundary.
107 | self.preamble_re = re.compile(
108 | rb"%s?--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)"
109 | % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK),
110 | re.MULTILINE,
111 | )
112 | # A boundary must include a line break prefix and suffix, and
113 | # may include trailing whitespace. In addition the boundary
114 | # could be the epilogue boundary hence the matching group to
115 | # understand if it is an epilogue boundary.
116 | self.boundary_re = re.compile(
117 | rb"%s--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)"
118 | % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK),
119 | re.MULTILINE,
120 | )
121 | self._search_position = 0
122 | self._parts_decoded = 0
123 |
124 | def last_newline(self, data: bytes) -> int:
125 | try:
126 | last_nl = data.rindex(b"\n")
127 | except ValueError:
128 | last_nl = len(data)
129 | try:
130 | last_cr = data.rindex(b"\r")
131 | except ValueError:
132 | last_cr = len(data)
133 |
134 | return min(last_nl, last_cr)
135 |
136 | def receive_data(self, data: bytes | None) -> None:
137 | if data is None:
138 | self.complete = True
139 | elif (
140 | self.max_form_memory_size is not None
141 | and len(self.buffer) + len(data) > self.max_form_memory_size
142 | ):
143 | raise RequestEntityTooLarge()
144 | else:
145 | self.buffer.extend(data)
146 |
147 | def next_event(self) -> Event:
148 | event: Event = NEED_DATA
149 |
150 | if self.state == State.PREAMBLE:
151 | match = self.preamble_re.search(self.buffer, self._search_position)
152 | if match is not None:
153 | if match.group(1).startswith(b"--"):
154 | self.state = State.EPILOGUE
155 | else:
156 | self.state = State.PART
157 | data = bytes(self.buffer[: match.start()])
158 | del self.buffer[: match.end()]
159 | event = Preamble(data=data)
160 | self._search_position = 0
161 | else:
162 | # Update the search start position to be equal to the
163 | # current buffer length (already searched) minus a
164 | # safe buffer for part of the search target.
165 | self._search_position = max(
166 | 0, len(self.buffer) - len(self.boundary) - SEARCH_EXTRA_LENGTH
167 | )
168 |
169 | elif self.state == State.PART:
170 | match = BLANK_LINE_RE.search(self.buffer, self._search_position)
171 | if match is not None:
172 | headers = self._parse_headers(self.buffer[: match.start()])
173 | # The final header ends with a single CRLF, however a
174 | # blank line indicates the start of the
175 | # body. Therefore the end is after the first CRLF.
176 | headers_end = (match.start() + match.end()) // 2
177 | del self.buffer[:headers_end]
178 |
179 | if "content-disposition" not in headers:
180 | raise ValueError("Missing Content-Disposition header")
181 |
182 | disposition, extra = parse_options_header(
183 | headers["content-disposition"]
184 | )
185 | name = t.cast(str, extra.get("name"))
186 | filename = extra.get("filename")
187 | if filename is not None:
188 | event = File(
189 | filename=filename,
190 | headers=headers,
191 | name=name,
192 | )
193 | else:
194 | event = Field(
195 | headers=headers,
196 | name=name,
197 | )
198 | self.state = State.DATA_START
199 | self._search_position = 0
200 | self._parts_decoded += 1
201 |
202 | if self.max_parts is not None and self._parts_decoded > self.max_parts:
203 | raise RequestEntityTooLarge()
204 | else:
205 | # Update the search start position to be equal to the
206 | # current buffer length (already searched) minus a
207 | # safe buffer for part of the search target.
208 | self._search_position = max(0, len(self.buffer) - SEARCH_EXTRA_LENGTH)
209 |
210 | elif self.state == State.DATA_START:
211 | data, del_index, more_data = self._parse_data(self.buffer, start=True)
212 | del self.buffer[:del_index]
213 | event = Data(data=data, more_data=more_data)
214 | if more_data:
215 | self.state = State.DATA
216 |
217 | elif self.state == State.DATA:
218 | data, del_index, more_data = self._parse_data(self.buffer, start=False)
219 | del self.buffer[:del_index]
220 | if data or not more_data:
221 | event = Data(data=data, more_data=more_data)
222 |
223 | elif self.state == State.EPILOGUE and self.complete:
224 | event = Epilogue(data=bytes(self.buffer))
225 | del self.buffer[:]
226 | self.state = State.COMPLETE
227 |
228 | if self.complete and isinstance(event, NeedData):
229 | raise ValueError(f"Invalid form-data cannot parse beyond {self.state}")
230 |
231 | return event
232 |
233 | def _parse_headers(self, data: bytes) -> Headers:
234 | headers: list[tuple[str, str]] = []
235 | # Merge the continued headers into one line
236 | data = HEADER_CONTINUATION_RE.sub(b" ", data)
237 | # Now there is one header per line
238 | for line in data.splitlines():
239 | line = line.strip()
240 |
241 | if line != b"":
242 | name, _, value = line.decode().partition(":")
243 | headers.append((name.strip(), value.strip()))
244 | return Headers(headers)
245 |
246 | def _parse_data(self, data: bytes, *, start: bool) -> tuple[bytes, int, bool]:
247 | # Body parts must start with CRLF (or CR or LF)
248 | if start:
249 | match = LINE_BREAK_RE.match(data)
250 | data_start = t.cast(t.Match[bytes], match).end()
251 | else:
252 | data_start = 0
253 |
254 | boundary = b"--" + self.boundary
255 |
256 | if self.buffer.find(boundary) == -1:
257 | # No complete boundary in the buffer, but there may be
258 | # a partial boundary at the end. As the boundary
259 | # starts with either a nl or cr find the earliest and
260 | # return up to that as data.
261 | data_end = del_index = self.last_newline(data[data_start:]) + data_start
262 | # If amount of data after last newline is far from
263 | # possible length of partial boundary, we should
264 | # assume that there is no partial boundary in the buffer
265 | # and return all pending data.
266 | if (len(data) - data_end) > len(b"\n" + boundary):
267 | data_end = del_index = len(data)
268 | more_data = True
269 | else:
270 | match = self.boundary_re.search(data)
271 | if match is not None:
272 | if match.group(1).startswith(b"--"):
273 | self.state = State.EPILOGUE
274 | else:
275 | self.state = State.PART
276 | data_end = match.start()
277 | del_index = match.end()
278 | else:
279 | data_end = del_index = self.last_newline(data[data_start:]) + data_start
280 | more_data = match is None
281 |
282 | return bytes(data[data_start:data_end]), del_index, more_data
283 |
284 |
285 | class MultipartEncoder:
286 | def __init__(self, boundary: bytes) -> None:
287 | self.boundary = boundary
288 | self.state = State.PREAMBLE
289 |
290 | def send_event(self, event: Event) -> bytes:
291 | if isinstance(event, Preamble) and self.state == State.PREAMBLE:
292 | self.state = State.PART
293 | return event.data
294 | elif isinstance(event, (Field, File)) and self.state in {
295 | State.PREAMBLE,
296 | State.PART,
297 | State.DATA,
298 | }:
299 | data = b"\r\n--" + self.boundary + b"\r\n"
300 | data += b'Content-Disposition: form-data; name="%s"' % event.name.encode()
301 | if isinstance(event, File):
302 | data += b'; filename="%s"' % event.filename.encode()
303 | data += b"\r\n"
304 | for name, value in t.cast(Field, event).headers:
305 | if name.lower() != "content-disposition":
306 | data += f"{name}: {value}\r\n".encode()
307 | self.state = State.DATA_START
308 | return data
309 | elif isinstance(event, Data) and self.state == State.DATA_START:
310 | self.state = State.DATA
311 | if len(event.data) > 0:
312 | return b"\r\n" + event.data
313 | else:
314 | return event.data
315 | elif isinstance(event, Data) and self.state == State.DATA:
316 | return event.data
317 | elif isinstance(event, Epilogue):
318 | self.state = State.COMPLETE
319 | return b"\r\n--" + self.boundary + b"--\r\n" + event.data
320 | else:
321 | raise ValueError(f"Cannot generate {event} in state: {self.state}")
322 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/utils/logging.py:
--------------------------------------------------------------------------------
```python
1 | import contextlib
2 | import errno
3 | import logging
4 | import logging.handlers
5 | import os
6 | import sys
7 | import threading
8 | from dataclasses import dataclass
9 | from io import TextIOWrapper
10 | from logging import Filter
11 | from typing import Any, ClassVar, Generator, List, Optional, TextIO, Type
12 |
13 | from pip._vendor.rich.console import (
14 | Console,
15 | ConsoleOptions,
16 | ConsoleRenderable,
17 | RenderableType,
18 | RenderResult,
19 | RichCast,
20 | )
21 | from pip._vendor.rich.highlighter import NullHighlighter
22 | from pip._vendor.rich.logging import RichHandler
23 | from pip._vendor.rich.segment import Segment
24 | from pip._vendor.rich.style import Style
25 |
26 | from pip._internal.utils._log import VERBOSE, getLogger
27 | from pip._internal.utils.compat import WINDOWS
28 | from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
29 | from pip._internal.utils.misc import ensure_dir
30 |
31 | _log_state = threading.local()
32 | subprocess_logger = getLogger("pip.subprocessor")
33 |
34 |
35 | class BrokenStdoutLoggingError(Exception):
36 | """
37 | Raised if BrokenPipeError occurs for the stdout stream while logging.
38 | """
39 |
40 |
41 | def _is_broken_pipe_error(exc_class: Type[BaseException], exc: BaseException) -> bool:
42 | if exc_class is BrokenPipeError:
43 | return True
44 |
45 | # On Windows, a broken pipe can show up as EINVAL rather than EPIPE:
46 | # https://bugs.python.org/issue19612
47 | # https://bugs.python.org/issue30418
48 | if not WINDOWS:
49 | return False
50 |
51 | return isinstance(exc, OSError) and exc.errno in (errno.EINVAL, errno.EPIPE)
52 |
53 |
54 | @contextlib.contextmanager
55 | def indent_log(num: int = 2) -> Generator[None, None, None]:
56 | """
57 | A context manager which will cause the log output to be indented for any
58 | log messages emitted inside it.
59 | """
60 | # For thread-safety
61 | _log_state.indentation = get_indentation()
62 | _log_state.indentation += num
63 | try:
64 | yield
65 | finally:
66 | _log_state.indentation -= num
67 |
68 |
69 | def get_indentation() -> int:
70 | return getattr(_log_state, "indentation", 0)
71 |
72 |
73 | class IndentingFormatter(logging.Formatter):
74 | default_time_format = "%Y-%m-%dT%H:%M:%S"
75 |
76 | def __init__(
77 | self,
78 | *args: Any,
79 | add_timestamp: bool = False,
80 | **kwargs: Any,
81 | ) -> None:
82 | """
83 | A logging.Formatter that obeys the indent_log() context manager.
84 |
85 | :param add_timestamp: A bool indicating output lines should be prefixed
86 | with their record's timestamp.
87 | """
88 | self.add_timestamp = add_timestamp
89 | super().__init__(*args, **kwargs)
90 |
91 | def get_message_start(self, formatted: str, levelno: int) -> str:
92 | """
93 | Return the start of the formatted log message (not counting the
94 | prefix to add to each line).
95 | """
96 | if levelno < logging.WARNING:
97 | return ""
98 | if formatted.startswith(DEPRECATION_MSG_PREFIX):
99 | # Then the message already has a prefix. We don't want it to
100 | # look like "WARNING: DEPRECATION: ...."
101 | return ""
102 | if levelno < logging.ERROR:
103 | return "WARNING: "
104 |
105 | return "ERROR: "
106 |
107 | def format(self, record: logging.LogRecord) -> str:
108 | """
109 | Calls the standard formatter, but will indent all of the log message
110 | lines by our current indentation level.
111 | """
112 | formatted = super().format(record)
113 | message_start = self.get_message_start(formatted, record.levelno)
114 | formatted = message_start + formatted
115 |
116 | prefix = ""
117 | if self.add_timestamp:
118 | prefix = f"{self.formatTime(record)} "
119 | prefix += " " * get_indentation()
120 | formatted = "".join([prefix + line for line in formatted.splitlines(True)])
121 | return formatted
122 |
123 |
124 | @dataclass
125 | class IndentedRenderable:
126 | renderable: RenderableType
127 | indent: int
128 |
129 | def __rich_console__(
130 | self, console: Console, options: ConsoleOptions
131 | ) -> RenderResult:
132 | segments = console.render(self.renderable, options)
133 | lines = Segment.split_lines(segments)
134 | for line in lines:
135 | yield Segment(" " * self.indent)
136 | yield from line
137 | yield Segment("\n")
138 |
139 |
140 | class RichPipStreamHandler(RichHandler):
141 | KEYWORDS: ClassVar[Optional[List[str]]] = []
142 |
143 | def __init__(self, stream: Optional[TextIO], no_color: bool) -> None:
144 | super().__init__(
145 | console=Console(file=stream, no_color=no_color, soft_wrap=True),
146 | show_time=False,
147 | show_level=False,
148 | show_path=False,
149 | highlighter=NullHighlighter(),
150 | )
151 |
152 | # Our custom override on Rich's logger, to make things work as we need them to.
153 | def emit(self, record: logging.LogRecord) -> None:
154 | style: Optional[Style] = None
155 |
156 | # If we are given a diagnostic error to present, present it with indentation.
157 | if getattr(record, "rich", False):
158 | assert isinstance(record.args, tuple)
159 | (rich_renderable,) = record.args
160 | assert isinstance(
161 | rich_renderable, (ConsoleRenderable, RichCast, str)
162 | ), f"{rich_renderable} is not rich-console-renderable"
163 |
164 | renderable: RenderableType = IndentedRenderable(
165 | rich_renderable, indent=get_indentation()
166 | )
167 | else:
168 | message = self.format(record)
169 | renderable = self.render_message(record, message)
170 | if record.levelno is not None:
171 | if record.levelno >= logging.ERROR:
172 | style = Style(color="red")
173 | elif record.levelno >= logging.WARNING:
174 | style = Style(color="yellow")
175 |
176 | try:
177 | self.console.print(renderable, overflow="ignore", crop=False, style=style)
178 | except Exception:
179 | self.handleError(record)
180 |
181 | def handleError(self, record: logging.LogRecord) -> None:
182 | """Called when logging is unable to log some output."""
183 |
184 | exc_class, exc = sys.exc_info()[:2]
185 | # If a broken pipe occurred while calling write() or flush() on the
186 | # stdout stream in logging's Handler.emit(), then raise our special
187 | # exception so we can handle it in main() instead of logging the
188 | # broken pipe error and continuing.
189 | if (
190 | exc_class
191 | and exc
192 | and self.console.file is sys.stdout
193 | and _is_broken_pipe_error(exc_class, exc)
194 | ):
195 | raise BrokenStdoutLoggingError()
196 |
197 | return super().handleError(record)
198 |
199 |
200 | class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler):
201 | def _open(self) -> TextIOWrapper:
202 | ensure_dir(os.path.dirname(self.baseFilename))
203 | return super()._open()
204 |
205 |
206 | class MaxLevelFilter(Filter):
207 | def __init__(self, level: int) -> None:
208 | self.level = level
209 |
210 | def filter(self, record: logging.LogRecord) -> bool:
211 | return record.levelno < self.level
212 |
213 |
214 | class ExcludeLoggerFilter(Filter):
215 | """
216 | A logging Filter that excludes records from a logger (or its children).
217 | """
218 |
219 | def filter(self, record: logging.LogRecord) -> bool:
220 | # The base Filter class allows only records from a logger (or its
221 | # children).
222 | return not super().filter(record)
223 |
224 |
225 | def setup_logging(verbosity: int, no_color: bool, user_log_file: Optional[str]) -> int:
226 | """Configures and sets up all of the logging
227 |
228 | Returns the requested logging level, as its integer value.
229 | """
230 |
231 | # Determine the level to be logging at.
232 | if verbosity >= 2:
233 | level_number = logging.DEBUG
234 | elif verbosity == 1:
235 | level_number = VERBOSE
236 | elif verbosity == -1:
237 | level_number = logging.WARNING
238 | elif verbosity == -2:
239 | level_number = logging.ERROR
240 | elif verbosity <= -3:
241 | level_number = logging.CRITICAL
242 | else:
243 | level_number = logging.INFO
244 |
245 | level = logging.getLevelName(level_number)
246 |
247 | # The "root" logger should match the "console" level *unless* we also need
248 | # to log to a user log file.
249 | include_user_log = user_log_file is not None
250 | if include_user_log:
251 | additional_log_file = user_log_file
252 | root_level = "DEBUG"
253 | else:
254 | additional_log_file = "/dev/null"
255 | root_level = level
256 |
257 | # Disable any logging besides WARNING unless we have DEBUG level logging
258 | # enabled for vendored libraries.
259 | vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG"
260 |
261 | # Shorthands for clarity
262 | log_streams = {
263 | "stdout": "ext://sys.stdout",
264 | "stderr": "ext://sys.stderr",
265 | }
266 | handler_classes = {
267 | "stream": "pip._internal.utils.logging.RichPipStreamHandler",
268 | "file": "pip._internal.utils.logging.BetterRotatingFileHandler",
269 | }
270 | handlers = ["console", "console_errors", "console_subprocess"] + (
271 | ["user_log"] if include_user_log else []
272 | )
273 |
274 | logging.config.dictConfig(
275 | {
276 | "version": 1,
277 | "disable_existing_loggers": False,
278 | "filters": {
279 | "exclude_warnings": {
280 | "()": "pip._internal.utils.logging.MaxLevelFilter",
281 | "level": logging.WARNING,
282 | },
283 | "restrict_to_subprocess": {
284 | "()": "logging.Filter",
285 | "name": subprocess_logger.name,
286 | },
287 | "exclude_subprocess": {
288 | "()": "pip._internal.utils.logging.ExcludeLoggerFilter",
289 | "name": subprocess_logger.name,
290 | },
291 | },
292 | "formatters": {
293 | "indent": {
294 | "()": IndentingFormatter,
295 | "format": "%(message)s",
296 | },
297 | "indent_with_timestamp": {
298 | "()": IndentingFormatter,
299 | "format": "%(message)s",
300 | "add_timestamp": True,
301 | },
302 | },
303 | "handlers": {
304 | "console": {
305 | "level": level,
306 | "class": handler_classes["stream"],
307 | "no_color": no_color,
308 | "stream": log_streams["stdout"],
309 | "filters": ["exclude_subprocess", "exclude_warnings"],
310 | "formatter": "indent",
311 | },
312 | "console_errors": {
313 | "level": "WARNING",
314 | "class": handler_classes["stream"],
315 | "no_color": no_color,
316 | "stream": log_streams["stderr"],
317 | "filters": ["exclude_subprocess"],
318 | "formatter": "indent",
319 | },
320 | # A handler responsible for logging to the console messages
321 | # from the "subprocessor" logger.
322 | "console_subprocess": {
323 | "level": level,
324 | "class": handler_classes["stream"],
325 | "stream": log_streams["stderr"],
326 | "no_color": no_color,
327 | "filters": ["restrict_to_subprocess"],
328 | "formatter": "indent",
329 | },
330 | "user_log": {
331 | "level": "DEBUG",
332 | "class": handler_classes["file"],
333 | "filename": additional_log_file,
334 | "encoding": "utf-8",
335 | "delay": True,
336 | "formatter": "indent_with_timestamp",
337 | },
338 | },
339 | "root": {
340 | "level": root_level,
341 | "handlers": handlers,
342 | },
343 | "loggers": {"pip._vendor": {"level": vendored_log_level}},
344 | }
345 | )
346 |
347 | return level_number
348 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py:
--------------------------------------------------------------------------------
```python
1 | import logging
2 | import os
3 | import re
4 | from typing import List, Optional, Tuple
5 |
6 | from pip._internal.utils.misc import (
7 | HiddenText,
8 | display_path,
9 | is_console_interactive,
10 | is_installable_dir,
11 | split_auth_from_netloc,
12 | )
13 | from pip._internal.utils.subprocess import CommandArgs, make_command
14 | from pip._internal.vcs.versioncontrol import (
15 | AuthInfo,
16 | RemoteNotFoundError,
17 | RevOptions,
18 | VersionControl,
19 | vcs,
20 | )
21 |
22 | logger = logging.getLogger(__name__)
23 |
24 | _svn_xml_url_re = re.compile('url="([^"]+)"')
25 | _svn_rev_re = re.compile(r'committed-rev="(\d+)"')
26 | _svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"')
27 | _svn_info_xml_url_re = re.compile(r"<url>(.*)</url>")
28 |
29 |
30 | class Subversion(VersionControl):
31 | name = "svn"
32 | dirname = ".svn"
33 | repo_name = "checkout"
34 | schemes = ("svn+ssh", "svn+http", "svn+https", "svn+svn", "svn+file")
35 |
36 | @classmethod
37 | def should_add_vcs_url_prefix(cls, remote_url: str) -> bool:
38 | return True
39 |
40 | @staticmethod
41 | def get_base_rev_args(rev: str) -> List[str]:
42 | return ["-r", rev]
43 |
44 | @classmethod
45 | def get_revision(cls, location: str) -> str:
46 | """
47 | Return the maximum revision for all files under a given location
48 | """
49 | # Note: taken from setuptools.command.egg_info
50 | revision = 0
51 |
52 | for base, dirs, _ in os.walk(location):
53 | if cls.dirname not in dirs:
54 | dirs[:] = []
55 | continue # no sense walking uncontrolled subdirs
56 | dirs.remove(cls.dirname)
57 | entries_fn = os.path.join(base, cls.dirname, "entries")
58 | if not os.path.exists(entries_fn):
59 | # FIXME: should we warn?
60 | continue
61 |
62 | dirurl, localrev = cls._get_svn_url_rev(base)
63 |
64 | if base == location:
65 | assert dirurl is not None
66 | base = dirurl + "/" # save the root url
67 | elif not dirurl or not dirurl.startswith(base):
68 | dirs[:] = []
69 | continue # not part of the same svn tree, skip it
70 | revision = max(revision, localrev)
71 | return str(revision)
72 |
73 | @classmethod
74 | def get_netloc_and_auth(
75 | cls, netloc: str, scheme: str
76 | ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]:
77 | """
78 | This override allows the auth information to be passed to svn via the
79 | --username and --password options instead of via the URL.
80 | """
81 | if scheme == "ssh":
82 | # The --username and --password options can't be used for
83 | # svn+ssh URLs, so keep the auth information in the URL.
84 | return super().get_netloc_and_auth(netloc, scheme)
85 |
86 | return split_auth_from_netloc(netloc)
87 |
88 | @classmethod
89 | def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]:
90 | # hotfix the URL scheme after removing svn+ from svn+ssh:// re-add it
91 | url, rev, user_pass = super().get_url_rev_and_auth(url)
92 | if url.startswith("ssh://"):
93 | url = "svn+" + url
94 | return url, rev, user_pass
95 |
96 | @staticmethod
97 | def make_rev_args(
98 | username: Optional[str], password: Optional[HiddenText]
99 | ) -> CommandArgs:
100 | extra_args: CommandArgs = []
101 | if username:
102 | extra_args += ["--username", username]
103 | if password:
104 | extra_args += ["--password", password]
105 |
106 | return extra_args
107 |
108 | @classmethod
109 | def get_remote_url(cls, location: str) -> str:
110 | # In cases where the source is in a subdirectory, we have to look up in
111 | # the location until we find a valid project root.
112 | orig_location = location
113 | while not is_installable_dir(location):
114 | last_location = location
115 | location = os.path.dirname(location)
116 | if location == last_location:
117 | # We've traversed up to the root of the filesystem without
118 | # finding a Python project.
119 | logger.warning(
120 | "Could not find Python project for directory %s (tried all "
121 | "parent directories)",
122 | orig_location,
123 | )
124 | raise RemoteNotFoundError
125 |
126 | url, _rev = cls._get_svn_url_rev(location)
127 | if url is None:
128 | raise RemoteNotFoundError
129 |
130 | return url
131 |
132 | @classmethod
133 | def _get_svn_url_rev(cls, location: str) -> Tuple[Optional[str], int]:
134 | from pip._internal.exceptions import InstallationError
135 |
136 | entries_path = os.path.join(location, cls.dirname, "entries")
137 | if os.path.exists(entries_path):
138 | with open(entries_path) as f:
139 | data = f.read()
140 | else: # subversion >= 1.7 does not have the 'entries' file
141 | data = ""
142 |
143 | url = None
144 | if data.startswith("8") or data.startswith("9") or data.startswith("10"):
145 | entries = list(map(str.splitlines, data.split("\n\x0c\n")))
146 | del entries[0][0] # get rid of the '8'
147 | url = entries[0][3]
148 | revs = [int(d[9]) for d in entries if len(d) > 9 and d[9]] + [0]
149 | elif data.startswith("<?xml"):
150 | match = _svn_xml_url_re.search(data)
151 | if not match:
152 | raise ValueError(f"Badly formatted data: {data!r}")
153 | url = match.group(1) # get repository URL
154 | revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0]
155 | else:
156 | try:
157 | # subversion >= 1.7
158 | # Note that using get_remote_call_options is not necessary here
159 | # because `svn info` is being run against a local directory.
160 | # We don't need to worry about making sure interactive mode
161 | # is being used to prompt for passwords, because passwords
162 | # are only potentially needed for remote server requests.
163 | xml = cls.run_command(
164 | ["info", "--xml", location],
165 | show_stdout=False,
166 | stdout_only=True,
167 | )
168 | match = _svn_info_xml_url_re.search(xml)
169 | assert match is not None
170 | url = match.group(1)
171 | revs = [int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml)]
172 | except InstallationError:
173 | url, revs = None, []
174 |
175 | if revs:
176 | rev = max(revs)
177 | else:
178 | rev = 0
179 |
180 | return url, rev
181 |
182 | @classmethod
183 | def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool:
184 | """Always assume the versions don't match"""
185 | return False
186 |
187 | def __init__(self, use_interactive: Optional[bool] = None) -> None:
188 | if use_interactive is None:
189 | use_interactive = is_console_interactive()
190 | self.use_interactive = use_interactive
191 |
192 | # This member is used to cache the fetched version of the current
193 | # ``svn`` client.
194 | # Special value definitions:
195 | # None: Not evaluated yet.
196 | # Empty tuple: Could not parse version.
197 | self._vcs_version: Optional[Tuple[int, ...]] = None
198 |
199 | super().__init__()
200 |
201 | def call_vcs_version(self) -> Tuple[int, ...]:
202 | """Query the version of the currently installed Subversion client.
203 |
204 | :return: A tuple containing the parts of the version information or
205 | ``()`` if the version returned from ``svn`` could not be parsed.
206 | :raises: BadCommand: If ``svn`` is not installed.
207 | """
208 | # Example versions:
209 | # svn, version 1.10.3 (r1842928)
210 | # compiled Feb 25 2019, 14:20:39 on x86_64-apple-darwin17.0.0
211 | # svn, version 1.7.14 (r1542130)
212 | # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu
213 | # svn, version 1.12.0-SlikSvn (SlikSvn/1.12.0)
214 | # compiled May 28 2019, 13:44:56 on x86_64-microsoft-windows6.2
215 | version_prefix = "svn, version "
216 | version = self.run_command(["--version"], show_stdout=False, stdout_only=True)
217 | if not version.startswith(version_prefix):
218 | return ()
219 |
220 | version = version[len(version_prefix) :].split()[0]
221 | version_list = version.partition("-")[0].split(".")
222 | try:
223 | parsed_version = tuple(map(int, version_list))
224 | except ValueError:
225 | return ()
226 |
227 | return parsed_version
228 |
229 | def get_vcs_version(self) -> Tuple[int, ...]:
230 | """Return the version of the currently installed Subversion client.
231 |
232 | If the version of the Subversion client has already been queried,
233 | a cached value will be used.
234 |
235 | :return: A tuple containing the parts of the version information or
236 | ``()`` if the version returned from ``svn`` could not be parsed.
237 | :raises: BadCommand: If ``svn`` is not installed.
238 | """
239 | if self._vcs_version is not None:
240 | # Use cached version, if available.
241 | # If parsing the version failed previously (empty tuple),
242 | # do not attempt to parse it again.
243 | return self._vcs_version
244 |
245 | vcs_version = self.call_vcs_version()
246 | self._vcs_version = vcs_version
247 | return vcs_version
248 |
249 | def get_remote_call_options(self) -> CommandArgs:
250 | """Return options to be used on calls to Subversion that contact the server.
251 |
252 | These options are applicable for the following ``svn`` subcommands used
253 | in this class.
254 |
255 | - checkout
256 | - switch
257 | - update
258 |
259 | :return: A list of command line arguments to pass to ``svn``.
260 | """
261 | if not self.use_interactive:
262 | # --non-interactive switch is available since Subversion 0.14.4.
263 | # Subversion < 1.8 runs in interactive mode by default.
264 | return ["--non-interactive"]
265 |
266 | svn_version = self.get_vcs_version()
267 | # By default, Subversion >= 1.8 runs in non-interactive mode if
268 | # stdin is not a TTY. Since that is how pip invokes SVN, in
269 | # call_subprocess(), pip must pass --force-interactive to ensure
270 | # the user can be prompted for a password, if required.
271 | # SVN added the --force-interactive option in SVN 1.8. Since
272 | # e.g. RHEL/CentOS 7, which is supported until 2024, ships with
273 | # SVN 1.7, pip should continue to support SVN 1.7. Therefore, pip
274 | # can't safely add the option if the SVN version is < 1.8 (or unknown).
275 | if svn_version >= (1, 8):
276 | return ["--force-interactive"]
277 |
278 | return []
279 |
280 | def fetch_new(
281 | self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int
282 | ) -> None:
283 | rev_display = rev_options.to_display()
284 | logger.info(
285 | "Checking out %s%s to %s",
286 | url,
287 | rev_display,
288 | display_path(dest),
289 | )
290 | if verbosity <= 0:
291 | flags = ["--quiet"]
292 | else:
293 | flags = []
294 | cmd_args = make_command(
295 | "checkout",
296 | *flags,
297 | self.get_remote_call_options(),
298 | rev_options.to_args(),
299 | url,
300 | dest,
301 | )
302 | self.run_command(cmd_args)
303 |
304 | def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
305 | cmd_args = make_command(
306 | "switch",
307 | self.get_remote_call_options(),
308 | rev_options.to_args(),
309 | url,
310 | dest,
311 | )
312 | self.run_command(cmd_args)
313 |
314 | def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None:
315 | cmd_args = make_command(
316 | "update",
317 | self.get_remote_call_options(),
318 | rev_options.to_args(),
319 | dest,
320 | )
321 | self.run_command(cmd_args)
322 |
323 |
324 | vcs.register(Subversion)
325 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | pygments.formatters.terminal256
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Formatter for 256-color terminal output with ANSI sequences.
6 |
7 | RGB-to-XTERM color conversion routines adapted from xterm256-conv
8 | tool (http://frexx.de/xterm-256-notes/data/xterm256-conv2.tar.bz2)
9 | by Wolfgang Frisch.
10 |
11 | Formatter version 1.
12 |
13 | :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
14 | :license: BSD, see LICENSE for details.
15 | """
16 |
17 | # TODO:
18 | # - Options to map style's bold/underline/italic/border attributes
19 | # to some ANSI attrbutes (something like 'italic=underline')
20 | # - An option to output "style RGB to xterm RGB/index" conversion table
21 | # - An option to indicate that we are running in "reverse background"
22 | # xterm. This means that default colors are white-on-black, not
23 | # black-on-while, so colors like "white background" need to be converted
24 | # to "white background, black foreground", etc...
25 |
26 | from pip._vendor.pygments.formatter import Formatter
27 | from pip._vendor.pygments.console import codes
28 | from pip._vendor.pygments.style import ansicolors
29 |
30 |
31 | __all__ = ['Terminal256Formatter', 'TerminalTrueColorFormatter']
32 |
33 |
34 | class EscapeSequence:
35 | def __init__(self, fg=None, bg=None, bold=False, underline=False, italic=False):
36 | self.fg = fg
37 | self.bg = bg
38 | self.bold = bold
39 | self.underline = underline
40 | self.italic = italic
41 |
42 | def escape(self, attrs):
43 | if len(attrs):
44 | return "\x1b[" + ";".join(attrs) + "m"
45 | return ""
46 |
47 | def color_string(self):
48 | attrs = []
49 | if self.fg is not None:
50 | if self.fg in ansicolors:
51 | esc = codes[self.fg.replace('ansi','')]
52 | if ';01m' in esc:
53 | self.bold = True
54 | # extract fg color code.
55 | attrs.append(esc[2:4])
56 | else:
57 | attrs.extend(("38", "5", "%i" % self.fg))
58 | if self.bg is not None:
59 | if self.bg in ansicolors:
60 | esc = codes[self.bg.replace('ansi','')]
61 | # extract fg color code, add 10 for bg.
62 | attrs.append(str(int(esc[2:4])+10))
63 | else:
64 | attrs.extend(("48", "5", "%i" % self.bg))
65 | if self.bold:
66 | attrs.append("01")
67 | if self.underline:
68 | attrs.append("04")
69 | if self.italic:
70 | attrs.append("03")
71 | return self.escape(attrs)
72 |
73 | def true_color_string(self):
74 | attrs = []
75 | if self.fg:
76 | attrs.extend(("38", "2", str(self.fg[0]), str(self.fg[1]), str(self.fg[2])))
77 | if self.bg:
78 | attrs.extend(("48", "2", str(self.bg[0]), str(self.bg[1]), str(self.bg[2])))
79 | if self.bold:
80 | attrs.append("01")
81 | if self.underline:
82 | attrs.append("04")
83 | if self.italic:
84 | attrs.append("03")
85 | return self.escape(attrs)
86 |
87 | def reset_string(self):
88 | attrs = []
89 | if self.fg is not None:
90 | attrs.append("39")
91 | if self.bg is not None:
92 | attrs.append("49")
93 | if self.bold or self.underline or self.italic:
94 | attrs.append("00")
95 | return self.escape(attrs)
96 |
97 |
98 | class Terminal256Formatter(Formatter):
99 | """
100 | Format tokens with ANSI color sequences, for output in a 256-color
101 | terminal or console. Like in `TerminalFormatter` color sequences
102 | are terminated at newlines, so that paging the output works correctly.
103 |
104 | The formatter takes colors from a style defined by the `style` option
105 | and converts them to nearest ANSI 256-color escape sequences. Bold and
106 | underline attributes from the style are preserved (and displayed).
107 |
108 | .. versionadded:: 0.9
109 |
110 | .. versionchanged:: 2.2
111 | If the used style defines foreground colors in the form ``#ansi*``, then
112 | `Terminal256Formatter` will map these to non extended foreground color.
113 | See :ref:`AnsiTerminalStyle` for more information.
114 |
115 | .. versionchanged:: 2.4
116 | The ANSI color names have been updated with names that are easier to
117 | understand and align with colornames of other projects and terminals.
118 | See :ref:`this table <new-ansi-color-names>` for more information.
119 |
120 |
121 | Options accepted:
122 |
123 | `style`
124 | The style to use, can be a string or a Style subclass (default:
125 | ``'default'``).
126 |
127 | `linenos`
128 | Set to ``True`` to have line numbers on the terminal output as well
129 | (default: ``False`` = no line numbers).
130 | """
131 | name = 'Terminal256'
132 | aliases = ['terminal256', 'console256', '256']
133 | filenames = []
134 |
135 | def __init__(self, **options):
136 | Formatter.__init__(self, **options)
137 |
138 | self.xterm_colors = []
139 | self.best_match = {}
140 | self.style_string = {}
141 |
142 | self.usebold = 'nobold' not in options
143 | self.useunderline = 'nounderline' not in options
144 | self.useitalic = 'noitalic' not in options
145 |
146 | self._build_color_table() # build an RGB-to-256 color conversion table
147 | self._setup_styles() # convert selected style's colors to term. colors
148 |
149 | self.linenos = options.get('linenos', False)
150 | self._lineno = 0
151 |
152 | def _build_color_table(self):
153 | # colors 0..15: 16 basic colors
154 |
155 | self.xterm_colors.append((0x00, 0x00, 0x00)) # 0
156 | self.xterm_colors.append((0xcd, 0x00, 0x00)) # 1
157 | self.xterm_colors.append((0x00, 0xcd, 0x00)) # 2
158 | self.xterm_colors.append((0xcd, 0xcd, 0x00)) # 3
159 | self.xterm_colors.append((0x00, 0x00, 0xee)) # 4
160 | self.xterm_colors.append((0xcd, 0x00, 0xcd)) # 5
161 | self.xterm_colors.append((0x00, 0xcd, 0xcd)) # 6
162 | self.xterm_colors.append((0xe5, 0xe5, 0xe5)) # 7
163 | self.xterm_colors.append((0x7f, 0x7f, 0x7f)) # 8
164 | self.xterm_colors.append((0xff, 0x00, 0x00)) # 9
165 | self.xterm_colors.append((0x00, 0xff, 0x00)) # 10
166 | self.xterm_colors.append((0xff, 0xff, 0x00)) # 11
167 | self.xterm_colors.append((0x5c, 0x5c, 0xff)) # 12
168 | self.xterm_colors.append((0xff, 0x00, 0xff)) # 13
169 | self.xterm_colors.append((0x00, 0xff, 0xff)) # 14
170 | self.xterm_colors.append((0xff, 0xff, 0xff)) # 15
171 |
172 | # colors 16..232: the 6x6x6 color cube
173 |
174 | valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
175 |
176 | for i in range(217):
177 | r = valuerange[(i // 36) % 6]
178 | g = valuerange[(i // 6) % 6]
179 | b = valuerange[i % 6]
180 | self.xterm_colors.append((r, g, b))
181 |
182 | # colors 233..253: grayscale
183 |
184 | for i in range(1, 22):
185 | v = 8 + i * 10
186 | self.xterm_colors.append((v, v, v))
187 |
188 | def _closest_color(self, r, g, b):
189 | distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff)
190 | match = 0
191 |
192 | for i in range(0, 254):
193 | values = self.xterm_colors[i]
194 |
195 | rd = r - values[0]
196 | gd = g - values[1]
197 | bd = b - values[2]
198 | d = rd*rd + gd*gd + bd*bd
199 |
200 | if d < distance:
201 | match = i
202 | distance = d
203 | return match
204 |
205 | def _color_index(self, color):
206 | index = self.best_match.get(color, None)
207 | if color in ansicolors:
208 | # strip the `ansi/#ansi` part and look up code
209 | index = color
210 | self.best_match[color] = index
211 | if index is None:
212 | try:
213 | rgb = int(str(color), 16)
214 | except ValueError:
215 | rgb = 0
216 |
217 | r = (rgb >> 16) & 0xff
218 | g = (rgb >> 8) & 0xff
219 | b = rgb & 0xff
220 | index = self._closest_color(r, g, b)
221 | self.best_match[color] = index
222 | return index
223 |
224 | def _setup_styles(self):
225 | for ttype, ndef in self.style:
226 | escape = EscapeSequence()
227 | # get foreground from ansicolor if set
228 | if ndef['ansicolor']:
229 | escape.fg = self._color_index(ndef['ansicolor'])
230 | elif ndef['color']:
231 | escape.fg = self._color_index(ndef['color'])
232 | if ndef['bgansicolor']:
233 | escape.bg = self._color_index(ndef['bgansicolor'])
234 | elif ndef['bgcolor']:
235 | escape.bg = self._color_index(ndef['bgcolor'])
236 | if self.usebold and ndef['bold']:
237 | escape.bold = True
238 | if self.useunderline and ndef['underline']:
239 | escape.underline = True
240 | if self.useitalic and ndef['italic']:
241 | escape.italic = True
242 | self.style_string[str(ttype)] = (escape.color_string(),
243 | escape.reset_string())
244 |
245 | def _write_lineno(self, outfile):
246 | self._lineno += 1
247 | outfile.write("%s%04d: " % (self._lineno != 1 and '\n' or '', self._lineno))
248 |
249 | def format(self, tokensource, outfile):
250 | return Formatter.format(self, tokensource, outfile)
251 |
252 | def format_unencoded(self, tokensource, outfile):
253 | if self.linenos:
254 | self._write_lineno(outfile)
255 |
256 | for ttype, value in tokensource:
257 | not_found = True
258 | while ttype and not_found:
259 | try:
260 | # outfile.write( "<" + str(ttype) + ">" )
261 | on, off = self.style_string[str(ttype)]
262 |
263 | # Like TerminalFormatter, add "reset colors" escape sequence
264 | # on newline.
265 | spl = value.split('\n')
266 | for line in spl[:-1]:
267 | if line:
268 | outfile.write(on + line + off)
269 | if self.linenos:
270 | self._write_lineno(outfile)
271 | else:
272 | outfile.write('\n')
273 |
274 | if spl[-1]:
275 | outfile.write(on + spl[-1] + off)
276 |
277 | not_found = False
278 | # outfile.write( '#' + str(ttype) + '#' )
279 |
280 | except KeyError:
281 | # ottype = ttype
282 | ttype = ttype.parent
283 | # outfile.write( '!' + str(ottype) + '->' + str(ttype) + '!' )
284 |
285 | if not_found:
286 | outfile.write(value)
287 |
288 | if self.linenos:
289 | outfile.write("\n")
290 |
291 |
292 |
293 | class TerminalTrueColorFormatter(Terminal256Formatter):
294 | r"""
295 | Format tokens with ANSI color sequences, for output in a true-color
296 | terminal or console. Like in `TerminalFormatter` color sequences
297 | are terminated at newlines, so that paging the output works correctly.
298 |
299 | .. versionadded:: 2.1
300 |
301 | Options accepted:
302 |
303 | `style`
304 | The style to use, can be a string or a Style subclass (default:
305 | ``'default'``).
306 | """
307 | name = 'TerminalTrueColor'
308 | aliases = ['terminal16m', 'console16m', '16m']
309 | filenames = []
310 |
311 | def _build_color_table(self):
312 | pass
313 |
314 | def _color_tuple(self, color):
315 | try:
316 | rgb = int(str(color), 16)
317 | except ValueError:
318 | return None
319 | r = (rgb >> 16) & 0xff
320 | g = (rgb >> 8) & 0xff
321 | b = rgb & 0xff
322 | return (r, g, b)
323 |
324 | def _setup_styles(self):
325 | for ttype, ndef in self.style:
326 | escape = EscapeSequence()
327 | if ndef['color']:
328 | escape.fg = self._color_tuple(ndef['color'])
329 | if ndef['bgcolor']:
330 | escape.bg = self._color_tuple(ndef['bgcolor'])
331 | if self.usebold and ndef['bold']:
332 | escape.bold = True
333 | if self.useunderline and ndef['underline']:
334 | escape.underline = True
335 | if self.useitalic and ndef['italic']:
336 | escape.italic = True
337 | self.style_string[str(ttype)] = (escape.true_color_string(),
338 | escape.reset_string())
339 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/wheel_builder.py:
--------------------------------------------------------------------------------
```python
1 | """Orchestrator for building wheels from InstallRequirements.
2 | """
3 |
4 | import logging
5 | import os.path
6 | import re
7 | import shutil
8 | from typing import Iterable, List, Optional, Tuple
9 |
10 | from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version
11 | from pip._vendor.packaging.version import InvalidVersion, Version
12 |
13 | from pip._internal.cache import WheelCache
14 | from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
15 | from pip._internal.metadata import FilesystemWheel, get_wheel_distribution
16 | from pip._internal.models.link import Link
17 | from pip._internal.models.wheel import Wheel
18 | from pip._internal.operations.build.wheel import build_wheel_pep517
19 | from pip._internal.operations.build.wheel_editable import build_wheel_editable
20 | from pip._internal.operations.build.wheel_legacy import build_wheel_legacy
21 | from pip._internal.req.req_install import InstallRequirement
22 | from pip._internal.utils.logging import indent_log
23 | from pip._internal.utils.misc import ensure_dir, hash_file
24 | from pip._internal.utils.setuptools_build import make_setuptools_clean_args
25 | from pip._internal.utils.subprocess import call_subprocess
26 | from pip._internal.utils.temp_dir import TempDirectory
27 | from pip._internal.utils.urls import path_to_url
28 | from pip._internal.vcs import vcs
29 |
30 | logger = logging.getLogger(__name__)
31 |
32 | _egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE)
33 |
34 | BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]]
35 |
36 |
37 | def _contains_egg_info(s: str) -> bool:
38 | """Determine whether the string looks like an egg_info.
39 |
40 | :param s: The string to parse. E.g. foo-2.1
41 | """
42 | return bool(_egg_info_re.search(s))
43 |
44 |
45 | def _should_build(
46 | req: InstallRequirement,
47 | need_wheel: bool,
48 | ) -> bool:
49 | """Return whether an InstallRequirement should be built into a wheel."""
50 | if req.constraint:
51 | # never build requirements that are merely constraints
52 | return False
53 | if req.is_wheel:
54 | if need_wheel:
55 | logger.info(
56 | "Skipping %s, due to already being wheel.",
57 | req.name,
58 | )
59 | return False
60 |
61 | if need_wheel:
62 | # i.e. pip wheel, not pip install
63 | return True
64 |
65 | # From this point, this concerns the pip install command only
66 | # (need_wheel=False).
67 |
68 | if not req.source_dir:
69 | return False
70 |
71 | if req.editable:
72 | # we only build PEP 660 editable requirements
73 | return req.supports_pyproject_editable
74 |
75 | return True
76 |
77 |
78 | def should_build_for_wheel_command(
79 | req: InstallRequirement,
80 | ) -> bool:
81 | return _should_build(req, need_wheel=True)
82 |
83 |
84 | def should_build_for_install_command(
85 | req: InstallRequirement,
86 | ) -> bool:
87 | return _should_build(req, need_wheel=False)
88 |
89 |
90 | def _should_cache(
91 | req: InstallRequirement,
92 | ) -> Optional[bool]:
93 | """
94 | Return whether a built InstallRequirement can be stored in the persistent
95 | wheel cache, assuming the wheel cache is available, and _should_build()
96 | has determined a wheel needs to be built.
97 | """
98 | if req.editable or not req.source_dir:
99 | # never cache editable requirements
100 | return False
101 |
102 | if req.link and req.link.is_vcs:
103 | # VCS checkout. Do not cache
104 | # unless it points to an immutable commit hash.
105 | assert not req.editable
106 | assert req.source_dir
107 | vcs_backend = vcs.get_backend_for_scheme(req.link.scheme)
108 | assert vcs_backend
109 | if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir):
110 | return True
111 | return False
112 |
113 | assert req.link
114 | base, ext = req.link.splitext()
115 | if _contains_egg_info(base):
116 | return True
117 |
118 | # Otherwise, do not cache.
119 | return False
120 |
121 |
122 | def _get_cache_dir(
123 | req: InstallRequirement,
124 | wheel_cache: WheelCache,
125 | ) -> str:
126 | """Return the persistent or temporary cache directory where the built
127 | wheel need to be stored.
128 | """
129 | cache_available = bool(wheel_cache.cache_dir)
130 | assert req.link
131 | if cache_available and _should_cache(req):
132 | cache_dir = wheel_cache.get_path_for_link(req.link)
133 | else:
134 | cache_dir = wheel_cache.get_ephem_path_for_link(req.link)
135 | return cache_dir
136 |
137 |
138 | def _verify_one(req: InstallRequirement, wheel_path: str) -> None:
139 | canonical_name = canonicalize_name(req.name or "")
140 | w = Wheel(os.path.basename(wheel_path))
141 | if canonicalize_name(w.name) != canonical_name:
142 | raise InvalidWheelFilename(
143 | f"Wheel has unexpected file name: expected {canonical_name!r}, "
144 | f"got {w.name!r}",
145 | )
146 | dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name)
147 | dist_verstr = str(dist.version)
148 | if canonicalize_version(dist_verstr) != canonicalize_version(w.version):
149 | raise InvalidWheelFilename(
150 | f"Wheel has unexpected file name: expected {dist_verstr!r}, "
151 | f"got {w.version!r}",
152 | )
153 | metadata_version_value = dist.metadata_version
154 | if metadata_version_value is None:
155 | raise UnsupportedWheel("Missing Metadata-Version")
156 | try:
157 | metadata_version = Version(metadata_version_value)
158 | except InvalidVersion:
159 | msg = f"Invalid Metadata-Version: {metadata_version_value}"
160 | raise UnsupportedWheel(msg)
161 | if metadata_version >= Version("1.2") and not isinstance(dist.version, Version):
162 | raise UnsupportedWheel(
163 | f"Metadata 1.2 mandates PEP 440 version, but {dist_verstr!r} is not"
164 | )
165 |
166 |
167 | def _build_one(
168 | req: InstallRequirement,
169 | output_dir: str,
170 | verify: bool,
171 | build_options: List[str],
172 | global_options: List[str],
173 | editable: bool,
174 | ) -> Optional[str]:
175 | """Build one wheel.
176 |
177 | :return: The filename of the built wheel, or None if the build failed.
178 | """
179 | artifact = "editable" if editable else "wheel"
180 | try:
181 | ensure_dir(output_dir)
182 | except OSError as e:
183 | logger.warning(
184 | "Building %s for %s failed: %s",
185 | artifact,
186 | req.name,
187 | e,
188 | )
189 | return None
190 |
191 | # Install build deps into temporary directory (PEP 518)
192 | with req.build_env:
193 | wheel_path = _build_one_inside_env(
194 | req, output_dir, build_options, global_options, editable
195 | )
196 | if wheel_path and verify:
197 | try:
198 | _verify_one(req, wheel_path)
199 | except (InvalidWheelFilename, UnsupportedWheel) as e:
200 | logger.warning("Built %s for %s is invalid: %s", artifact, req.name, e)
201 | return None
202 | return wheel_path
203 |
204 |
205 | def _build_one_inside_env(
206 | req: InstallRequirement,
207 | output_dir: str,
208 | build_options: List[str],
209 | global_options: List[str],
210 | editable: bool,
211 | ) -> Optional[str]:
212 | with TempDirectory(kind="wheel") as temp_dir:
213 | assert req.name
214 | if req.use_pep517:
215 | assert req.metadata_directory
216 | assert req.pep517_backend
217 | if global_options:
218 | logger.warning(
219 | "Ignoring --global-option when building %s using PEP 517", req.name
220 | )
221 | if build_options:
222 | logger.warning(
223 | "Ignoring --build-option when building %s using PEP 517", req.name
224 | )
225 | if editable:
226 | wheel_path = build_wheel_editable(
227 | name=req.name,
228 | backend=req.pep517_backend,
229 | metadata_directory=req.metadata_directory,
230 | tempd=temp_dir.path,
231 | )
232 | else:
233 | wheel_path = build_wheel_pep517(
234 | name=req.name,
235 | backend=req.pep517_backend,
236 | metadata_directory=req.metadata_directory,
237 | tempd=temp_dir.path,
238 | )
239 | else:
240 | wheel_path = build_wheel_legacy(
241 | name=req.name,
242 | setup_py_path=req.setup_py_path,
243 | source_dir=req.unpacked_source_directory,
244 | global_options=global_options,
245 | build_options=build_options,
246 | tempd=temp_dir.path,
247 | )
248 |
249 | if wheel_path is not None:
250 | wheel_name = os.path.basename(wheel_path)
251 | dest_path = os.path.join(output_dir, wheel_name)
252 | try:
253 | wheel_hash, length = hash_file(wheel_path)
254 | shutil.move(wheel_path, dest_path)
255 | logger.info(
256 | "Created wheel for %s: filename=%s size=%d sha256=%s",
257 | req.name,
258 | wheel_name,
259 | length,
260 | wheel_hash.hexdigest(),
261 | )
262 | logger.info("Stored in directory: %s", output_dir)
263 | return dest_path
264 | except Exception as e:
265 | logger.warning(
266 | "Building wheel for %s failed: %s",
267 | req.name,
268 | e,
269 | )
270 | # Ignore return, we can't do anything else useful.
271 | if not req.use_pep517:
272 | _clean_one_legacy(req, global_options)
273 | return None
274 |
275 |
276 | def _clean_one_legacy(req: InstallRequirement, global_options: List[str]) -> bool:
277 | clean_args = make_setuptools_clean_args(
278 | req.setup_py_path,
279 | global_options=global_options,
280 | )
281 |
282 | logger.info("Running setup.py clean for %s", req.name)
283 | try:
284 | call_subprocess(
285 | clean_args, command_desc="python setup.py clean", cwd=req.source_dir
286 | )
287 | return True
288 | except Exception:
289 | logger.error("Failed cleaning build dir for %s", req.name)
290 | return False
291 |
292 |
293 | def build(
294 | requirements: Iterable[InstallRequirement],
295 | wheel_cache: WheelCache,
296 | verify: bool,
297 | build_options: List[str],
298 | global_options: List[str],
299 | ) -> BuildResult:
300 | """Build wheels.
301 |
302 | :return: The list of InstallRequirement that succeeded to build and
303 | the list of InstallRequirement that failed to build.
304 | """
305 | if not requirements:
306 | return [], []
307 |
308 | # Build the wheels.
309 | logger.info(
310 | "Building wheels for collected packages: %s",
311 | ", ".join(req.name for req in requirements), # type: ignore
312 | )
313 |
314 | with indent_log():
315 | build_successes, build_failures = [], []
316 | for req in requirements:
317 | assert req.name
318 | cache_dir = _get_cache_dir(req, wheel_cache)
319 | wheel_file = _build_one(
320 | req,
321 | cache_dir,
322 | verify,
323 | build_options,
324 | global_options,
325 | req.editable and req.permit_editable_wheels,
326 | )
327 | if wheel_file:
328 | # Record the download origin in the cache
329 | if req.download_info is not None:
330 | # download_info is guaranteed to be set because when we build an
331 | # InstallRequirement it has been through the preparer before, but
332 | # let's be cautious.
333 | wheel_cache.record_download_origin(cache_dir, req.download_info)
334 | # Update the link for this.
335 | req.link = Link(path_to_url(wheel_file))
336 | req.local_file_path = req.link.file_path
337 | assert req.link.is_wheel
338 | build_successes.append(req)
339 | else:
340 | build_failures.append(req)
341 |
342 | # notify success/failure
343 | if build_successes:
344 | logger.info(
345 | "Successfully built %s",
346 | " ".join([req.name for req in build_successes]), # type: ignore
347 | )
348 | if build_failures:
349 | logger.info(
350 | "Failed to build %s",
351 | " ".join([req.name for req in build_failures]), # type: ignore
352 | )
353 | # Return a list of requirements that failed to build
354 | return build_successes, build_failures
355 |
```