This is page 81 of 168. Use http://codebase.md/romanshablio/mcp_server?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .DS_Store
├── .venv
│ ├── __pycache__
│ │ └── hello.cpython-312.pyc
│ ├── bin
│ │ ├── activate
│ │ ├── activate.csh
│ │ ├── activate.fish
│ │ ├── Activate.ps1
│ │ ├── flask
│ │ ├── normalizer
│ │ ├── pip
│ │ ├── pip3
│ │ ├── pip3.12
│ │ ├── python
│ │ ├── python3
│ │ └── python3.12
│ ├── hello.py
│ ├── lib
│ │ └── python3.12
│ │ └── site-packages
│ │ ├── beautifulsoup4-4.12.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ ├── AUTHORS
│ │ │ │ └── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── blinker
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _utilities.cpython-312.pyc
│ │ │ │ └── base.cpython-312.pyc
│ │ │ ├── _utilities.py
│ │ │ ├── base.py
│ │ │ └── py.typed
│ │ ├── blinker-1.8.2.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── bs4
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── css.cpython-312.pyc
│ │ │ │ ├── dammit.cpython-312.pyc
│ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ ├── element.cpython-312.pyc
│ │ │ │ └── formatter.cpython-312.pyc
│ │ │ ├── builder
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _html5lib.cpython-312.pyc
│ │ │ │ │ ├── _htmlparser.cpython-312.pyc
│ │ │ │ │ └── _lxml.cpython-312.pyc
│ │ │ │ ├── _html5lib.py
│ │ │ │ ├── _htmlparser.py
│ │ │ │ └── _lxml.py
│ │ │ ├── css.py
│ │ │ ├── dammit.py
│ │ │ ├── diagnose.py
│ │ │ ├── element.py
│ │ │ ├── formatter.py
│ │ │ └── tests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── test_builder_registry.cpython-312.pyc
│ │ │ │ ├── test_builder.cpython-312.pyc
│ │ │ │ ├── test_css.cpython-312.pyc
│ │ │ │ ├── test_dammit.cpython-312.pyc
│ │ │ │ ├── test_docs.cpython-312.pyc
│ │ │ │ ├── test_element.cpython-312.pyc
│ │ │ │ ├── test_formatter.cpython-312.pyc
│ │ │ │ ├── test_fuzz.cpython-312.pyc
│ │ │ │ ├── test_html5lib.cpython-312.pyc
│ │ │ │ ├── test_htmlparser.cpython-312.pyc
│ │ │ │ ├── test_lxml.cpython-312.pyc
│ │ │ │ ├── test_navigablestring.cpython-312.pyc
│ │ │ │ ├── test_pageelement.cpython-312.pyc
│ │ │ │ ├── test_soup.cpython-312.pyc
│ │ │ │ ├── test_tag.cpython-312.pyc
│ │ │ │ └── test_tree.cpython-312.pyc
│ │ │ ├── fuzz
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase
│ │ │ │ ├── crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase
│ │ │ │ └── crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase
│ │ │ ├── test_builder_registry.py
│ │ │ ├── test_builder.py
│ │ │ ├── test_css.py
│ │ │ ├── test_dammit.py
│ │ │ ├── test_docs.py
│ │ │ ├── test_element.py
│ │ │ ├── test_formatter.py
│ │ │ ├── test_fuzz.py
│ │ │ ├── test_html5lib.py
│ │ │ ├── test_htmlparser.py
│ │ │ ├── test_lxml.py
│ │ │ ├── test_navigablestring.py
│ │ │ ├── test_pageelement.py
│ │ │ ├── test_soup.py
│ │ │ ├── test_tag.py
│ │ │ └── test_tree.py
│ │ ├── certifi
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── core.cpython-312.pyc
│ │ │ ├── cacert.pem
│ │ │ ├── core.py
│ │ │ └── py.typed
│ │ ├── certifi-2024.8.30.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── charset_normalizer
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── cd.cpython-312.pyc
│ │ │ │ ├── constant.cpython-312.pyc
│ │ │ │ ├── legacy.cpython-312.pyc
│ │ │ │ ├── md.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── version.cpython-312.pyc
│ │ │ ├── api.py
│ │ │ ├── cd.py
│ │ │ ├── cli
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ └── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── __main__.cpython-312.pyc
│ │ │ ├── constant.py
│ │ │ ├── legacy.py
│ │ │ ├── md__mypyc.cpython-312-darwin.so
│ │ │ ├── md.cpython-312-darwin.so
│ │ │ ├── md.py
│ │ │ ├── models.py
│ │ │ ├── py.typed
│ │ │ ├── utils.py
│ │ │ └── version.py
│ │ ├── charset_normalizer-3.4.0.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── click
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ ├── _termui_impl.cpython-312.pyc
│ │ │ │ ├── _textwrap.cpython-312.pyc
│ │ │ │ ├── _winconsole.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── decorators.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formatting.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── shell_completion.cpython-312.pyc
│ │ │ │ ├── termui.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── types.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── _compat.py
│ │ │ ├── _termui_impl.py
│ │ │ ├── _textwrap.py
│ │ │ ├── _winconsole.py
│ │ │ ├── core.py
│ │ │ ├── decorators.py
│ │ │ ├── exceptions.py
│ │ │ ├── formatting.py
│ │ │ ├── globals.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── shell_completion.py
│ │ │ ├── termui.py
│ │ │ ├── testing.py
│ │ │ ├── types.py
│ │ │ └── utils.py
│ │ ├── click-8.1.7.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.rst
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── fake_useragent
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ ├── fake.cpython-312.pyc
│ │ │ │ ├── log.cpython-312.pyc
│ │ │ │ ├── settings.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── data
│ │ │ │ └── browsers.json
│ │ │ ├── errors.py
│ │ │ ├── fake.py
│ │ │ ├── log.py
│ │ │ ├── settings.py
│ │ │ └── utils.py
│ │ ├── fake_useragent-1.5.1.dist-info
│ │ │ ├── AUTHORS
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── flask
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ ├── cli.cpython-312.pyc
│ │ │ │ ├── config.cpython-312.pyc
│ │ │ │ ├── ctx.cpython-312.pyc
│ │ │ │ ├── debughelpers.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── helpers.cpython-312.pyc
│ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── signals.cpython-312.pyc
│ │ │ │ ├── templating.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── typing.cpython-312.pyc
│ │ │ │ ├── views.cpython-312.pyc
│ │ │ │ └── wrappers.cpython-312.pyc
│ │ │ ├── app.py
│ │ │ ├── blueprints.py
│ │ │ ├── cli.py
│ │ │ ├── config.py
│ │ │ ├── ctx.py
│ │ │ ├── debughelpers.py
│ │ │ ├── globals.py
│ │ │ ├── helpers.py
│ │ │ ├── json
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ └── tag.cpython-312.pyc
│ │ │ │ ├── provider.py
│ │ │ │ └── tag.py
│ │ │ ├── logging.py
│ │ │ ├── py.typed
│ │ │ ├── sansio
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ │ └── scaffold.cpython-312.pyc
│ │ │ │ ├── app.py
│ │ │ │ ├── blueprints.py
│ │ │ │ ├── README.md
│ │ │ │ └── scaffold.py
│ │ │ ├── sessions.py
│ │ │ ├── signals.py
│ │ │ ├── templating.py
│ │ │ ├── testing.py
│ │ │ ├── typing.py
│ │ │ ├── views.py
│ │ │ └── wrappers.py
│ │ ├── flask-3.0.3.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── idna
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ ├── codec.py
│ │ │ ├── compat.py
│ │ │ ├── core.py
│ │ │ ├── idnadata.py
│ │ │ ├── intranges.py
│ │ │ ├── package_data.py
│ │ │ ├── py.typed
│ │ │ └── uts46data.py
│ │ ├── idna-3.10.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── itsdangerous
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ ├── exc.cpython-312.pyc
│ │ │ │ ├── serializer.cpython-312.pyc
│ │ │ │ ├── signer.cpython-312.pyc
│ │ │ │ ├── timed.cpython-312.pyc
│ │ │ │ └── url_safe.cpython-312.pyc
│ │ │ ├── _json.py
│ │ │ ├── encoding.py
│ │ │ ├── exc.py
│ │ │ ├── py.typed
│ │ │ ├── serializer.py
│ │ │ ├── signer.py
│ │ │ ├── timed.py
│ │ │ └── url_safe.py
│ │ ├── itsdangerous-2.2.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── jinja2
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _identifier.cpython-312.pyc
│ │ │ │ ├── async_utils.cpython-312.pyc
│ │ │ │ ├── bccache.cpython-312.pyc
│ │ │ │ ├── compiler.cpython-312.pyc
│ │ │ │ ├── constants.cpython-312.pyc
│ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ ├── defaults.cpython-312.pyc
│ │ │ │ ├── environment.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ ├── filters.cpython-312.pyc
│ │ │ │ ├── idtracking.cpython-312.pyc
│ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ ├── loaders.cpython-312.pyc
│ │ │ │ ├── meta.cpython-312.pyc
│ │ │ │ ├── nativetypes.cpython-312.pyc
│ │ │ │ ├── nodes.cpython-312.pyc
│ │ │ │ ├── optimizer.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── runtime.cpython-312.pyc
│ │ │ │ ├── sandbox.cpython-312.pyc
│ │ │ │ ├── tests.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── visitor.cpython-312.pyc
│ │ │ ├── _identifier.py
│ │ │ ├── async_utils.py
│ │ │ ├── bccache.py
│ │ │ ├── compiler.py
│ │ │ ├── constants.py
│ │ │ ├── debug.py
│ │ │ ├── defaults.py
│ │ │ ├── environment.py
│ │ │ ├── exceptions.py
│ │ │ ├── ext.py
│ │ │ ├── filters.py
│ │ │ ├── idtracking.py
│ │ │ ├── lexer.py
│ │ │ ├── loaders.py
│ │ │ ├── meta.py
│ │ │ ├── nativetypes.py
│ │ │ ├── nodes.py
│ │ │ ├── optimizer.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── runtime.py
│ │ │ ├── sandbox.py
│ │ │ ├── tests.py
│ │ │ ├── utils.py
│ │ │ └── visitor.py
│ │ ├── jinja2-3.1.4.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── lxml
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _elementpath.cpython-312.pyc
│ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ ├── cssselect.cpython-312.pyc
│ │ │ │ ├── doctestcompare.cpython-312.pyc
│ │ │ │ ├── ElementInclude.cpython-312.pyc
│ │ │ │ ├── pyclasslookup.cpython-312.pyc
│ │ │ │ ├── sax.cpython-312.pyc
│ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ ├── _elementpath.cpython-312-darwin.so
│ │ │ ├── _elementpath.py
│ │ │ ├── apihelpers.pxi
│ │ │ ├── builder.cpython-312-darwin.so
│ │ │ ├── builder.py
│ │ │ ├── classlookup.pxi
│ │ │ ├── cleanup.pxi
│ │ │ ├── cssselect.py
│ │ │ ├── debug.pxi
│ │ │ ├── docloader.pxi
│ │ │ ├── doctestcompare.py
│ │ │ ├── dtd.pxi
│ │ │ ├── ElementInclude.py
│ │ │ ├── etree_api.h
│ │ │ ├── etree.cpython-312-darwin.so
│ │ │ ├── etree.h
│ │ │ ├── etree.pyx
│ │ │ ├── extensions.pxi
│ │ │ ├── html
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _diffcommand.cpython-312.pyc
│ │ │ │ │ ├── _html5builder.cpython-312.pyc
│ │ │ │ │ ├── _setmixin.cpython-312.pyc
│ │ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ │ ├── clean.cpython-312.pyc
│ │ │ │ │ ├── defs.cpython-312.pyc
│ │ │ │ │ ├── diff.cpython-312.pyc
│ │ │ │ │ ├── ElementSoup.cpython-312.pyc
│ │ │ │ │ ├── formfill.cpython-312.pyc
│ │ │ │ │ ├── html5parser.cpython-312.pyc
│ │ │ │ │ ├── soupparser.cpython-312.pyc
│ │ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ │ ├── _diffcommand.py
│ │ │ │ ├── _html5builder.py
│ │ │ │ ├── _setmixin.py
│ │ │ │ ├── builder.py
│ │ │ │ ├── clean.py
│ │ │ │ ├── defs.py
│ │ │ │ ├── diff.cpython-312-darwin.so
│ │ │ │ ├── diff.py
│ │ │ │ ├── ElementSoup.py
│ │ │ │ ├── formfill.py
│ │ │ │ ├── html5parser.py
│ │ │ │ ├── soupparser.py
│ │ │ │ └── usedoctest.py
│ │ │ ├── includes
│ │ │ │ ├── __init__.pxd
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── c14n.pxd
│ │ │ │ ├── config.pxd
│ │ │ │ ├── dtdvalid.pxd
│ │ │ │ ├── etree_defs.h
│ │ │ │ ├── etreepublic.pxd
│ │ │ │ ├── extlibs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── libcharset.h
│ │ │ │ │ ├── localcharset.h
│ │ │ │ │ ├── zconf.h
│ │ │ │ │ └── zlib.h
│ │ │ │ ├── htmlparser.pxd
│ │ │ │ ├── libexslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── exslt.h
│ │ │ │ │ ├── exsltconfig.h
│ │ │ │ │ └── exsltexports.h
│ │ │ │ ├── libxml
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── c14n.h
│ │ │ │ │ ├── catalog.h
│ │ │ │ │ ├── chvalid.h
│ │ │ │ │ ├── debugXML.h
│ │ │ │ │ ├── dict.h
│ │ │ │ │ ├── encoding.h
│ │ │ │ │ ├── entities.h
│ │ │ │ │ ├── globals.h
│ │ │ │ │ ├── hash.h
│ │ │ │ │ ├── HTMLparser.h
│ │ │ │ │ ├── HTMLtree.h
│ │ │ │ │ ├── list.h
│ │ │ │ │ ├── nanoftp.h
│ │ │ │ │ ├── nanohttp.h
│ │ │ │ │ ├── parser.h
│ │ │ │ │ ├── parserInternals.h
│ │ │ │ │ ├── relaxng.h
│ │ │ │ │ ├── SAX.h
│ │ │ │ │ ├── SAX2.h
│ │ │ │ │ ├── schemasInternals.h
│ │ │ │ │ ├── schematron.h
│ │ │ │ │ ├── threads.h
│ │ │ │ │ ├── tree.h
│ │ │ │ │ ├── uri.h
│ │ │ │ │ ├── valid.h
│ │ │ │ │ ├── xinclude.h
│ │ │ │ │ ├── xlink.h
│ │ │ │ │ ├── xmlautomata.h
│ │ │ │ │ ├── xmlerror.h
│ │ │ │ │ ├── xmlexports.h
│ │ │ │ │ ├── xmlIO.h
│ │ │ │ │ ├── xmlmemory.h
│ │ │ │ │ ├── xmlmodule.h
│ │ │ │ │ ├── xmlreader.h
│ │ │ │ │ ├── xmlregexp.h
│ │ │ │ │ ├── xmlsave.h
│ │ │ │ │ ├── xmlschemas.h
│ │ │ │ │ ├── xmlschemastypes.h
│ │ │ │ │ ├── xmlstring.h
│ │ │ │ │ ├── xmlunicode.h
│ │ │ │ │ ├── xmlversion.h
│ │ │ │ │ ├── xmlwriter.h
│ │ │ │ │ ├── xpath.h
│ │ │ │ │ ├── xpathInternals.h
│ │ │ │ │ └── xpointer.h
│ │ │ │ ├── libxslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── attributes.h
│ │ │ │ │ ├── documents.h
│ │ │ │ │ ├── extensions.h
│ │ │ │ │ ├── extra.h
│ │ │ │ │ ├── functions.h
│ │ │ │ │ ├── imports.h
│ │ │ │ │ ├── keys.h
│ │ │ │ │ ├── namespaces.h
│ │ │ │ │ ├── numbersInternals.h
│ │ │ │ │ ├── pattern.h
│ │ │ │ │ ├── preproc.h
│ │ │ │ │ ├── security.h
│ │ │ │ │ ├── templates.h
│ │ │ │ │ ├── transform.h
│ │ │ │ │ ├── variables.h
│ │ │ │ │ ├── xslt.h
│ │ │ │ │ ├── xsltconfig.h
│ │ │ │ │ ├── xsltexports.h
│ │ │ │ │ ├── xsltInternals.h
│ │ │ │ │ ├── xsltlocale.h
│ │ │ │ │ └── xsltutils.h
│ │ │ │ ├── lxml-version.h
│ │ │ │ ├── relaxng.pxd
│ │ │ │ ├── schematron.pxd
│ │ │ │ ├── tree.pxd
│ │ │ │ ├── uri.pxd
│ │ │ │ ├── xinclude.pxd
│ │ │ │ ├── xmlerror.pxd
│ │ │ │ ├── xmlparser.pxd
│ │ │ │ ├── xmlschema.pxd
│ │ │ │ ├── xpath.pxd
│ │ │ │ └── xslt.pxd
│ │ │ ├── isoschematron
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ └── resources
│ │ │ │ ├── rng
│ │ │ │ │ └── iso-schematron.rng
│ │ │ │ └── xsl
│ │ │ │ ├── iso-schematron-xslt1
│ │ │ │ │ ├── iso_abstract_expand.xsl
│ │ │ │ │ ├── iso_dsdl_include.xsl
│ │ │ │ │ ├── iso_schematron_message.xsl
│ │ │ │ │ ├── iso_schematron_skeleton_for_xslt1.xsl
│ │ │ │ │ ├── iso_svrl_for_xslt1.xsl
│ │ │ │ │ └── readme.txt
│ │ │ │ ├── RNG2Schtrn.xsl
│ │ │ │ └── XSD2Schtrn.xsl
│ │ │ ├── iterparse.pxi
│ │ │ ├── lxml.etree_api.h
│ │ │ ├── lxml.etree.h
│ │ │ ├── nsclasses.pxi
│ │ │ ├── objectify.cpython-312-darwin.so
│ │ │ ├── objectify.pyx
│ │ │ ├── objectpath.pxi
│ │ │ ├── parser.pxi
│ │ │ ├── parsertarget.pxi
│ │ │ ├── proxy.pxi
│ │ │ ├── public-api.pxi
│ │ │ ├── pyclasslookup.py
│ │ │ ├── readonlytree.pxi
│ │ │ ├── relaxng.pxi
│ │ │ ├── sax.cpython-312-darwin.so
│ │ │ ├── sax.py
│ │ │ ├── saxparser.pxi
│ │ │ ├── schematron.pxi
│ │ │ ├── serializer.pxi
│ │ │ ├── usedoctest.py
│ │ │ ├── xinclude.pxi
│ │ │ ├── xmlerror.pxi
│ │ │ ├── xmlid.pxi
│ │ │ ├── xmlschema.pxi
│ │ │ ├── xpath.pxi
│ │ │ ├── xslt.pxi
│ │ │ └── xsltext.pxi
│ │ ├── lxml-5.3.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── LICENSES.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── markupsafe
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── _native.cpython-312.pyc
│ │ │ ├── _native.py
│ │ │ ├── _speedups.c
│ │ │ ├── _speedups.cpython-312-darwin.so
│ │ │ ├── _speedups.pyi
│ │ │ └── py.typed
│ │ ├── MarkupSafe-3.0.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── pip
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pip-runner__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── __pip-runner__.cpython-312.pyc
│ │ │ ├── _internal
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── build_env.cpython-312.pyc
│ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ ├── pyproject.cpython-312.pyc
│ │ │ │ │ ├── self_outdated_check.cpython-312.pyc
│ │ │ │ │ └── wheel_builder.cpython-312.pyc
│ │ │ │ ├── build_env.py
│ │ │ │ ├── cache.py
│ │ │ │ ├── cli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── autocompletion.cpython-312.pyc
│ │ │ │ │ │ ├── base_command.cpython-312.pyc
│ │ │ │ │ │ ├── cmdoptions.cpython-312.pyc
│ │ │ │ │ │ ├── command_context.cpython-312.pyc
│ │ │ │ │ │ ├── index_command.cpython-312.pyc
│ │ │ │ │ │ ├── main_parser.cpython-312.pyc
│ │ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bars.cpython-312.pyc
│ │ │ │ │ │ ├── req_command.cpython-312.pyc
│ │ │ │ │ │ ├── spinners.cpython-312.pyc
│ │ │ │ │ │ └── status_codes.cpython-312.pyc
│ │ │ │ │ ├── autocompletion.py
│ │ │ │ │ ├── base_command.py
│ │ │ │ │ ├── cmdoptions.py
│ │ │ │ │ ├── command_context.py
│ │ │ │ │ ├── index_command.py
│ │ │ │ │ ├── main_parser.py
│ │ │ │ │ ├── main.py
│ │ │ │ │ ├── parser.py
│ │ │ │ │ ├── progress_bars.py
│ │ │ │ │ ├── req_command.py
│ │ │ │ │ ├── spinners.py
│ │ │ │ │ └── status_codes.py
│ │ │ │ ├── commands
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── completion.cpython-312.pyc
│ │ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ ├── hash.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── inspect.cpython-312.pyc
│ │ │ │ │ │ ├── install.cpython-312.pyc
│ │ │ │ │ │ ├── list.cpython-312.pyc
│ │ │ │ │ │ ├── search.cpython-312.pyc
│ │ │ │ │ │ ├── show.cpython-312.pyc
│ │ │ │ │ │ ├── uninstall.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── completion.py
│ │ │ │ │ ├── configuration.py
│ │ │ │ │ ├── debug.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── hash.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── inspect.py
│ │ │ │ │ ├── install.py
│ │ │ │ │ ├── list.py
│ │ │ │ │ ├── search.py
│ │ │ │ │ ├── show.py
│ │ │ │ │ ├── uninstall.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── configuration.py
│ │ │ │ ├── distributions
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── installed.cpython-312.pyc
│ │ │ │ │ │ ├── sdist.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── installed.py
│ │ │ │ │ ├── sdist.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── index
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── collector.cpython-312.pyc
│ │ │ │ │ │ ├── package_finder.cpython-312.pyc
│ │ │ │ │ │ └── sources.cpython-312.pyc
│ │ │ │ │ ├── collector.py
│ │ │ │ │ ├── package_finder.py
│ │ │ │ │ └── sources.py
│ │ │ │ ├── locations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _distutils.cpython-312.pyc
│ │ │ │ │ │ ├── _sysconfig.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── _distutils.py
│ │ │ │ │ ├── _sysconfig.py
│ │ │ │ │ └── base.py
│ │ │ │ ├── main.py
│ │ │ │ ├── metadata
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ └── pkg_resources.cpython-312.pyc
│ │ │ │ │ ├── _json.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── importlib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ │ ├── _dists.cpython-312.pyc
│ │ │ │ │ │ │ └── _envs.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.py
│ │ │ │ │ │ ├── _dists.py
│ │ │ │ │ │ └── _envs.py
│ │ │ │ │ └── pkg_resources.py
│ │ │ │ ├── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── candidate.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url.cpython-312.pyc
│ │ │ │ │ │ ├── format_control.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── installation_report.cpython-312.pyc
│ │ │ │ │ │ ├── link.cpython-312.pyc
│ │ │ │ │ │ ├── scheme.cpython-312.pyc
│ │ │ │ │ │ ├── search_scope.cpython-312.pyc
│ │ │ │ │ │ ├── selection_prefs.cpython-312.pyc
│ │ │ │ │ │ ├── target_python.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── candidate.py
│ │ │ │ │ ├── direct_url.py
│ │ │ │ │ ├── format_control.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── installation_report.py
│ │ │ │ │ ├── link.py
│ │ │ │ │ ├── scheme.py
│ │ │ │ │ ├── search_scope.py
│ │ │ │ │ ├── selection_prefs.py
│ │ │ │ │ ├── target_python.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── network
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── lazy_wheel.cpython-312.pyc
│ │ │ │ │ │ ├── session.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── xmlrpc.cpython-312.pyc
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── lazy_wheel.py
│ │ │ │ │ ├── session.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── xmlrpc.py
│ │ │ │ ├── operations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ └── prepare.cpython-312.pyc
│ │ │ │ │ ├── build
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── build_tracker.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_legacy.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── build_tracker.py
│ │ │ │ │ │ ├── metadata_editable.py
│ │ │ │ │ │ ├── metadata_legacy.py
│ │ │ │ │ │ ├── metadata.py
│ │ │ │ │ │ ├── wheel_editable.py
│ │ │ │ │ │ ├── wheel_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── install
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── editable_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── editable_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ └── prepare.py
│ │ │ │ ├── pyproject.py
│ │ │ │ ├── req
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── constructors.cpython-312.pyc
│ │ │ │ │ │ ├── req_file.cpython-312.pyc
│ │ │ │ │ │ ├── req_install.cpython-312.pyc
│ │ │ │ │ │ ├── req_set.cpython-312.pyc
│ │ │ │ │ │ └── req_uninstall.cpython-312.pyc
│ │ │ │ │ ├── constructors.py
│ │ │ │ │ ├── req_file.py
│ │ │ │ │ ├── req_install.py
│ │ │ │ │ ├── req_set.py
│ │ │ │ │ └── req_uninstall.py
│ │ │ │ ├── resolution
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── legacy
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ │ └── resolver.py
│ │ │ │ │ └── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── candidates.cpython-312.pyc
│ │ │ │ │ │ ├── factory.cpython-312.pyc
│ │ │ │ │ │ ├── found_candidates.cpython-312.pyc
│ │ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ │ ├── reporter.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── candidates.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── found_candidates.py
│ │ │ │ │ ├── provider.py
│ │ │ │ │ ├── reporter.py
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ └── resolver.py
│ │ │ │ ├── self_outdated_check.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _jaraco_text.cpython-312.pyc
│ │ │ │ │ │ ├── _log.cpython-312.pyc
│ │ │ │ │ │ ├── appdirs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── compatibility_tags.cpython-312.pyc
│ │ │ │ │ │ ├── datetime.cpython-312.pyc
│ │ │ │ │ │ ├── deprecation.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url_helpers.cpython-312.pyc
│ │ │ │ │ │ ├── egg_link.cpython-312.pyc
│ │ │ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ │ │ ├── entrypoints.cpython-312.pyc
│ │ │ │ │ │ ├── filesystem.cpython-312.pyc
│ │ │ │ │ │ ├── filetypes.cpython-312.pyc
│ │ │ │ │ │ ├── glibc.cpython-312.pyc
│ │ │ │ │ │ ├── hashes.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── misc.cpython-312.pyc
│ │ │ │ │ │ ├── packaging.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── setuptools_build.cpython-312.pyc
│ │ │ │ │ │ ├── subprocess.cpython-312.pyc
│ │ │ │ │ │ ├── temp_dir.cpython-312.pyc
│ │ │ │ │ │ ├── unpacking.cpython-312.pyc
│ │ │ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ │ │ ├── virtualenv.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── _jaraco_text.py
│ │ │ │ │ ├── _log.py
│ │ │ │ │ ├── appdirs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── compatibility_tags.py
│ │ │ │ │ ├── datetime.py
│ │ │ │ │ ├── deprecation.py
│ │ │ │ │ ├── direct_url_helpers.py
│ │ │ │ │ ├── egg_link.py
│ │ │ │ │ ├── encoding.py
│ │ │ │ │ ├── entrypoints.py
│ │ │ │ │ ├── filesystem.py
│ │ │ │ │ ├── filetypes.py
│ │ │ │ │ ├── glibc.py
│ │ │ │ │ ├── hashes.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── packaging.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── setuptools_build.py
│ │ │ │ │ ├── subprocess.py
│ │ │ │ │ ├── temp_dir.py
│ │ │ │ │ ├── unpacking.py
│ │ │ │ │ ├── urls.py
│ │ │ │ │ ├── virtualenv.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── vcs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── bazaar.cpython-312.pyc
│ │ │ │ │ │ ├── git.cpython-312.pyc
│ │ │ │ │ │ ├── mercurial.cpython-312.pyc
│ │ │ │ │ │ ├── subversion.cpython-312.pyc
│ │ │ │ │ │ └── versioncontrol.cpython-312.pyc
│ │ │ │ │ ├── bazaar.py
│ │ │ │ │ ├── git.py
│ │ │ │ │ ├── mercurial.py
│ │ │ │ │ ├── subversion.py
│ │ │ │ │ └── versioncontrol.py
│ │ │ │ └── wheel_builder.py
│ │ │ ├── _vendor
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ └── typing_extensions.cpython-312.pyc
│ │ │ │ ├── cachecontrol
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _cmd.cpython-312.pyc
│ │ │ │ │ │ ├── adapter.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── controller.cpython-312.pyc
│ │ │ │ │ │ ├── filewrapper.cpython-312.pyc
│ │ │ │ │ │ ├── heuristics.cpython-312.pyc
│ │ │ │ │ │ ├── serialize.cpython-312.pyc
│ │ │ │ │ │ └── wrapper.cpython-312.pyc
│ │ │ │ │ ├── _cmd.py
│ │ │ │ │ ├── adapter.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── caches
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── file_cache.cpython-312.pyc
│ │ │ │ │ │ │ └── redis_cache.cpython-312.pyc
│ │ │ │ │ │ ├── file_cache.py
│ │ │ │ │ │ └── redis_cache.py
│ │ │ │ │ ├── controller.py
│ │ │ │ │ ├── filewrapper.py
│ │ │ │ │ ├── heuristics.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── serialize.py
│ │ │ │ │ └── wrapper.py
│ │ │ │ ├── certifi
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── core.cpython-312.pyc
│ │ │ │ │ ├── cacert.pem
│ │ │ │ │ ├── core.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── distlib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── database.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── locators.cpython-312.pyc
│ │ │ │ │ │ ├── manifest.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── resources.cpython-312.pyc
│ │ │ │ │ │ ├── scripts.cpython-312.pyc
│ │ │ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── database.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── locators.py
│ │ │ │ │ ├── manifest.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ ├── scripts.py
│ │ │ │ │ ├── t32.exe
│ │ │ │ │ ├── t64-arm.exe
│ │ │ │ │ ├── t64.exe
│ │ │ │ │ ├── util.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ ├── w32.exe
│ │ │ │ │ ├── w64-arm.exe
│ │ │ │ │ ├── w64.exe
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── distro
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── distro.cpython-312.pyc
│ │ │ │ │ ├── distro.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── idna
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ │ │ ├── codec.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── core.py
│ │ │ │ │ ├── idnadata.py
│ │ │ │ │ ├── intranges.py
│ │ │ │ │ ├── package_data.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ └── uts46data.py
│ │ │ │ ├── msgpack
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ │ │ └── fallback.cpython-312.pyc
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── ext.py
│ │ │ │ │ └── fallback.py
│ │ │ │ ├── packaging
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _elffile.cpython-312.pyc
│ │ │ │ │ │ ├── _manylinux.cpython-312.pyc
│ │ │ │ │ │ ├── _musllinux.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _structures.cpython-312.pyc
│ │ │ │ │ │ ├── _tokenizer.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ ├── specifiers.cpython-312.pyc
│ │ │ │ │ │ ├── tags.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── version.cpython-312.pyc
│ │ │ │ │ ├── _elffile.py
│ │ │ │ │ ├── _manylinux.py
│ │ │ │ │ ├── _musllinux.py
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _structures.py
│ │ │ │ │ ├── _tokenizer.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ ├── specifiers.py
│ │ │ │ │ ├── tags.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── version.py
│ │ │ │ ├── pkg_resources
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── platformdirs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── android.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── macos.cpython-312.pyc
│ │ │ │ │ │ ├── unix.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── windows.cpython-312.pyc
│ │ │ │ │ ├── android.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── unix.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── pygments
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── cmdline.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── filter.cpython-312.pyc
│ │ │ │ │ │ ├── formatter.cpython-312.pyc
│ │ │ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ │ │ ├── modeline.cpython-312.pyc
│ │ │ │ │ │ ├── plugin.cpython-312.pyc
│ │ │ │ │ │ ├── regexopt.cpython-312.pyc
│ │ │ │ │ │ ├── scanner.cpython-312.pyc
│ │ │ │ │ │ ├── sphinxext.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── token.cpython-312.pyc
│ │ │ │ │ │ ├── unistring.cpython-312.pyc
│ │ │ │ │ │ └── util.cpython-312.pyc
│ │ │ │ │ ├── cmdline.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── filter.py
│ │ │ │ │ ├── filters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── formatter.py
│ │ │ │ │ ├── formatters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ ├── bbcode.cpython-312.pyc
│ │ │ │ │ │ │ ├── groff.cpython-312.pyc
│ │ │ │ │ │ │ ├── html.cpython-312.pyc
│ │ │ │ │ │ │ ├── img.cpython-312.pyc
│ │ │ │ │ │ │ ├── irc.cpython-312.pyc
│ │ │ │ │ │ │ ├── latex.cpython-312.pyc
│ │ │ │ │ │ │ ├── other.cpython-312.pyc
│ │ │ │ │ │ │ ├── pangomarkup.cpython-312.pyc
│ │ │ │ │ │ │ ├── rtf.cpython-312.pyc
│ │ │ │ │ │ │ ├── svg.cpython-312.pyc
│ │ │ │ │ │ │ ├── terminal.cpython-312.pyc
│ │ │ │ │ │ │ └── terminal256.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ ├── bbcode.py
│ │ │ │ │ │ ├── groff.py
│ │ │ │ │ │ ├── html.py
│ │ │ │ │ │ ├── img.py
│ │ │ │ │ │ ├── irc.py
│ │ │ │ │ │ ├── latex.py
│ │ │ │ │ │ ├── other.py
│ │ │ │ │ │ ├── pangomarkup.py
│ │ │ │ │ │ ├── rtf.py
│ │ │ │ │ │ ├── svg.py
│ │ │ │ │ │ ├── terminal.py
│ │ │ │ │ │ └── terminal256.py
│ │ │ │ │ ├── lexer.py
│ │ │ │ │ ├── lexers
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ └── python.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ └── python.py
│ │ │ │ │ ├── modeline.py
│ │ │ │ │ ├── plugin.py
│ │ │ │ │ ├── regexopt.py
│ │ │ │ │ ├── scanner.py
│ │ │ │ │ ├── sphinxext.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styles
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── _mapping.cpython-312.pyc
│ │ │ │ │ │ └── _mapping.py
│ │ │ │ │ ├── token.py
│ │ │ │ │ ├── unistring.py
│ │ │ │ │ └── util.py
│ │ │ │ ├── pyproject_hooks
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ └── _impl.cpython-312.pyc
│ │ │ │ │ ├── _compat.py
│ │ │ │ │ ├── _impl.py
│ │ │ │ │ └── _in_process
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── _in_process.cpython-312.pyc
│ │ │ │ │ └── _in_process.py
│ │ │ │ ├── requests
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ │ ├── __version__.py
│ │ │ │ │ ├── _internal_utils.py
│ │ │ │ │ ├── adapters.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── certs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── cookies.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── hooks.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ ├── packages.py
│ │ │ │ │ ├── sessions.py
│ │ │ │ │ ├── status_codes.py
│ │ │ │ │ ├── structures.py
│ │ │ │ │ └── utils.py
│ │ │ │ ├── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── providers.cpython-312.pyc
│ │ │ │ │ │ ├── reporters.cpython-312.pyc
│ │ │ │ │ │ ├── resolvers.cpython-312.pyc
│ │ │ │ │ │ └── structs.cpython-312.pyc
│ │ │ │ │ ├── compat
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── collections_abc.cpython-312.pyc
│ │ │ │ │ │ └── collections_abc.py
│ │ │ │ │ ├── providers.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── reporters.py
│ │ │ │ │ ├── resolvers.py
│ │ │ │ │ └── structs.py
│ │ │ │ ├── rich
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── _cell_widths.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_codes.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_replace.cpython-312.pyc
│ │ │ │ │ │ ├── _export_format.cpython-312.pyc
│ │ │ │ │ │ ├── _extension.cpython-312.pyc
│ │ │ │ │ │ ├── _fileno.cpython-312.pyc
│ │ │ │ │ │ ├── _inspect.cpython-312.pyc
│ │ │ │ │ │ ├── _log_render.cpython-312.pyc
│ │ │ │ │ │ ├── _loop.cpython-312.pyc
│ │ │ │ │ │ ├── _null_file.cpython-312.pyc
│ │ │ │ │ │ ├── _palettes.cpython-312.pyc
│ │ │ │ │ │ ├── _pick.cpython-312.pyc
│ │ │ │ │ │ ├── _ratio.cpython-312.pyc
│ │ │ │ │ │ ├── _spinners.cpython-312.pyc
│ │ │ │ │ │ ├── _stack.cpython-312.pyc
│ │ │ │ │ │ ├── _timer.cpython-312.pyc
│ │ │ │ │ │ ├── _win32_console.cpython-312.pyc
│ │ │ │ │ │ ├── _windows_renderer.cpython-312.pyc
│ │ │ │ │ │ ├── _windows.cpython-312.pyc
│ │ │ │ │ │ ├── _wrap.cpython-312.pyc
│ │ │ │ │ │ ├── abc.cpython-312.pyc
│ │ │ │ │ │ ├── align.cpython-312.pyc
│ │ │ │ │ │ ├── ansi.cpython-312.pyc
│ │ │ │ │ │ ├── bar.cpython-312.pyc
│ │ │ │ │ │ ├── box.cpython-312.pyc
│ │ │ │ │ │ ├── cells.cpython-312.pyc
│ │ │ │ │ │ ├── color_triplet.cpython-312.pyc
│ │ │ │ │ │ ├── color.cpython-312.pyc
│ │ │ │ │ │ ├── columns.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── constrain.cpython-312.pyc
│ │ │ │ │ │ ├── containers.cpython-312.pyc
│ │ │ │ │ │ ├── control.cpython-312.pyc
│ │ │ │ │ │ ├── default_styles.cpython-312.pyc
│ │ │ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ │ │ ├── emoji.cpython-312.pyc
│ │ │ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ │ │ ├── file_proxy.cpython-312.pyc
│ │ │ │ │ │ ├── filesize.cpython-312.pyc
│ │ │ │ │ │ ├── highlighter.cpython-312.pyc
│ │ │ │ │ │ ├── json.cpython-312.pyc
│ │ │ │ │ │ ├── jupyter.cpython-312.pyc
│ │ │ │ │ │ ├── layout.cpython-312.pyc
│ │ │ │ │ │ ├── live_render.cpython-312.pyc
│ │ │ │ │ │ ├── live.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── markup.cpython-312.pyc
│ │ │ │ │ │ ├── measure.cpython-312.pyc
│ │ │ │ │ │ ├── padding.cpython-312.pyc
│ │ │ │ │ │ ├── pager.cpython-312.pyc
│ │ │ │ │ │ ├── palette.cpython-312.pyc
│ │ │ │ │ │ ├── panel.cpython-312.pyc
│ │ │ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bar.cpython-312.pyc
│ │ │ │ │ │ ├── progress.cpython-312.pyc
│ │ │ │ │ │ ├── prompt.cpython-312.pyc
│ │ │ │ │ │ ├── protocol.cpython-312.pyc
│ │ │ │ │ │ ├── region.cpython-312.pyc
│ │ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ │ ├── rule.cpython-312.pyc
│ │ │ │ │ │ ├── scope.cpython-312.pyc
│ │ │ │ │ │ ├── screen.cpython-312.pyc
│ │ │ │ │ │ ├── segment.cpython-312.pyc
│ │ │ │ │ │ ├── spinner.cpython-312.pyc
│ │ │ │ │ │ ├── status.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── styled.cpython-312.pyc
│ │ │ │ │ │ ├── syntax.cpython-312.pyc
│ │ │ │ │ │ ├── table.cpython-312.pyc
│ │ │ │ │ │ ├── terminal_theme.cpython-312.pyc
│ │ │ │ │ │ ├── text.cpython-312.pyc
│ │ │ │ │ │ ├── theme.cpython-312.pyc
│ │ │ │ │ │ ├── themes.cpython-312.pyc
│ │ │ │ │ │ ├── traceback.cpython-312.pyc
│ │ │ │ │ │ └── tree.cpython-312.pyc
│ │ │ │ │ ├── _cell_widths.py
│ │ │ │ │ ├── _emoji_codes.py
│ │ │ │ │ ├── _emoji_replace.py
│ │ │ │ │ ├── _export_format.py
│ │ │ │ │ ├── _extension.py
│ │ │ │ │ ├── _fileno.py
│ │ │ │ │ ├── _inspect.py
│ │ │ │ │ ├── _log_render.py
│ │ │ │ │ ├── _loop.py
│ │ │ │ │ ├── _null_file.py
│ │ │ │ │ ├── _palettes.py
│ │ │ │ │ ├── _pick.py
│ │ │ │ │ ├── _ratio.py
│ │ │ │ │ ├── _spinners.py
│ │ │ │ │ ├── _stack.py
│ │ │ │ │ ├── _timer.py
│ │ │ │ │ ├── _win32_console.py
│ │ │ │ │ ├── _windows_renderer.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ ├── _wrap.py
│ │ │ │ │ ├── abc.py
│ │ │ │ │ ├── align.py
│ │ │ │ │ ├── ansi.py
│ │ │ │ │ ├── bar.py
│ │ │ │ │ ├── box.py
│ │ │ │ │ ├── cells.py
│ │ │ │ │ ├── color_triplet.py
│ │ │ │ │ ├── color.py
│ │ │ │ │ ├── columns.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── constrain.py
│ │ │ │ │ ├── containers.py
│ │ │ │ │ ├── control.py
│ │ │ │ │ ├── default_styles.py
│ │ │ │ │ ├── diagnose.py
│ │ │ │ │ ├── emoji.py
│ │ │ │ │ ├── errors.py
│ │ │ │ │ ├── file_proxy.py
│ │ │ │ │ ├── filesize.py
│ │ │ │ │ ├── highlighter.py
│ │ │ │ │ ├── json.py
│ │ │ │ │ ├── jupyter.py
│ │ │ │ │ ├── layout.py
│ │ │ │ │ ├── live_render.py
│ │ │ │ │ ├── live.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── markup.py
│ │ │ │ │ ├── measure.py
│ │ │ │ │ ├── padding.py
│ │ │ │ │ ├── pager.py
│ │ │ │ │ ├── palette.py
│ │ │ │ │ ├── panel.py
│ │ │ │ │ ├── pretty.py
│ │ │ │ │ ├── progress_bar.py
│ │ │ │ │ ├── progress.py
│ │ │ │ │ ├── prompt.py
│ │ │ │ │ ├── protocol.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── region.py
│ │ │ │ │ ├── repr.py
│ │ │ │ │ ├── rule.py
│ │ │ │ │ ├── scope.py
│ │ │ │ │ ├── screen.py
│ │ │ │ │ ├── segment.py
│ │ │ │ │ ├── spinner.py
│ │ │ │ │ ├── status.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styled.py
│ │ │ │ │ ├── syntax.py
│ │ │ │ │ ├── table.py
│ │ │ │ │ ├── terminal_theme.py
│ │ │ │ │ ├── text.py
│ │ │ │ │ ├── theme.py
│ │ │ │ │ ├── themes.py
│ │ │ │ │ ├── traceback.py
│ │ │ │ │ └── tree.py
│ │ │ │ ├── tomli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _re.cpython-312.pyc
│ │ │ │ │ │ └── _types.cpython-312.pyc
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _re.py
│ │ │ │ │ ├── _types.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── truststore
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _api.cpython-312.pyc
│ │ │ │ │ │ ├── _macos.cpython-312.pyc
│ │ │ │ │ │ ├── _openssl.cpython-312.pyc
│ │ │ │ │ │ ├── _ssl_constants.cpython-312.pyc
│ │ │ │ │ │ └── _windows.cpython-312.pyc
│ │ │ │ │ ├── _api.py
│ │ │ │ │ ├── _macos.py
│ │ │ │ │ ├── _openssl.py
│ │ │ │ │ ├── _ssl_constants.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── typing_extensions.py
│ │ │ │ ├── urllib3
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── _collections.py
│ │ │ │ │ ├── _version.py
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── connectionpool.py
│ │ │ │ │ ├── contrib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _appengine_environ.cpython-312.pyc
│ │ │ │ │ │ │ ├── appengine.cpython-312.pyc
│ │ │ │ │ │ │ ├── ntlmpool.cpython-312.pyc
│ │ │ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ │ │ ├── securetransport.cpython-312.pyc
│ │ │ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ │ │ ├── _appengine_environ.py
│ │ │ │ │ │ ├── _securetransport
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── bindings.cpython-312.pyc
│ │ │ │ │ │ │ │ └── low_level.cpython-312.pyc
│ │ │ │ │ │ │ ├── bindings.py
│ │ │ │ │ │ │ └── low_level.py
│ │ │ │ │ │ ├── appengine.py
│ │ │ │ │ │ ├── ntlmpool.py
│ │ │ │ │ │ ├── pyopenssl.py
│ │ │ │ │ │ ├── securetransport.py
│ │ │ │ │ │ └── socks.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── fields.py
│ │ │ │ │ ├── filepost.py
│ │ │ │ │ ├── packages
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── six.cpython-312.pyc
│ │ │ │ │ │ ├── backports
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── makefile.cpython-312.pyc
│ │ │ │ │ │ │ │ └── weakref_finalize.cpython-312.pyc
│ │ │ │ │ │ │ ├── makefile.py
│ │ │ │ │ │ │ └── weakref_finalize.py
│ │ │ │ │ │ └── six.py
│ │ │ │ │ ├── poolmanager.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ └── util
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ │ │ ├── queue.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ │ │ └── wait.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── proxy.py
│ │ │ │ │ ├── queue.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── ssl_.py
│ │ │ │ │ ├── ssl_match_hostname.py
│ │ │ │ │ ├── ssltransport.py
│ │ │ │ │ ├── timeout.py
│ │ │ │ │ ├── url.py
│ │ │ │ │ └── wait.py
│ │ │ │ └── vendor.txt
│ │ │ └── py.typed
│ │ ├── pip-24.2.dist-info
│ │ │ ├── AUTHORS.txt
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── requests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── __version__.py
│ │ │ ├── _internal_utils.py
│ │ │ ├── adapters.py
│ │ │ ├── api.py
│ │ │ ├── auth.py
│ │ │ ├── certs.py
│ │ │ ├── compat.py
│ │ │ ├── cookies.py
│ │ │ ├── exceptions.py
│ │ │ ├── help.py
│ │ │ ├── hooks.py
│ │ │ ├── models.py
│ │ │ ├── packages.py
│ │ │ ├── sessions.py
│ │ │ ├── status_codes.py
│ │ │ ├── structures.py
│ │ │ └── utils.py
│ │ ├── requests-2.32.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── soupsieve
│ │ │ ├── __init__.py
│ │ │ ├── __meta__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __meta__.cpython-312.pyc
│ │ │ │ ├── css_match.cpython-312.pyc
│ │ │ │ ├── css_parser.cpython-312.pyc
│ │ │ │ ├── css_types.cpython-312.pyc
│ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ └── util.cpython-312.pyc
│ │ │ ├── css_match.py
│ │ │ ├── css_parser.py
│ │ │ ├── css_types.py
│ │ │ ├── pretty.py
│ │ │ ├── py.typed
│ │ │ └── util.py
│ │ ├── soupsieve-2.6.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── urllib3
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _base_connection.cpython-312.pyc
│ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ ├── _request_methods.cpython-312.pyc
│ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ └── response.cpython-312.pyc
│ │ │ ├── _base_connection.py
│ │ │ ├── _collections.py
│ │ │ ├── _request_methods.py
│ │ │ ├── _version.py
│ │ │ ├── connection.py
│ │ │ ├── connectionpool.py
│ │ │ ├── contrib
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ ├── emscripten
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── fetch.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── emscripten_fetch_worker.js
│ │ │ │ │ ├── fetch.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ └── response.py
│ │ │ │ ├── pyopenssl.py
│ │ │ │ └── socks.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── filepost.py
│ │ │ ├── http2
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ └── probe.cpython-312.pyc
│ │ │ │ ├── connection.py
│ │ │ │ └── probe.py
│ │ │ ├── poolmanager.py
│ │ │ ├── py.typed
│ │ │ ├── response.py
│ │ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ └── wait.cpython-312.pyc
│ │ │ ├── connection.py
│ │ │ ├── proxy.py
│ │ │ ├── request.py
│ │ │ ├── response.py
│ │ │ ├── retry.py
│ │ │ ├── ssl_.py
│ │ │ ├── ssl_match_hostname.py
│ │ │ ├── ssltransport.py
│ │ │ ├── timeout.py
│ │ │ ├── url.py
│ │ │ ├── util.py
│ │ │ └── wait.py
│ │ ├── urllib3-2.2.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── useragent
│ │ │ ├── __init__.py
│ │ │ ├── __init__.pyc
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── resources
│ │ │ │ └── user_agent_data.json
│ │ │ └── test
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── test_additional_os.json
│ │ │ ├── test_browser.json
│ │ │ ├── test_device.json
│ │ │ ├── test_firefox.json
│ │ │ ├── test_os.json
│ │ │ └── test_pgts_browser.json
│ │ ├── useragent-0.1.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── werkzeug
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _internal.cpython-312.pyc
│ │ │ │ ├── _reloader.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formparser.cpython-312.pyc
│ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ ├── local.cpython-312.pyc
│ │ │ │ ├── security.cpython-312.pyc
│ │ │ │ ├── serving.cpython-312.pyc
│ │ │ │ ├── test.cpython-312.pyc
│ │ │ │ ├── testapp.cpython-312.pyc
│ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ ├── user_agent.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── wsgi.cpython-312.pyc
│ │ │ ├── _internal.py
│ │ │ ├── _reloader.py
│ │ │ ├── datastructures
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── accept.cpython-312.pyc
│ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ ├── cache_control.cpython-312.pyc
│ │ │ │ │ ├── csp.cpython-312.pyc
│ │ │ │ │ ├── etag.cpython-312.pyc
│ │ │ │ │ ├── file_storage.cpython-312.pyc
│ │ │ │ │ ├── headers.cpython-312.pyc
│ │ │ │ │ ├── mixins.cpython-312.pyc
│ │ │ │ │ ├── range.cpython-312.pyc
│ │ │ │ │ └── structures.cpython-312.pyc
│ │ │ │ ├── accept.py
│ │ │ │ ├── accept.pyi
│ │ │ │ ├── auth.py
│ │ │ │ ├── cache_control.py
│ │ │ │ ├── cache_control.pyi
│ │ │ │ ├── csp.py
│ │ │ │ ├── csp.pyi
│ │ │ │ ├── etag.py
│ │ │ │ ├── etag.pyi
│ │ │ │ ├── file_storage.py
│ │ │ │ ├── file_storage.pyi
│ │ │ │ ├── headers.py
│ │ │ │ ├── headers.pyi
│ │ │ │ ├── mixins.py
│ │ │ │ ├── mixins.pyi
│ │ │ │ ├── range.py
│ │ │ │ ├── range.pyi
│ │ │ │ ├── structures.py
│ │ │ │ └── structures.pyi
│ │ │ ├── debug
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ └── tbtools.cpython-312.pyc
│ │ │ │ ├── console.py
│ │ │ │ ├── repr.py
│ │ │ │ ├── shared
│ │ │ │ │ ├── console.png
│ │ │ │ │ ├── debugger.js
│ │ │ │ │ ├── ICON_LICENSE.md
│ │ │ │ │ ├── less.png
│ │ │ │ │ ├── more.png
│ │ │ │ │ └── style.css
│ │ │ │ └── tbtools.py
│ │ │ ├── exceptions.py
│ │ │ ├── formparser.py
│ │ │ ├── http.py
│ │ │ ├── local.py
│ │ │ ├── middleware
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── dispatcher.cpython-312.pyc
│ │ │ │ │ ├── http_proxy.cpython-312.pyc
│ │ │ │ │ ├── lint.cpython-312.pyc
│ │ │ │ │ ├── profiler.cpython-312.pyc
│ │ │ │ │ ├── proxy_fix.cpython-312.pyc
│ │ │ │ │ └── shared_data.cpython-312.pyc
│ │ │ │ ├── dispatcher.py
│ │ │ │ ├── http_proxy.py
│ │ │ │ ├── lint.py
│ │ │ │ ├── profiler.py
│ │ │ │ ├── proxy_fix.py
│ │ │ │ └── shared_data.py
│ │ │ ├── py.typed
│ │ │ ├── routing
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── converters.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── map.cpython-312.pyc
│ │ │ │ │ ├── matcher.cpython-312.pyc
│ │ │ │ │ └── rules.cpython-312.pyc
│ │ │ │ ├── converters.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── map.py
│ │ │ │ ├── matcher.py
│ │ │ │ └── rules.py
│ │ │ ├── sansio
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ │ ├── multipart.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ ├── http.py
│ │ │ │ ├── multipart.py
│ │ │ │ ├── request.py
│ │ │ │ ├── response.py
│ │ │ │ └── utils.py
│ │ │ ├── security.py
│ │ │ ├── serving.py
│ │ │ ├── test.py
│ │ │ ├── testapp.py
│ │ │ ├── urls.py
│ │ │ ├── user_agent.py
│ │ │ ├── utils.py
│ │ │ ├── wrappers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ ├── request.py
│ │ │ │ └── response.py
│ │ │ └── wsgi.py
│ │ └── werkzeug-3.0.4.dist-info
│ │ ├── INSTALLER
│ │ ├── LICENSE.txt
│ │ ├── METADATA
│ │ ├── RECORD
│ │ └── WHEEL
│ ├── pyvenv.cfg
│ ├── static
│ │ └── styles.css
│ ├── templates
│ │ └── index.html
│ └── test.py
├── cline_config.json
├── mcp_server.py
├── README.md
├── search_results.json
├── settings.json
└── test_files
├── text1.txt
└── text2.txt
```
# Files
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py:
--------------------------------------------------------------------------------
```python
1 | """Dependency Resolution
2 |
3 | The dependency resolution in pip is performed as follows:
4 |
5 | for top-level requirements:
6 | a. only one spec allowed per project, regardless of conflicts or not.
7 | otherwise a "double requirement" exception is raised
8 | b. they override sub-dependency requirements.
9 | for sub-dependencies
10 | a. "first found, wins" (where the order is breadth first)
11 | """
12 |
13 | import logging
14 | import sys
15 | from collections import defaultdict
16 | from itertools import chain
17 | from typing import DefaultDict, Iterable, List, Optional, Set, Tuple
18 |
19 | from pip._vendor.packaging import specifiers
20 | from pip._vendor.packaging.requirements import Requirement
21 |
22 | from pip._internal.cache import WheelCache
23 | from pip._internal.exceptions import (
24 | BestVersionAlreadyInstalled,
25 | DistributionNotFound,
26 | HashError,
27 | HashErrors,
28 | InstallationError,
29 | NoneMetadataError,
30 | UnsupportedPythonVersion,
31 | )
32 | from pip._internal.index.package_finder import PackageFinder
33 | from pip._internal.metadata import BaseDistribution
34 | from pip._internal.models.link import Link
35 | from pip._internal.models.wheel import Wheel
36 | from pip._internal.operations.prepare import RequirementPreparer
37 | from pip._internal.req.req_install import (
38 | InstallRequirement,
39 | check_invalid_constraint_type,
40 | )
41 | from pip._internal.req.req_set import RequirementSet
42 | from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider
43 | from pip._internal.utils import compatibility_tags
44 | from pip._internal.utils.compatibility_tags import get_supported
45 | from pip._internal.utils.direct_url_helpers import direct_url_from_link
46 | from pip._internal.utils.logging import indent_log
47 | from pip._internal.utils.misc import normalize_version_info
48 | from pip._internal.utils.packaging import check_requires_python
49 |
50 | logger = logging.getLogger(__name__)
51 |
52 | DiscoveredDependencies = DefaultDict[Optional[str], List[InstallRequirement]]
53 |
54 |
55 | def _check_dist_requires_python(
56 | dist: BaseDistribution,
57 | version_info: Tuple[int, int, int],
58 | ignore_requires_python: bool = False,
59 | ) -> None:
60 | """
61 | Check whether the given Python version is compatible with a distribution's
62 | "Requires-Python" value.
63 |
64 | :param version_info: A 3-tuple of ints representing the Python
65 | major-minor-micro version to check.
66 | :param ignore_requires_python: Whether to ignore the "Requires-Python"
67 | value if the given Python version isn't compatible.
68 |
69 | :raises UnsupportedPythonVersion: When the given Python version isn't
70 | compatible.
71 | """
72 | # This idiosyncratically converts the SpecifierSet to str and let
73 | # check_requires_python then parse it again into SpecifierSet. But this
74 | # is the legacy resolver so I'm just not going to bother refactoring.
75 | try:
76 | requires_python = str(dist.requires_python)
77 | except FileNotFoundError as e:
78 | raise NoneMetadataError(dist, str(e))
79 | try:
80 | is_compatible = check_requires_python(
81 | requires_python,
82 | version_info=version_info,
83 | )
84 | except specifiers.InvalidSpecifier as exc:
85 | logger.warning(
86 | "Package %r has an invalid Requires-Python: %s", dist.raw_name, exc
87 | )
88 | return
89 |
90 | if is_compatible:
91 | return
92 |
93 | version = ".".join(map(str, version_info))
94 | if ignore_requires_python:
95 | logger.debug(
96 | "Ignoring failed Requires-Python check for package %r: %s not in %r",
97 | dist.raw_name,
98 | version,
99 | requires_python,
100 | )
101 | return
102 |
103 | raise UnsupportedPythonVersion(
104 | f"Package {dist.raw_name!r} requires a different Python: "
105 | f"{version} not in {requires_python!r}"
106 | )
107 |
108 |
109 | class Resolver(BaseResolver):
110 | """Resolves which packages need to be installed/uninstalled to perform \
111 | the requested operation without breaking the requirements of any package.
112 | """
113 |
114 | _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"}
115 |
116 | def __init__(
117 | self,
118 | preparer: RequirementPreparer,
119 | finder: PackageFinder,
120 | wheel_cache: Optional[WheelCache],
121 | make_install_req: InstallRequirementProvider,
122 | use_user_site: bool,
123 | ignore_dependencies: bool,
124 | ignore_installed: bool,
125 | ignore_requires_python: bool,
126 | force_reinstall: bool,
127 | upgrade_strategy: str,
128 | py_version_info: Optional[Tuple[int, ...]] = None,
129 | ) -> None:
130 | super().__init__()
131 | assert upgrade_strategy in self._allowed_strategies
132 |
133 | if py_version_info is None:
134 | py_version_info = sys.version_info[:3]
135 | else:
136 | py_version_info = normalize_version_info(py_version_info)
137 |
138 | self._py_version_info = py_version_info
139 |
140 | self.preparer = preparer
141 | self.finder = finder
142 | self.wheel_cache = wheel_cache
143 |
144 | self.upgrade_strategy = upgrade_strategy
145 | self.force_reinstall = force_reinstall
146 | self.ignore_dependencies = ignore_dependencies
147 | self.ignore_installed = ignore_installed
148 | self.ignore_requires_python = ignore_requires_python
149 | self.use_user_site = use_user_site
150 | self._make_install_req = make_install_req
151 |
152 | self._discovered_dependencies: DiscoveredDependencies = defaultdict(list)
153 |
154 | def resolve(
155 | self, root_reqs: List[InstallRequirement], check_supported_wheels: bool
156 | ) -> RequirementSet:
157 | """Resolve what operations need to be done
158 |
159 | As a side-effect of this method, the packages (and their dependencies)
160 | are downloaded, unpacked and prepared for installation. This
161 | preparation is done by ``pip.operations.prepare``.
162 |
163 | Once PyPI has static dependency metadata available, it would be
164 | possible to move the preparation to become a step separated from
165 | dependency resolution.
166 | """
167 | requirement_set = RequirementSet(check_supported_wheels=check_supported_wheels)
168 | for req in root_reqs:
169 | if req.constraint:
170 | check_invalid_constraint_type(req)
171 | self._add_requirement_to_set(requirement_set, req)
172 |
173 | # Actually prepare the files, and collect any exceptions. Most hash
174 | # exceptions cannot be checked ahead of time, because
175 | # _populate_link() needs to be called before we can make decisions
176 | # based on link type.
177 | discovered_reqs: List[InstallRequirement] = []
178 | hash_errors = HashErrors()
179 | for req in chain(requirement_set.all_requirements, discovered_reqs):
180 | try:
181 | discovered_reqs.extend(self._resolve_one(requirement_set, req))
182 | except HashError as exc:
183 | exc.req = req
184 | hash_errors.append(exc)
185 |
186 | if hash_errors:
187 | raise hash_errors
188 |
189 | return requirement_set
190 |
191 | def _add_requirement_to_set(
192 | self,
193 | requirement_set: RequirementSet,
194 | install_req: InstallRequirement,
195 | parent_req_name: Optional[str] = None,
196 | extras_requested: Optional[Iterable[str]] = None,
197 | ) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]:
198 | """Add install_req as a requirement to install.
199 |
200 | :param parent_req_name: The name of the requirement that needed this
201 | added. The name is used because when multiple unnamed requirements
202 | resolve to the same name, we could otherwise end up with dependency
203 | links that point outside the Requirements set. parent_req must
204 | already be added. Note that None implies that this is a user
205 | supplied requirement, vs an inferred one.
206 | :param extras_requested: an iterable of extras used to evaluate the
207 | environment markers.
208 | :return: Additional requirements to scan. That is either [] if
209 | the requirement is not applicable, or [install_req] if the
210 | requirement is applicable and has just been added.
211 | """
212 | # If the markers do not match, ignore this requirement.
213 | if not install_req.match_markers(extras_requested):
214 | logger.info(
215 | "Ignoring %s: markers '%s' don't match your environment",
216 | install_req.name,
217 | install_req.markers,
218 | )
219 | return [], None
220 |
221 | # If the wheel is not supported, raise an error.
222 | # Should check this after filtering out based on environment markers to
223 | # allow specifying different wheels based on the environment/OS, in a
224 | # single requirements file.
225 | if install_req.link and install_req.link.is_wheel:
226 | wheel = Wheel(install_req.link.filename)
227 | tags = compatibility_tags.get_supported()
228 | if requirement_set.check_supported_wheels and not wheel.supported(tags):
229 | raise InstallationError(
230 | f"{wheel.filename} is not a supported wheel on this platform."
231 | )
232 |
233 | # This next bit is really a sanity check.
234 | assert (
235 | not install_req.user_supplied or parent_req_name is None
236 | ), "a user supplied req shouldn't have a parent"
237 |
238 | # Unnamed requirements are scanned again and the requirement won't be
239 | # added as a dependency until after scanning.
240 | if not install_req.name:
241 | requirement_set.add_unnamed_requirement(install_req)
242 | return [install_req], None
243 |
244 | try:
245 | existing_req: Optional[InstallRequirement] = (
246 | requirement_set.get_requirement(install_req.name)
247 | )
248 | except KeyError:
249 | existing_req = None
250 |
251 | has_conflicting_requirement = (
252 | parent_req_name is None
253 | and existing_req
254 | and not existing_req.constraint
255 | and existing_req.extras == install_req.extras
256 | and existing_req.req
257 | and install_req.req
258 | and existing_req.req.specifier != install_req.req.specifier
259 | )
260 | if has_conflicting_requirement:
261 | raise InstallationError(
262 | f"Double requirement given: {install_req} "
263 | f"(already in {existing_req}, name={install_req.name!r})"
264 | )
265 |
266 | # When no existing requirement exists, add the requirement as a
267 | # dependency and it will be scanned again after.
268 | if not existing_req:
269 | requirement_set.add_named_requirement(install_req)
270 | # We'd want to rescan this requirement later
271 | return [install_req], install_req
272 |
273 | # Assume there's no need to scan, and that we've already
274 | # encountered this for scanning.
275 | if install_req.constraint or not existing_req.constraint:
276 | return [], existing_req
277 |
278 | does_not_satisfy_constraint = install_req.link and not (
279 | existing_req.link and install_req.link.path == existing_req.link.path
280 | )
281 | if does_not_satisfy_constraint:
282 | raise InstallationError(
283 | f"Could not satisfy constraints for '{install_req.name}': "
284 | "installation from path or url cannot be "
285 | "constrained to a version"
286 | )
287 | # If we're now installing a constraint, mark the existing
288 | # object for real installation.
289 | existing_req.constraint = False
290 | # If we're now installing a user supplied requirement,
291 | # mark the existing object as such.
292 | if install_req.user_supplied:
293 | existing_req.user_supplied = True
294 | existing_req.extras = tuple(
295 | sorted(set(existing_req.extras) | set(install_req.extras))
296 | )
297 | logger.debug(
298 | "Setting %s extras to: %s",
299 | existing_req,
300 | existing_req.extras,
301 | )
302 | # Return the existing requirement for addition to the parent and
303 | # scanning again.
304 | return [existing_req], existing_req
305 |
306 | def _is_upgrade_allowed(self, req: InstallRequirement) -> bool:
307 | if self.upgrade_strategy == "to-satisfy-only":
308 | return False
309 | elif self.upgrade_strategy == "eager":
310 | return True
311 | else:
312 | assert self.upgrade_strategy == "only-if-needed"
313 | return req.user_supplied or req.constraint
314 |
315 | def _set_req_to_reinstall(self, req: InstallRequirement) -> None:
316 | """
317 | Set a requirement to be installed.
318 | """
319 | # Don't uninstall the conflict if doing a user install and the
320 | # conflict is not a user install.
321 | assert req.satisfied_by is not None
322 | if not self.use_user_site or req.satisfied_by.in_usersite:
323 | req.should_reinstall = True
324 | req.satisfied_by = None
325 |
326 | def _check_skip_installed(
327 | self, req_to_install: InstallRequirement
328 | ) -> Optional[str]:
329 | """Check if req_to_install should be skipped.
330 |
331 | This will check if the req is installed, and whether we should upgrade
332 | or reinstall it, taking into account all the relevant user options.
333 |
334 | After calling this req_to_install will only have satisfied_by set to
335 | None if the req_to_install is to be upgraded/reinstalled etc. Any
336 | other value will be a dist recording the current thing installed that
337 | satisfies the requirement.
338 |
339 | Note that for vcs urls and the like we can't assess skipping in this
340 | routine - we simply identify that we need to pull the thing down,
341 | then later on it is pulled down and introspected to assess upgrade/
342 | reinstalls etc.
343 |
344 | :return: A text reason for why it was skipped, or None.
345 | """
346 | if self.ignore_installed:
347 | return None
348 |
349 | req_to_install.check_if_exists(self.use_user_site)
350 | if not req_to_install.satisfied_by:
351 | return None
352 |
353 | if self.force_reinstall:
354 | self._set_req_to_reinstall(req_to_install)
355 | return None
356 |
357 | if not self._is_upgrade_allowed(req_to_install):
358 | if self.upgrade_strategy == "only-if-needed":
359 | return "already satisfied, skipping upgrade"
360 | return "already satisfied"
361 |
362 | # Check for the possibility of an upgrade. For link-based
363 | # requirements we have to pull the tree down and inspect to assess
364 | # the version #, so it's handled way down.
365 | if not req_to_install.link:
366 | try:
367 | self.finder.find_requirement(req_to_install, upgrade=True)
368 | except BestVersionAlreadyInstalled:
369 | # Then the best version is installed.
370 | return "already up-to-date"
371 | except DistributionNotFound:
372 | # No distribution found, so we squash the error. It will
373 | # be raised later when we re-try later to do the install.
374 | # Why don't we just raise here?
375 | pass
376 |
377 | self._set_req_to_reinstall(req_to_install)
378 | return None
379 |
380 | def _find_requirement_link(self, req: InstallRequirement) -> Optional[Link]:
381 | upgrade = self._is_upgrade_allowed(req)
382 | best_candidate = self.finder.find_requirement(req, upgrade)
383 | if not best_candidate:
384 | return None
385 |
386 | # Log a warning per PEP 592 if necessary before returning.
387 | link = best_candidate.link
388 | if link.is_yanked:
389 | reason = link.yanked_reason or "<none given>"
390 | msg = (
391 | # Mark this as a unicode string to prevent
392 | # "UnicodeEncodeError: 'ascii' codec can't encode character"
393 | # in Python 2 when the reason contains non-ascii characters.
394 | "The candidate selected for download or install is a "
395 | f"yanked version: {best_candidate}\n"
396 | f"Reason for being yanked: {reason}"
397 | )
398 | logger.warning(msg)
399 |
400 | return link
401 |
402 | def _populate_link(self, req: InstallRequirement) -> None:
403 | """Ensure that if a link can be found for this, that it is found.
404 |
405 | Note that req.link may still be None - if the requirement is already
406 | installed and not needed to be upgraded based on the return value of
407 | _is_upgrade_allowed().
408 |
409 | If preparer.require_hashes is True, don't use the wheel cache, because
410 | cached wheels, always built locally, have different hashes than the
411 | files downloaded from the index server and thus throw false hash
412 | mismatches. Furthermore, cached wheels at present have undeterministic
413 | contents due to file modification times.
414 | """
415 | if req.link is None:
416 | req.link = self._find_requirement_link(req)
417 |
418 | if self.wheel_cache is None or self.preparer.require_hashes:
419 | return
420 |
421 | assert req.link is not None, "_find_requirement_link unexpectedly returned None"
422 | cache_entry = self.wheel_cache.get_cache_entry(
423 | link=req.link,
424 | package_name=req.name,
425 | supported_tags=get_supported(),
426 | )
427 | if cache_entry is not None:
428 | logger.debug("Using cached wheel link: %s", cache_entry.link)
429 | if req.link is req.original_link and cache_entry.persistent:
430 | req.cached_wheel_source_link = req.link
431 | if cache_entry.origin is not None:
432 | req.download_info = cache_entry.origin
433 | else:
434 | # Legacy cache entry that does not have origin.json.
435 | # download_info may miss the archive_info.hashes field.
436 | req.download_info = direct_url_from_link(
437 | req.link, link_is_in_wheel_cache=cache_entry.persistent
438 | )
439 | req.link = cache_entry.link
440 |
441 | def _get_dist_for(self, req: InstallRequirement) -> BaseDistribution:
442 | """Takes a InstallRequirement and returns a single AbstractDist \
443 | representing a prepared variant of the same.
444 | """
445 | if req.editable:
446 | return self.preparer.prepare_editable_requirement(req)
447 |
448 | # satisfied_by is only evaluated by calling _check_skip_installed,
449 | # so it must be None here.
450 | assert req.satisfied_by is None
451 | skip_reason = self._check_skip_installed(req)
452 |
453 | if req.satisfied_by:
454 | return self.preparer.prepare_installed_requirement(req, skip_reason)
455 |
456 | # We eagerly populate the link, since that's our "legacy" behavior.
457 | self._populate_link(req)
458 | dist = self.preparer.prepare_linked_requirement(req)
459 |
460 | # NOTE
461 | # The following portion is for determining if a certain package is
462 | # going to be re-installed/upgraded or not and reporting to the user.
463 | # This should probably get cleaned up in a future refactor.
464 |
465 | # req.req is only avail after unpack for URL
466 | # pkgs repeat check_if_exists to uninstall-on-upgrade
467 | # (#14)
468 | if not self.ignore_installed:
469 | req.check_if_exists(self.use_user_site)
470 |
471 | if req.satisfied_by:
472 | should_modify = (
473 | self.upgrade_strategy != "to-satisfy-only"
474 | or self.force_reinstall
475 | or self.ignore_installed
476 | or req.link.scheme == "file"
477 | )
478 | if should_modify:
479 | self._set_req_to_reinstall(req)
480 | else:
481 | logger.info(
482 | "Requirement already satisfied (use --upgrade to upgrade): %s",
483 | req,
484 | )
485 | return dist
486 |
487 | def _resolve_one(
488 | self,
489 | requirement_set: RequirementSet,
490 | req_to_install: InstallRequirement,
491 | ) -> List[InstallRequirement]:
492 | """Prepare a single requirements file.
493 |
494 | :return: A list of additional InstallRequirements to also install.
495 | """
496 | # Tell user what we are doing for this requirement:
497 | # obtain (editable), skipping, processing (local url), collecting
498 | # (remote url or package name)
499 | if req_to_install.constraint or req_to_install.prepared:
500 | return []
501 |
502 | req_to_install.prepared = True
503 |
504 | # Parse and return dependencies
505 | dist = self._get_dist_for(req_to_install)
506 | # This will raise UnsupportedPythonVersion if the given Python
507 | # version isn't compatible with the distribution's Requires-Python.
508 | _check_dist_requires_python(
509 | dist,
510 | version_info=self._py_version_info,
511 | ignore_requires_python=self.ignore_requires_python,
512 | )
513 |
514 | more_reqs: List[InstallRequirement] = []
515 |
516 | def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None:
517 | # This idiosyncratically converts the Requirement to str and let
518 | # make_install_req then parse it again into Requirement. But this is
519 | # the legacy resolver so I'm just not going to bother refactoring.
520 | sub_install_req = self._make_install_req(str(subreq), req_to_install)
521 | parent_req_name = req_to_install.name
522 | to_scan_again, add_to_parent = self._add_requirement_to_set(
523 | requirement_set,
524 | sub_install_req,
525 | parent_req_name=parent_req_name,
526 | extras_requested=extras_requested,
527 | )
528 | if parent_req_name and add_to_parent:
529 | self._discovered_dependencies[parent_req_name].append(add_to_parent)
530 | more_reqs.extend(to_scan_again)
531 |
532 | with indent_log():
533 | # We add req_to_install before its dependencies, so that we
534 | # can refer to it when adding dependencies.
535 | assert req_to_install.name is not None
536 | if not requirement_set.has_requirement(req_to_install.name):
537 | # 'unnamed' requirements will get added here
538 | # 'unnamed' requirements can only come from being directly
539 | # provided by the user.
540 | assert req_to_install.user_supplied
541 | self._add_requirement_to_set(
542 | requirement_set, req_to_install, parent_req_name=None
543 | )
544 |
545 | if not self.ignore_dependencies:
546 | if req_to_install.extras:
547 | logger.debug(
548 | "Installing extra requirements: %r",
549 | ",".join(req_to_install.extras),
550 | )
551 | missing_requested = sorted(
552 | set(req_to_install.extras) - set(dist.iter_provided_extras())
553 | )
554 | for missing in missing_requested:
555 | logger.warning(
556 | "%s %s does not provide the extra '%s'",
557 | dist.raw_name,
558 | dist.version,
559 | missing,
560 | )
561 |
562 | available_requested = sorted(
563 | set(dist.iter_provided_extras()) & set(req_to_install.extras)
564 | )
565 | for subreq in dist.iter_dependencies(available_requested):
566 | add_req(subreq, extras_requested=available_requested)
567 |
568 | return more_reqs
569 |
570 | def get_installation_order(
571 | self, req_set: RequirementSet
572 | ) -> List[InstallRequirement]:
573 | """Create the installation order.
574 |
575 | The installation order is topological - requirements are installed
576 | before the requiring thing. We break cycles at an arbitrary point,
577 | and make no other guarantees.
578 | """
579 | # The current implementation, which we may change at any point
580 | # installs the user specified things in the order given, except when
581 | # dependencies must come earlier to achieve topological order.
582 | order = []
583 | ordered_reqs: Set[InstallRequirement] = set()
584 |
585 | def schedule(req: InstallRequirement) -> None:
586 | if req.satisfied_by or req in ordered_reqs:
587 | return
588 | if req.constraint:
589 | return
590 | ordered_reqs.add(req)
591 | for dep in self._discovered_dependencies[req.name]:
592 | schedule(dep)
593 | order.append(req)
594 |
595 | for install_req in req_set.requirements.values():
596 | schedule(install_req)
597 | return order
598 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/click/_termui_impl.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | This module contains implementations for the termui module. To keep the
3 | import time of Click down, some infrequently used functionality is
4 | placed in this module and only imported as needed.
5 | """
6 | import contextlib
7 | import math
8 | import os
9 | import sys
10 | import time
11 | import typing as t
12 | from gettext import gettext as _
13 | from io import StringIO
14 | from types import TracebackType
15 |
16 | from ._compat import _default_text_stdout
17 | from ._compat import CYGWIN
18 | from ._compat import get_best_encoding
19 | from ._compat import isatty
20 | from ._compat import open_stream
21 | from ._compat import strip_ansi
22 | from ._compat import term_len
23 | from ._compat import WIN
24 | from .exceptions import ClickException
25 | from .utils import echo
26 |
27 | V = t.TypeVar("V")
28 |
29 | if os.name == "nt":
30 | BEFORE_BAR = "\r"
31 | AFTER_BAR = "\n"
32 | else:
33 | BEFORE_BAR = "\r\033[?25l"
34 | AFTER_BAR = "\033[?25h\n"
35 |
36 |
37 | class ProgressBar(t.Generic[V]):
38 | def __init__(
39 | self,
40 | iterable: t.Optional[t.Iterable[V]],
41 | length: t.Optional[int] = None,
42 | fill_char: str = "#",
43 | empty_char: str = " ",
44 | bar_template: str = "%(bar)s",
45 | info_sep: str = " ",
46 | show_eta: bool = True,
47 | show_percent: t.Optional[bool] = None,
48 | show_pos: bool = False,
49 | item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None,
50 | label: t.Optional[str] = None,
51 | file: t.Optional[t.TextIO] = None,
52 | color: t.Optional[bool] = None,
53 | update_min_steps: int = 1,
54 | width: int = 30,
55 | ) -> None:
56 | self.fill_char = fill_char
57 | self.empty_char = empty_char
58 | self.bar_template = bar_template
59 | self.info_sep = info_sep
60 | self.show_eta = show_eta
61 | self.show_percent = show_percent
62 | self.show_pos = show_pos
63 | self.item_show_func = item_show_func
64 | self.label: str = label or ""
65 |
66 | if file is None:
67 | file = _default_text_stdout()
68 |
69 | # There are no standard streams attached to write to. For example,
70 | # pythonw on Windows.
71 | if file is None:
72 | file = StringIO()
73 |
74 | self.file = file
75 | self.color = color
76 | self.update_min_steps = update_min_steps
77 | self._completed_intervals = 0
78 | self.width: int = width
79 | self.autowidth: bool = width == 0
80 |
81 | if length is None:
82 | from operator import length_hint
83 |
84 | length = length_hint(iterable, -1)
85 |
86 | if length == -1:
87 | length = None
88 | if iterable is None:
89 | if length is None:
90 | raise TypeError("iterable or length is required")
91 | iterable = t.cast(t.Iterable[V], range(length))
92 | self.iter: t.Iterable[V] = iter(iterable)
93 | self.length = length
94 | self.pos = 0
95 | self.avg: t.List[float] = []
96 | self.last_eta: float
97 | self.start: float
98 | self.start = self.last_eta = time.time()
99 | self.eta_known: bool = False
100 | self.finished: bool = False
101 | self.max_width: t.Optional[int] = None
102 | self.entered: bool = False
103 | self.current_item: t.Optional[V] = None
104 | self.is_hidden: bool = not isatty(self.file)
105 | self._last_line: t.Optional[str] = None
106 |
107 | def __enter__(self) -> "ProgressBar[V]":
108 | self.entered = True
109 | self.render_progress()
110 | return self
111 |
112 | def __exit__(
113 | self,
114 | exc_type: t.Optional[t.Type[BaseException]],
115 | exc_value: t.Optional[BaseException],
116 | tb: t.Optional[TracebackType],
117 | ) -> None:
118 | self.render_finish()
119 |
120 | def __iter__(self) -> t.Iterator[V]:
121 | if not self.entered:
122 | raise RuntimeError("You need to use progress bars in a with block.")
123 | self.render_progress()
124 | return self.generator()
125 |
126 | def __next__(self) -> V:
127 | # Iteration is defined in terms of a generator function,
128 | # returned by iter(self); use that to define next(). This works
129 | # because `self.iter` is an iterable consumed by that generator,
130 | # so it is re-entry safe. Calling `next(self.generator())`
131 | # twice works and does "what you want".
132 | return next(iter(self))
133 |
134 | def render_finish(self) -> None:
135 | if self.is_hidden:
136 | return
137 | self.file.write(AFTER_BAR)
138 | self.file.flush()
139 |
140 | @property
141 | def pct(self) -> float:
142 | if self.finished:
143 | return 1.0
144 | return min(self.pos / (float(self.length or 1) or 1), 1.0)
145 |
146 | @property
147 | def time_per_iteration(self) -> float:
148 | if not self.avg:
149 | return 0.0
150 | return sum(self.avg) / float(len(self.avg))
151 |
152 | @property
153 | def eta(self) -> float:
154 | if self.length is not None and not self.finished:
155 | return self.time_per_iteration * (self.length - self.pos)
156 | return 0.0
157 |
158 | def format_eta(self) -> str:
159 | if self.eta_known:
160 | t = int(self.eta)
161 | seconds = t % 60
162 | t //= 60
163 | minutes = t % 60
164 | t //= 60
165 | hours = t % 24
166 | t //= 24
167 | if t > 0:
168 | return f"{t}d {hours:02}:{minutes:02}:{seconds:02}"
169 | else:
170 | return f"{hours:02}:{minutes:02}:{seconds:02}"
171 | return ""
172 |
173 | def format_pos(self) -> str:
174 | pos = str(self.pos)
175 | if self.length is not None:
176 | pos += f"/{self.length}"
177 | return pos
178 |
179 | def format_pct(self) -> str:
180 | return f"{int(self.pct * 100): 4}%"[1:]
181 |
182 | def format_bar(self) -> str:
183 | if self.length is not None:
184 | bar_length = int(self.pct * self.width)
185 | bar = self.fill_char * bar_length
186 | bar += self.empty_char * (self.width - bar_length)
187 | elif self.finished:
188 | bar = self.fill_char * self.width
189 | else:
190 | chars = list(self.empty_char * (self.width or 1))
191 | if self.time_per_iteration != 0:
192 | chars[
193 | int(
194 | (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5)
195 | * self.width
196 | )
197 | ] = self.fill_char
198 | bar = "".join(chars)
199 | return bar
200 |
201 | def format_progress_line(self) -> str:
202 | show_percent = self.show_percent
203 |
204 | info_bits = []
205 | if self.length is not None and show_percent is None:
206 | show_percent = not self.show_pos
207 |
208 | if self.show_pos:
209 | info_bits.append(self.format_pos())
210 | if show_percent:
211 | info_bits.append(self.format_pct())
212 | if self.show_eta and self.eta_known and not self.finished:
213 | info_bits.append(self.format_eta())
214 | if self.item_show_func is not None:
215 | item_info = self.item_show_func(self.current_item)
216 | if item_info is not None:
217 | info_bits.append(item_info)
218 |
219 | return (
220 | self.bar_template
221 | % {
222 | "label": self.label,
223 | "bar": self.format_bar(),
224 | "info": self.info_sep.join(info_bits),
225 | }
226 | ).rstrip()
227 |
228 | def render_progress(self) -> None:
229 | import shutil
230 |
231 | if self.is_hidden:
232 | # Only output the label as it changes if the output is not a
233 | # TTY. Use file=stderr if you expect to be piping stdout.
234 | if self._last_line != self.label:
235 | self._last_line = self.label
236 | echo(self.label, file=self.file, color=self.color)
237 |
238 | return
239 |
240 | buf = []
241 | # Update width in case the terminal has been resized
242 | if self.autowidth:
243 | old_width = self.width
244 | self.width = 0
245 | clutter_length = term_len(self.format_progress_line())
246 | new_width = max(0, shutil.get_terminal_size().columns - clutter_length)
247 | if new_width < old_width:
248 | buf.append(BEFORE_BAR)
249 | buf.append(" " * self.max_width) # type: ignore
250 | self.max_width = new_width
251 | self.width = new_width
252 |
253 | clear_width = self.width
254 | if self.max_width is not None:
255 | clear_width = self.max_width
256 |
257 | buf.append(BEFORE_BAR)
258 | line = self.format_progress_line()
259 | line_len = term_len(line)
260 | if self.max_width is None or self.max_width < line_len:
261 | self.max_width = line_len
262 |
263 | buf.append(line)
264 | buf.append(" " * (clear_width - line_len))
265 | line = "".join(buf)
266 | # Render the line only if it changed.
267 |
268 | if line != self._last_line:
269 | self._last_line = line
270 | echo(line, file=self.file, color=self.color, nl=False)
271 | self.file.flush()
272 |
273 | def make_step(self, n_steps: int) -> None:
274 | self.pos += n_steps
275 | if self.length is not None and self.pos >= self.length:
276 | self.finished = True
277 |
278 | if (time.time() - self.last_eta) < 1.0:
279 | return
280 |
281 | self.last_eta = time.time()
282 |
283 | # self.avg is a rolling list of length <= 7 of steps where steps are
284 | # defined as time elapsed divided by the total progress through
285 | # self.length.
286 | if self.pos:
287 | step = (time.time() - self.start) / self.pos
288 | else:
289 | step = time.time() - self.start
290 |
291 | self.avg = self.avg[-6:] + [step]
292 |
293 | self.eta_known = self.length is not None
294 |
295 | def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None:
296 | """Update the progress bar by advancing a specified number of
297 | steps, and optionally set the ``current_item`` for this new
298 | position.
299 |
300 | :param n_steps: Number of steps to advance.
301 | :param current_item: Optional item to set as ``current_item``
302 | for the updated position.
303 |
304 | .. versionchanged:: 8.0
305 | Added the ``current_item`` optional parameter.
306 |
307 | .. versionchanged:: 8.0
308 | Only render when the number of steps meets the
309 | ``update_min_steps`` threshold.
310 | """
311 | if current_item is not None:
312 | self.current_item = current_item
313 |
314 | self._completed_intervals += n_steps
315 |
316 | if self._completed_intervals >= self.update_min_steps:
317 | self.make_step(self._completed_intervals)
318 | self.render_progress()
319 | self._completed_intervals = 0
320 |
321 | def finish(self) -> None:
322 | self.eta_known = False
323 | self.current_item = None
324 | self.finished = True
325 |
326 | def generator(self) -> t.Iterator[V]:
327 | """Return a generator which yields the items added to the bar
328 | during construction, and updates the progress bar *after* the
329 | yielded block returns.
330 | """
331 | # WARNING: the iterator interface for `ProgressBar` relies on
332 | # this and only works because this is a simple generator which
333 | # doesn't create or manage additional state. If this function
334 | # changes, the impact should be evaluated both against
335 | # `iter(bar)` and `next(bar)`. `next()` in particular may call
336 | # `self.generator()` repeatedly, and this must remain safe in
337 | # order for that interface to work.
338 | if not self.entered:
339 | raise RuntimeError("You need to use progress bars in a with block.")
340 |
341 | if self.is_hidden:
342 | yield from self.iter
343 | else:
344 | for rv in self.iter:
345 | self.current_item = rv
346 |
347 | # This allows show_item_func to be updated before the
348 | # item is processed. Only trigger at the beginning of
349 | # the update interval.
350 | if self._completed_intervals == 0:
351 | self.render_progress()
352 |
353 | yield rv
354 | self.update(1)
355 |
356 | self.finish()
357 | self.render_progress()
358 |
359 |
360 | def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None:
361 | """Decide what method to use for paging through text."""
362 | stdout = _default_text_stdout()
363 |
364 | # There are no standard streams attached to write to. For example,
365 | # pythonw on Windows.
366 | if stdout is None:
367 | stdout = StringIO()
368 |
369 | if not isatty(sys.stdin) or not isatty(stdout):
370 | return _nullpager(stdout, generator, color)
371 | pager_cmd = (os.environ.get("PAGER", None) or "").strip()
372 | if pager_cmd:
373 | if WIN:
374 | return _tempfilepager(generator, pager_cmd, color)
375 | return _pipepager(generator, pager_cmd, color)
376 | if os.environ.get("TERM") in ("dumb", "emacs"):
377 | return _nullpager(stdout, generator, color)
378 | if WIN or sys.platform.startswith("os2"):
379 | return _tempfilepager(generator, "more <", color)
380 | if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0:
381 | return _pipepager(generator, "less", color)
382 |
383 | import tempfile
384 |
385 | fd, filename = tempfile.mkstemp()
386 | os.close(fd)
387 | try:
388 | if hasattr(os, "system") and os.system(f'more "{filename}"') == 0:
389 | return _pipepager(generator, "more", color)
390 | return _nullpager(stdout, generator, color)
391 | finally:
392 | os.unlink(filename)
393 |
394 |
395 | def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None:
396 | """Page through text by feeding it to another program. Invoking a
397 | pager through this might support colors.
398 | """
399 | import subprocess
400 |
401 | env = dict(os.environ)
402 |
403 | # If we're piping to less we might support colors under the
404 | # condition that
405 | cmd_detail = cmd.rsplit("/", 1)[-1].split()
406 | if color is None and cmd_detail[0] == "less":
407 | less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}"
408 | if not less_flags:
409 | env["LESS"] = "-R"
410 | color = True
411 | elif "r" in less_flags or "R" in less_flags:
412 | color = True
413 |
414 | c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env)
415 | stdin = t.cast(t.BinaryIO, c.stdin)
416 | encoding = get_best_encoding(stdin)
417 | try:
418 | for text in generator:
419 | if not color:
420 | text = strip_ansi(text)
421 |
422 | stdin.write(text.encode(encoding, "replace"))
423 | except (OSError, KeyboardInterrupt):
424 | pass
425 | else:
426 | stdin.close()
427 |
428 | # Less doesn't respect ^C, but catches it for its own UI purposes (aborting
429 | # search or other commands inside less).
430 | #
431 | # That means when the user hits ^C, the parent process (click) terminates,
432 | # but less is still alive, paging the output and messing up the terminal.
433 | #
434 | # If the user wants to make the pager exit on ^C, they should set
435 | # `LESS='-K'`. It's not our decision to make.
436 | while True:
437 | try:
438 | c.wait()
439 | except KeyboardInterrupt:
440 | pass
441 | else:
442 | break
443 |
444 |
445 | def _tempfilepager(
446 | generator: t.Iterable[str], cmd: str, color: t.Optional[bool]
447 | ) -> None:
448 | """Page through text by invoking a program on a temporary file."""
449 | import tempfile
450 |
451 | fd, filename = tempfile.mkstemp()
452 | # TODO: This never terminates if the passed generator never terminates.
453 | text = "".join(generator)
454 | if not color:
455 | text = strip_ansi(text)
456 | encoding = get_best_encoding(sys.stdout)
457 | with open_stream(filename, "wb")[0] as f:
458 | f.write(text.encode(encoding))
459 | try:
460 | os.system(f'{cmd} "{filename}"')
461 | finally:
462 | os.close(fd)
463 | os.unlink(filename)
464 |
465 |
466 | def _nullpager(
467 | stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool]
468 | ) -> None:
469 | """Simply print unformatted text. This is the ultimate fallback."""
470 | for text in generator:
471 | if not color:
472 | text = strip_ansi(text)
473 | stream.write(text)
474 |
475 |
476 | class Editor:
477 | def __init__(
478 | self,
479 | editor: t.Optional[str] = None,
480 | env: t.Optional[t.Mapping[str, str]] = None,
481 | require_save: bool = True,
482 | extension: str = ".txt",
483 | ) -> None:
484 | self.editor = editor
485 | self.env = env
486 | self.require_save = require_save
487 | self.extension = extension
488 |
489 | def get_editor(self) -> str:
490 | if self.editor is not None:
491 | return self.editor
492 | for key in "VISUAL", "EDITOR":
493 | rv = os.environ.get(key)
494 | if rv:
495 | return rv
496 | if WIN:
497 | return "notepad"
498 | for editor in "sensible-editor", "vim", "nano":
499 | if os.system(f"which {editor} >/dev/null 2>&1") == 0:
500 | return editor
501 | return "vi"
502 |
503 | def edit_file(self, filename: str) -> None:
504 | import subprocess
505 |
506 | editor = self.get_editor()
507 | environ: t.Optional[t.Dict[str, str]] = None
508 |
509 | if self.env:
510 | environ = os.environ.copy()
511 | environ.update(self.env)
512 |
513 | try:
514 | c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True)
515 | exit_code = c.wait()
516 | if exit_code != 0:
517 | raise ClickException(
518 | _("{editor}: Editing failed").format(editor=editor)
519 | )
520 | except OSError as e:
521 | raise ClickException(
522 | _("{editor}: Editing failed: {e}").format(editor=editor, e=e)
523 | ) from e
524 |
525 | def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]:
526 | import tempfile
527 |
528 | if not text:
529 | data = b""
530 | elif isinstance(text, (bytes, bytearray)):
531 | data = text
532 | else:
533 | if text and not text.endswith("\n"):
534 | text += "\n"
535 |
536 | if WIN:
537 | data = text.replace("\n", "\r\n").encode("utf-8-sig")
538 | else:
539 | data = text.encode("utf-8")
540 |
541 | fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension)
542 | f: t.BinaryIO
543 |
544 | try:
545 | with os.fdopen(fd, "wb") as f:
546 | f.write(data)
547 |
548 | # If the filesystem resolution is 1 second, like Mac OS
549 | # 10.12 Extended, or 2 seconds, like FAT32, and the editor
550 | # closes very fast, require_save can fail. Set the modified
551 | # time to be 2 seconds in the past to work around this.
552 | os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2))
553 | # Depending on the resolution, the exact value might not be
554 | # recorded, so get the new recorded value.
555 | timestamp = os.path.getmtime(name)
556 |
557 | self.edit_file(name)
558 |
559 | if self.require_save and os.path.getmtime(name) == timestamp:
560 | return None
561 |
562 | with open(name, "rb") as f:
563 | rv = f.read()
564 |
565 | if isinstance(text, (bytes, bytearray)):
566 | return rv
567 |
568 | return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore
569 | finally:
570 | os.unlink(name)
571 |
572 |
573 | def open_url(url: str, wait: bool = False, locate: bool = False) -> int:
574 | import subprocess
575 |
576 | def _unquote_file(url: str) -> str:
577 | from urllib.parse import unquote
578 |
579 | if url.startswith("file://"):
580 | url = unquote(url[7:])
581 |
582 | return url
583 |
584 | if sys.platform == "darwin":
585 | args = ["open"]
586 | if wait:
587 | args.append("-W")
588 | if locate:
589 | args.append("-R")
590 | args.append(_unquote_file(url))
591 | null = open("/dev/null", "w")
592 | try:
593 | return subprocess.Popen(args, stderr=null).wait()
594 | finally:
595 | null.close()
596 | elif WIN:
597 | if locate:
598 | url = _unquote_file(url.replace('"', ""))
599 | args = f'explorer /select,"{url}"'
600 | else:
601 | url = url.replace('"', "")
602 | wait_str = "/WAIT" if wait else ""
603 | args = f'start {wait_str} "" "{url}"'
604 | return os.system(args)
605 | elif CYGWIN:
606 | if locate:
607 | url = os.path.dirname(_unquote_file(url).replace('"', ""))
608 | args = f'cygstart "{url}"'
609 | else:
610 | url = url.replace('"', "")
611 | wait_str = "-w" if wait else ""
612 | args = f'cygstart {wait_str} "{url}"'
613 | return os.system(args)
614 |
615 | try:
616 | if locate:
617 | url = os.path.dirname(_unquote_file(url)) or "."
618 | else:
619 | url = _unquote_file(url)
620 | c = subprocess.Popen(["xdg-open", url])
621 | if wait:
622 | return c.wait()
623 | return 0
624 | except OSError:
625 | if url.startswith(("http://", "https://")) and not locate and not wait:
626 | import webbrowser
627 |
628 | webbrowser.open(url)
629 | return 0
630 | return 1
631 |
632 |
633 | def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]:
634 | if ch == "\x03":
635 | raise KeyboardInterrupt()
636 |
637 | if ch == "\x04" and not WIN: # Unix-like, Ctrl+D
638 | raise EOFError()
639 |
640 | if ch == "\x1a" and WIN: # Windows, Ctrl+Z
641 | raise EOFError()
642 |
643 | return None
644 |
645 |
646 | if WIN:
647 | import msvcrt
648 |
649 | @contextlib.contextmanager
650 | def raw_terminal() -> t.Iterator[int]:
651 | yield -1
652 |
653 | def getchar(echo: bool) -> str:
654 | # The function `getch` will return a bytes object corresponding to
655 | # the pressed character. Since Windows 10 build 1803, it will also
656 | # return \x00 when called a second time after pressing a regular key.
657 | #
658 | # `getwch` does not share this probably-bugged behavior. Moreover, it
659 | # returns a Unicode object by default, which is what we want.
660 | #
661 | # Either of these functions will return \x00 or \xe0 to indicate
662 | # a special key, and you need to call the same function again to get
663 | # the "rest" of the code. The fun part is that \u00e0 is
664 | # "latin small letter a with grave", so if you type that on a French
665 | # keyboard, you _also_ get a \xe0.
666 | # E.g., consider the Up arrow. This returns \xe0 and then \x48. The
667 | # resulting Unicode string reads as "a with grave" + "capital H".
668 | # This is indistinguishable from when the user actually types
669 | # "a with grave" and then "capital H".
670 | #
671 | # When \xe0 is returned, we assume it's part of a special-key sequence
672 | # and call `getwch` again, but that means that when the user types
673 | # the \u00e0 character, `getchar` doesn't return until a second
674 | # character is typed.
675 | # The alternative is returning immediately, but that would mess up
676 | # cross-platform handling of arrow keys and others that start with
677 | # \xe0. Another option is using `getch`, but then we can't reliably
678 | # read non-ASCII characters, because return values of `getch` are
679 | # limited to the current 8-bit codepage.
680 | #
681 | # Anyway, Click doesn't claim to do this Right(tm), and using `getwch`
682 | # is doing the right thing in more situations than with `getch`.
683 | func: t.Callable[[], str]
684 |
685 | if echo:
686 | func = msvcrt.getwche # type: ignore
687 | else:
688 | func = msvcrt.getwch # type: ignore
689 |
690 | rv = func()
691 |
692 | if rv in ("\x00", "\xe0"):
693 | # \x00 and \xe0 are control characters that indicate special key,
694 | # see above.
695 | rv += func()
696 |
697 | _translate_ch_to_exc(rv)
698 | return rv
699 |
700 | else:
701 | import tty
702 | import termios
703 |
704 | @contextlib.contextmanager
705 | def raw_terminal() -> t.Iterator[int]:
706 | f: t.Optional[t.TextIO]
707 | fd: int
708 |
709 | if not isatty(sys.stdin):
710 | f = open("/dev/tty")
711 | fd = f.fileno()
712 | else:
713 | fd = sys.stdin.fileno()
714 | f = None
715 |
716 | try:
717 | old_settings = termios.tcgetattr(fd)
718 |
719 | try:
720 | tty.setraw(fd)
721 | yield fd
722 | finally:
723 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
724 | sys.stdout.flush()
725 |
726 | if f is not None:
727 | f.close()
728 | except termios.error:
729 | pass
730 |
731 | def getchar(echo: bool) -> str:
732 | with raw_terminal() as fd:
733 | ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace")
734 |
735 | if echo and isatty(sys.stdout):
736 | sys.stdout.write(ch)
737 |
738 | _translate_ch_to_exc(ch)
739 | return ch
740 |
```