This is page 25 of 168. Use http://codebase.md/romanshablio/mcp_server?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .DS_Store
├── .venv
│ ├── __pycache__
│ │ └── hello.cpython-312.pyc
│ ├── bin
│ │ ├── activate
│ │ ├── activate.csh
│ │ ├── activate.fish
│ │ ├── Activate.ps1
│ │ ├── flask
│ │ ├── normalizer
│ │ ├── pip
│ │ ├── pip3
│ │ ├── pip3.12
│ │ ├── python
│ │ ├── python3
│ │ └── python3.12
│ ├── hello.py
│ ├── lib
│ │ └── python3.12
│ │ └── site-packages
│ │ ├── beautifulsoup4-4.12.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ ├── AUTHORS
│ │ │ │ └── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── blinker
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _utilities.cpython-312.pyc
│ │ │ │ └── base.cpython-312.pyc
│ │ │ ├── _utilities.py
│ │ │ ├── base.py
│ │ │ └── py.typed
│ │ ├── blinker-1.8.2.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── bs4
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── css.cpython-312.pyc
│ │ │ │ ├── dammit.cpython-312.pyc
│ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ ├── element.cpython-312.pyc
│ │ │ │ └── formatter.cpython-312.pyc
│ │ │ ├── builder
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _html5lib.cpython-312.pyc
│ │ │ │ │ ├── _htmlparser.cpython-312.pyc
│ │ │ │ │ └── _lxml.cpython-312.pyc
│ │ │ │ ├── _html5lib.py
│ │ │ │ ├── _htmlparser.py
│ │ │ │ └── _lxml.py
│ │ │ ├── css.py
│ │ │ ├── dammit.py
│ │ │ ├── diagnose.py
│ │ │ ├── element.py
│ │ │ ├── formatter.py
│ │ │ └── tests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── test_builder_registry.cpython-312.pyc
│ │ │ │ ├── test_builder.cpython-312.pyc
│ │ │ │ ├── test_css.cpython-312.pyc
│ │ │ │ ├── test_dammit.cpython-312.pyc
│ │ │ │ ├── test_docs.cpython-312.pyc
│ │ │ │ ├── test_element.cpython-312.pyc
│ │ │ │ ├── test_formatter.cpython-312.pyc
│ │ │ │ ├── test_fuzz.cpython-312.pyc
│ │ │ │ ├── test_html5lib.cpython-312.pyc
│ │ │ │ ├── test_htmlparser.cpython-312.pyc
│ │ │ │ ├── test_lxml.cpython-312.pyc
│ │ │ │ ├── test_navigablestring.cpython-312.pyc
│ │ │ │ ├── test_pageelement.cpython-312.pyc
│ │ │ │ ├── test_soup.cpython-312.pyc
│ │ │ │ ├── test_tag.cpython-312.pyc
│ │ │ │ └── test_tree.cpython-312.pyc
│ │ │ ├── fuzz
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase
│ │ │ │ ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase
│ │ │ │ ├── crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase
│ │ │ │ └── crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase
│ │ │ ├── test_builder_registry.py
│ │ │ ├── test_builder.py
│ │ │ ├── test_css.py
│ │ │ ├── test_dammit.py
│ │ │ ├── test_docs.py
│ │ │ ├── test_element.py
│ │ │ ├── test_formatter.py
│ │ │ ├── test_fuzz.py
│ │ │ ├── test_html5lib.py
│ │ │ ├── test_htmlparser.py
│ │ │ ├── test_lxml.py
│ │ │ ├── test_navigablestring.py
│ │ │ ├── test_pageelement.py
│ │ │ ├── test_soup.py
│ │ │ ├── test_tag.py
│ │ │ └── test_tree.py
│ │ ├── certifi
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── core.cpython-312.pyc
│ │ │ ├── cacert.pem
│ │ │ ├── core.py
│ │ │ └── py.typed
│ │ ├── certifi-2024.8.30.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── charset_normalizer
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── cd.cpython-312.pyc
│ │ │ │ ├── constant.cpython-312.pyc
│ │ │ │ ├── legacy.cpython-312.pyc
│ │ │ │ ├── md.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── version.cpython-312.pyc
│ │ │ ├── api.py
│ │ │ ├── cd.py
│ │ │ ├── cli
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __main__.py
│ │ │ │ └── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── __main__.cpython-312.pyc
│ │ │ ├── constant.py
│ │ │ ├── legacy.py
│ │ │ ├── md__mypyc.cpython-312-darwin.so
│ │ │ ├── md.cpython-312-darwin.so
│ │ │ ├── md.py
│ │ │ ├── models.py
│ │ │ ├── py.typed
│ │ │ ├── utils.py
│ │ │ └── version.py
│ │ ├── charset_normalizer-3.4.0.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── click
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ ├── _termui_impl.cpython-312.pyc
│ │ │ │ ├── _textwrap.cpython-312.pyc
│ │ │ │ ├── _winconsole.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── decorators.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formatting.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── shell_completion.cpython-312.pyc
│ │ │ │ ├── termui.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── types.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── _compat.py
│ │ │ ├── _termui_impl.py
│ │ │ ├── _textwrap.py
│ │ │ ├── _winconsole.py
│ │ │ ├── core.py
│ │ │ ├── decorators.py
│ │ │ ├── exceptions.py
│ │ │ ├── formatting.py
│ │ │ ├── globals.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── shell_completion.py
│ │ │ ├── termui.py
│ │ │ ├── testing.py
│ │ │ ├── types.py
│ │ │ └── utils.py
│ │ ├── click-8.1.7.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.rst
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── fake_useragent
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ ├── fake.cpython-312.pyc
│ │ │ │ ├── log.cpython-312.pyc
│ │ │ │ ├── settings.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── data
│ │ │ │ └── browsers.json
│ │ │ ├── errors.py
│ │ │ ├── fake.py
│ │ │ ├── log.py
│ │ │ ├── settings.py
│ │ │ └── utils.py
│ │ ├── fake_useragent-1.5.1.dist-info
│ │ │ ├── AUTHORS
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── flask
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ ├── cli.cpython-312.pyc
│ │ │ │ ├── config.cpython-312.pyc
│ │ │ │ ├── ctx.cpython-312.pyc
│ │ │ │ ├── debughelpers.cpython-312.pyc
│ │ │ │ ├── globals.cpython-312.pyc
│ │ │ │ ├── helpers.cpython-312.pyc
│ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── signals.cpython-312.pyc
│ │ │ │ ├── templating.cpython-312.pyc
│ │ │ │ ├── testing.cpython-312.pyc
│ │ │ │ ├── typing.cpython-312.pyc
│ │ │ │ ├── views.cpython-312.pyc
│ │ │ │ └── wrappers.cpython-312.pyc
│ │ │ ├── app.py
│ │ │ ├── blueprints.py
│ │ │ ├── cli.py
│ │ │ ├── config.py
│ │ │ ├── ctx.py
│ │ │ ├── debughelpers.py
│ │ │ ├── globals.py
│ │ │ ├── helpers.py
│ │ │ ├── json
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ └── tag.cpython-312.pyc
│ │ │ │ ├── provider.py
│ │ │ │ └── tag.py
│ │ │ ├── logging.py
│ │ │ ├── py.typed
│ │ │ ├── sansio
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── app.cpython-312.pyc
│ │ │ │ │ ├── blueprints.cpython-312.pyc
│ │ │ │ │ └── scaffold.cpython-312.pyc
│ │ │ │ ├── app.py
│ │ │ │ ├── blueprints.py
│ │ │ │ ├── README.md
│ │ │ │ └── scaffold.py
│ │ │ ├── sessions.py
│ │ │ ├── signals.py
│ │ │ ├── templating.py
│ │ │ ├── testing.py
│ │ │ ├── typing.py
│ │ │ ├── views.py
│ │ │ └── wrappers.py
│ │ ├── flask-3.0.3.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ └── WHEEL
│ │ ├── idna
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ ├── codec.py
│ │ │ ├── compat.py
│ │ │ ├── core.py
│ │ │ ├── idnadata.py
│ │ │ ├── intranges.py
│ │ │ ├── package_data.py
│ │ │ ├── py.typed
│ │ │ └── uts46data.py
│ │ ├── idna-3.10.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── itsdangerous
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ ├── exc.cpython-312.pyc
│ │ │ │ ├── serializer.cpython-312.pyc
│ │ │ │ ├── signer.cpython-312.pyc
│ │ │ │ ├── timed.cpython-312.pyc
│ │ │ │ └── url_safe.cpython-312.pyc
│ │ │ ├── _json.py
│ │ │ ├── encoding.py
│ │ │ ├── exc.py
│ │ │ ├── py.typed
│ │ │ ├── serializer.py
│ │ │ ├── signer.py
│ │ │ ├── timed.py
│ │ │ └── url_safe.py
│ │ ├── itsdangerous-2.2.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── jinja2
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _identifier.cpython-312.pyc
│ │ │ │ ├── async_utils.cpython-312.pyc
│ │ │ │ ├── bccache.cpython-312.pyc
│ │ │ │ ├── compiler.cpython-312.pyc
│ │ │ │ ├── constants.cpython-312.pyc
│ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ ├── defaults.cpython-312.pyc
│ │ │ │ ├── environment.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ ├── filters.cpython-312.pyc
│ │ │ │ ├── idtracking.cpython-312.pyc
│ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ ├── loaders.cpython-312.pyc
│ │ │ │ ├── meta.cpython-312.pyc
│ │ │ │ ├── nativetypes.cpython-312.pyc
│ │ │ │ ├── nodes.cpython-312.pyc
│ │ │ │ ├── optimizer.cpython-312.pyc
│ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ ├── runtime.cpython-312.pyc
│ │ │ │ ├── sandbox.cpython-312.pyc
│ │ │ │ ├── tests.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── visitor.cpython-312.pyc
│ │ │ ├── _identifier.py
│ │ │ ├── async_utils.py
│ │ │ ├── bccache.py
│ │ │ ├── compiler.py
│ │ │ ├── constants.py
│ │ │ ├── debug.py
│ │ │ ├── defaults.py
│ │ │ ├── environment.py
│ │ │ ├── exceptions.py
│ │ │ ├── ext.py
│ │ │ ├── filters.py
│ │ │ ├── idtracking.py
│ │ │ ├── lexer.py
│ │ │ ├── loaders.py
│ │ │ ├── meta.py
│ │ │ ├── nativetypes.py
│ │ │ ├── nodes.py
│ │ │ ├── optimizer.py
│ │ │ ├── parser.py
│ │ │ ├── py.typed
│ │ │ ├── runtime.py
│ │ │ ├── sandbox.py
│ │ │ ├── tests.py
│ │ │ ├── utils.py
│ │ │ └── visitor.py
│ │ ├── jinja2-3.1.4.dist-info
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── lxml
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _elementpath.cpython-312.pyc
│ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ ├── cssselect.cpython-312.pyc
│ │ │ │ ├── doctestcompare.cpython-312.pyc
│ │ │ │ ├── ElementInclude.cpython-312.pyc
│ │ │ │ ├── pyclasslookup.cpython-312.pyc
│ │ │ │ ├── sax.cpython-312.pyc
│ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ ├── _elementpath.cpython-312-darwin.so
│ │ │ ├── _elementpath.py
│ │ │ ├── apihelpers.pxi
│ │ │ ├── builder.cpython-312-darwin.so
│ │ │ ├── builder.py
│ │ │ ├── classlookup.pxi
│ │ │ ├── cleanup.pxi
│ │ │ ├── cssselect.py
│ │ │ ├── debug.pxi
│ │ │ ├── docloader.pxi
│ │ │ ├── doctestcompare.py
│ │ │ ├── dtd.pxi
│ │ │ ├── ElementInclude.py
│ │ │ ├── etree_api.h
│ │ │ ├── etree.cpython-312-darwin.so
│ │ │ ├── etree.h
│ │ │ ├── etree.pyx
│ │ │ ├── extensions.pxi
│ │ │ ├── html
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── _diffcommand.cpython-312.pyc
│ │ │ │ │ ├── _html5builder.cpython-312.pyc
│ │ │ │ │ ├── _setmixin.cpython-312.pyc
│ │ │ │ │ ├── builder.cpython-312.pyc
│ │ │ │ │ ├── clean.cpython-312.pyc
│ │ │ │ │ ├── defs.cpython-312.pyc
│ │ │ │ │ ├── diff.cpython-312.pyc
│ │ │ │ │ ├── ElementSoup.cpython-312.pyc
│ │ │ │ │ ├── formfill.cpython-312.pyc
│ │ │ │ │ ├── html5parser.cpython-312.pyc
│ │ │ │ │ ├── soupparser.cpython-312.pyc
│ │ │ │ │ └── usedoctest.cpython-312.pyc
│ │ │ │ ├── _diffcommand.py
│ │ │ │ ├── _html5builder.py
│ │ │ │ ├── _setmixin.py
│ │ │ │ ├── builder.py
│ │ │ │ ├── clean.py
│ │ │ │ ├── defs.py
│ │ │ │ ├── diff.cpython-312-darwin.so
│ │ │ │ ├── diff.py
│ │ │ │ ├── ElementSoup.py
│ │ │ │ ├── formfill.py
│ │ │ │ ├── html5parser.py
│ │ │ │ ├── soupparser.py
│ │ │ │ └── usedoctest.py
│ │ │ ├── includes
│ │ │ │ ├── __init__.pxd
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── c14n.pxd
│ │ │ │ ├── config.pxd
│ │ │ │ ├── dtdvalid.pxd
│ │ │ │ ├── etree_defs.h
│ │ │ │ ├── etreepublic.pxd
│ │ │ │ ├── extlibs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── libcharset.h
│ │ │ │ │ ├── localcharset.h
│ │ │ │ │ ├── zconf.h
│ │ │ │ │ └── zlib.h
│ │ │ │ ├── htmlparser.pxd
│ │ │ │ ├── libexslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── exslt.h
│ │ │ │ │ ├── exsltconfig.h
│ │ │ │ │ └── exsltexports.h
│ │ │ │ ├── libxml
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── c14n.h
│ │ │ │ │ ├── catalog.h
│ │ │ │ │ ├── chvalid.h
│ │ │ │ │ ├── debugXML.h
│ │ │ │ │ ├── dict.h
│ │ │ │ │ ├── encoding.h
│ │ │ │ │ ├── entities.h
│ │ │ │ │ ├── globals.h
│ │ │ │ │ ├── hash.h
│ │ │ │ │ ├── HTMLparser.h
│ │ │ │ │ ├── HTMLtree.h
│ │ │ │ │ ├── list.h
│ │ │ │ │ ├── nanoftp.h
│ │ │ │ │ ├── nanohttp.h
│ │ │ │ │ ├── parser.h
│ │ │ │ │ ├── parserInternals.h
│ │ │ │ │ ├── relaxng.h
│ │ │ │ │ ├── SAX.h
│ │ │ │ │ ├── SAX2.h
│ │ │ │ │ ├── schemasInternals.h
│ │ │ │ │ ├── schematron.h
│ │ │ │ │ ├── threads.h
│ │ │ │ │ ├── tree.h
│ │ │ │ │ ├── uri.h
│ │ │ │ │ ├── valid.h
│ │ │ │ │ ├── xinclude.h
│ │ │ │ │ ├── xlink.h
│ │ │ │ │ ├── xmlautomata.h
│ │ │ │ │ ├── xmlerror.h
│ │ │ │ │ ├── xmlexports.h
│ │ │ │ │ ├── xmlIO.h
│ │ │ │ │ ├── xmlmemory.h
│ │ │ │ │ ├── xmlmodule.h
│ │ │ │ │ ├── xmlreader.h
│ │ │ │ │ ├── xmlregexp.h
│ │ │ │ │ ├── xmlsave.h
│ │ │ │ │ ├── xmlschemas.h
│ │ │ │ │ ├── xmlschemastypes.h
│ │ │ │ │ ├── xmlstring.h
│ │ │ │ │ ├── xmlunicode.h
│ │ │ │ │ ├── xmlversion.h
│ │ │ │ │ ├── xmlwriter.h
│ │ │ │ │ ├── xpath.h
│ │ │ │ │ ├── xpathInternals.h
│ │ │ │ │ └── xpointer.h
│ │ │ │ ├── libxslt
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── attributes.h
│ │ │ │ │ ├── documents.h
│ │ │ │ │ ├── extensions.h
│ │ │ │ │ ├── extra.h
│ │ │ │ │ ├── functions.h
│ │ │ │ │ ├── imports.h
│ │ │ │ │ ├── keys.h
│ │ │ │ │ ├── namespaces.h
│ │ │ │ │ ├── numbersInternals.h
│ │ │ │ │ ├── pattern.h
│ │ │ │ │ ├── preproc.h
│ │ │ │ │ ├── security.h
│ │ │ │ │ ├── templates.h
│ │ │ │ │ ├── transform.h
│ │ │ │ │ ├── variables.h
│ │ │ │ │ ├── xslt.h
│ │ │ │ │ ├── xsltconfig.h
│ │ │ │ │ ├── xsltexports.h
│ │ │ │ │ ├── xsltInternals.h
│ │ │ │ │ ├── xsltlocale.h
│ │ │ │ │ └── xsltutils.h
│ │ │ │ ├── lxml-version.h
│ │ │ │ ├── relaxng.pxd
│ │ │ │ ├── schematron.pxd
│ │ │ │ ├── tree.pxd
│ │ │ │ ├── uri.pxd
│ │ │ │ ├── xinclude.pxd
│ │ │ │ ├── xmlerror.pxd
│ │ │ │ ├── xmlparser.pxd
│ │ │ │ ├── xmlschema.pxd
│ │ │ │ ├── xpath.pxd
│ │ │ │ └── xslt.pxd
│ │ │ ├── isoschematron
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ └── resources
│ │ │ │ ├── rng
│ │ │ │ │ └── iso-schematron.rng
│ │ │ │ └── xsl
│ │ │ │ ├── iso-schematron-xslt1
│ │ │ │ │ ├── iso_abstract_expand.xsl
│ │ │ │ │ ├── iso_dsdl_include.xsl
│ │ │ │ │ ├── iso_schematron_message.xsl
│ │ │ │ │ ├── iso_schematron_skeleton_for_xslt1.xsl
│ │ │ │ │ ├── iso_svrl_for_xslt1.xsl
│ │ │ │ │ └── readme.txt
│ │ │ │ ├── RNG2Schtrn.xsl
│ │ │ │ └── XSD2Schtrn.xsl
│ │ │ ├── iterparse.pxi
│ │ │ ├── lxml.etree_api.h
│ │ │ ├── lxml.etree.h
│ │ │ ├── nsclasses.pxi
│ │ │ ├── objectify.cpython-312-darwin.so
│ │ │ ├── objectify.pyx
│ │ │ ├── objectpath.pxi
│ │ │ ├── parser.pxi
│ │ │ ├── parsertarget.pxi
│ │ │ ├── proxy.pxi
│ │ │ ├── public-api.pxi
│ │ │ ├── pyclasslookup.py
│ │ │ ├── readonlytree.pxi
│ │ │ ├── relaxng.pxi
│ │ │ ├── sax.cpython-312-darwin.so
│ │ │ ├── sax.py
│ │ │ ├── saxparser.pxi
│ │ │ ├── schematron.pxi
│ │ │ ├── serializer.pxi
│ │ │ ├── usedoctest.py
│ │ │ ├── xinclude.pxi
│ │ │ ├── xmlerror.pxi
│ │ │ ├── xmlid.pxi
│ │ │ ├── xmlschema.pxi
│ │ │ ├── xpath.pxi
│ │ │ ├── xslt.pxi
│ │ │ └── xsltext.pxi
│ │ ├── lxml-5.3.0.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── LICENSES.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── markupsafe
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ └── _native.cpython-312.pyc
│ │ │ ├── _native.py
│ │ │ ├── _speedups.c
│ │ │ ├── _speedups.cpython-312-darwin.so
│ │ │ ├── _speedups.pyi
│ │ │ └── py.typed
│ │ ├── MarkupSafe-3.0.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── pip
│ │ │ ├── __init__.py
│ │ │ ├── __main__.py
│ │ │ ├── __pip-runner__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ └── __pip-runner__.cpython-312.pyc
│ │ │ ├── _internal
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── build_env.cpython-312.pyc
│ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ ├── pyproject.cpython-312.pyc
│ │ │ │ │ ├── self_outdated_check.cpython-312.pyc
│ │ │ │ │ └── wheel_builder.cpython-312.pyc
│ │ │ │ ├── build_env.py
│ │ │ │ ├── cache.py
│ │ │ │ ├── cli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── autocompletion.cpython-312.pyc
│ │ │ │ │ │ ├── base_command.cpython-312.pyc
│ │ │ │ │ │ ├── cmdoptions.cpython-312.pyc
│ │ │ │ │ │ ├── command_context.cpython-312.pyc
│ │ │ │ │ │ ├── index_command.cpython-312.pyc
│ │ │ │ │ │ ├── main_parser.cpython-312.pyc
│ │ │ │ │ │ ├── main.cpython-312.pyc
│ │ │ │ │ │ ├── parser.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bars.cpython-312.pyc
│ │ │ │ │ │ ├── req_command.cpython-312.pyc
│ │ │ │ │ │ ├── spinners.cpython-312.pyc
│ │ │ │ │ │ └── status_codes.cpython-312.pyc
│ │ │ │ │ ├── autocompletion.py
│ │ │ │ │ ├── base_command.py
│ │ │ │ │ ├── cmdoptions.py
│ │ │ │ │ ├── command_context.py
│ │ │ │ │ ├── index_command.py
│ │ │ │ │ ├── main_parser.py
│ │ │ │ │ ├── main.py
│ │ │ │ │ ├── parser.py
│ │ │ │ │ ├── progress_bars.py
│ │ │ │ │ ├── req_command.py
│ │ │ │ │ ├── spinners.py
│ │ │ │ │ └── status_codes.py
│ │ │ │ ├── commands
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── completion.cpython-312.pyc
│ │ │ │ │ │ ├── configuration.cpython-312.pyc
│ │ │ │ │ │ ├── debug.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ ├── hash.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── inspect.cpython-312.pyc
│ │ │ │ │ │ ├── install.cpython-312.pyc
│ │ │ │ │ │ ├── list.cpython-312.pyc
│ │ │ │ │ │ ├── search.cpython-312.pyc
│ │ │ │ │ │ ├── show.cpython-312.pyc
│ │ │ │ │ │ ├── uninstall.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── completion.py
│ │ │ │ │ ├── configuration.py
│ │ │ │ │ ├── debug.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── hash.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── inspect.py
│ │ │ │ │ ├── install.py
│ │ │ │ │ ├── list.py
│ │ │ │ │ ├── search.py
│ │ │ │ │ ├── show.py
│ │ │ │ │ ├── uninstall.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── configuration.py
│ │ │ │ ├── distributions
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── installed.cpython-312.pyc
│ │ │ │ │ │ ├── sdist.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── installed.py
│ │ │ │ │ ├── sdist.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── index
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── collector.cpython-312.pyc
│ │ │ │ │ │ ├── package_finder.cpython-312.pyc
│ │ │ │ │ │ └── sources.cpython-312.pyc
│ │ │ │ │ ├── collector.py
│ │ │ │ │ ├── package_finder.py
│ │ │ │ │ └── sources.py
│ │ │ │ ├── locations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _distutils.cpython-312.pyc
│ │ │ │ │ │ ├── _sysconfig.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── _distutils.py
│ │ │ │ │ ├── _sysconfig.py
│ │ │ │ │ └── base.py
│ │ │ │ ├── main.py
│ │ │ │ ├── metadata
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _json.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ └── pkg_resources.cpython-312.pyc
│ │ │ │ │ ├── _json.py
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── importlib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ │ ├── _dists.cpython-312.pyc
│ │ │ │ │ │ │ └── _envs.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.py
│ │ │ │ │ │ ├── _dists.py
│ │ │ │ │ │ └── _envs.py
│ │ │ │ │ └── pkg_resources.py
│ │ │ │ ├── models
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── candidate.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url.cpython-312.pyc
│ │ │ │ │ │ ├── format_control.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── installation_report.cpython-312.pyc
│ │ │ │ │ │ ├── link.cpython-312.pyc
│ │ │ │ │ │ ├── scheme.cpython-312.pyc
│ │ │ │ │ │ ├── search_scope.cpython-312.pyc
│ │ │ │ │ │ ├── selection_prefs.cpython-312.pyc
│ │ │ │ │ │ ├── target_python.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── candidate.py
│ │ │ │ │ ├── direct_url.py
│ │ │ │ │ ├── format_control.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── installation_report.py
│ │ │ │ │ ├── link.py
│ │ │ │ │ ├── scheme.py
│ │ │ │ │ ├── search_scope.py
│ │ │ │ │ ├── selection_prefs.py
│ │ │ │ │ ├── target_python.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── network
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── download.cpython-312.pyc
│ │ │ │ │ │ ├── lazy_wheel.cpython-312.pyc
│ │ │ │ │ │ ├── session.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── xmlrpc.cpython-312.pyc
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── download.py
│ │ │ │ │ ├── lazy_wheel.py
│ │ │ │ │ ├── session.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── xmlrpc.py
│ │ │ │ ├── operations
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── check.cpython-312.pyc
│ │ │ │ │ │ ├── freeze.cpython-312.pyc
│ │ │ │ │ │ └── prepare.cpython-312.pyc
│ │ │ │ │ ├── build
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── build_tracker.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata_legacy.cpython-312.pyc
│ │ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_editable.cpython-312.pyc
│ │ │ │ │ │ │ ├── wheel_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── build_tracker.py
│ │ │ │ │ │ ├── metadata_editable.py
│ │ │ │ │ │ ├── metadata_legacy.py
│ │ │ │ │ │ ├── metadata.py
│ │ │ │ │ │ ├── wheel_editable.py
│ │ │ │ │ │ ├── wheel_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ ├── check.py
│ │ │ │ │ ├── freeze.py
│ │ │ │ │ ├── install
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── editable_legacy.cpython-312.pyc
│ │ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ │ ├── editable_legacy.py
│ │ │ │ │ │ └── wheel.py
│ │ │ │ │ └── prepare.py
│ │ │ │ ├── pyproject.py
│ │ │ │ ├── req
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── constructors.cpython-312.pyc
│ │ │ │ │ │ ├── req_file.cpython-312.pyc
│ │ │ │ │ │ ├── req_install.cpython-312.pyc
│ │ │ │ │ │ ├── req_set.cpython-312.pyc
│ │ │ │ │ │ └── req_uninstall.cpython-312.pyc
│ │ │ │ │ ├── constructors.py
│ │ │ │ │ ├── req_file.py
│ │ │ │ │ ├── req_install.py
│ │ │ │ │ ├── req_set.py
│ │ │ │ │ └── req_uninstall.py
│ │ │ │ ├── resolution
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── base.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── legacy
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ │ └── resolver.py
│ │ │ │ │ └── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── base.cpython-312.pyc
│ │ │ │ │ │ ├── candidates.cpython-312.pyc
│ │ │ │ │ │ ├── factory.cpython-312.pyc
│ │ │ │ │ │ ├── found_candidates.cpython-312.pyc
│ │ │ │ │ │ ├── provider.cpython-312.pyc
│ │ │ │ │ │ ├── reporter.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ └── resolver.cpython-312.pyc
│ │ │ │ │ ├── base.py
│ │ │ │ │ ├── candidates.py
│ │ │ │ │ ├── factory.py
│ │ │ │ │ ├── found_candidates.py
│ │ │ │ │ ├── provider.py
│ │ │ │ │ ├── reporter.py
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ └── resolver.py
│ │ │ │ ├── self_outdated_check.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _jaraco_text.cpython-312.pyc
│ │ │ │ │ │ ├── _log.cpython-312.pyc
│ │ │ │ │ │ ├── appdirs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── compatibility_tags.cpython-312.pyc
│ │ │ │ │ │ ├── datetime.cpython-312.pyc
│ │ │ │ │ │ ├── deprecation.cpython-312.pyc
│ │ │ │ │ │ ├── direct_url_helpers.cpython-312.pyc
│ │ │ │ │ │ ├── egg_link.cpython-312.pyc
│ │ │ │ │ │ ├── encoding.cpython-312.pyc
│ │ │ │ │ │ ├── entrypoints.cpython-312.pyc
│ │ │ │ │ │ ├── filesystem.cpython-312.pyc
│ │ │ │ │ │ ├── filetypes.cpython-312.pyc
│ │ │ │ │ │ ├── glibc.cpython-312.pyc
│ │ │ │ │ │ ├── hashes.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── misc.cpython-312.pyc
│ │ │ │ │ │ ├── packaging.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── setuptools_build.cpython-312.pyc
│ │ │ │ │ │ ├── subprocess.cpython-312.pyc
│ │ │ │ │ │ ├── temp_dir.cpython-312.pyc
│ │ │ │ │ │ ├── unpacking.cpython-312.pyc
│ │ │ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ │ │ ├── virtualenv.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── _jaraco_text.py
│ │ │ │ │ ├── _log.py
│ │ │ │ │ ├── appdirs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── compatibility_tags.py
│ │ │ │ │ ├── datetime.py
│ │ │ │ │ ├── deprecation.py
│ │ │ │ │ ├── direct_url_helpers.py
│ │ │ │ │ ├── egg_link.py
│ │ │ │ │ ├── encoding.py
│ │ │ │ │ ├── entrypoints.py
│ │ │ │ │ ├── filesystem.py
│ │ │ │ │ ├── filetypes.py
│ │ │ │ │ ├── glibc.py
│ │ │ │ │ ├── hashes.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── misc.py
│ │ │ │ │ ├── packaging.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── setuptools_build.py
│ │ │ │ │ ├── subprocess.py
│ │ │ │ │ ├── temp_dir.py
│ │ │ │ │ ├── unpacking.py
│ │ │ │ │ ├── urls.py
│ │ │ │ │ ├── virtualenv.py
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── vcs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── bazaar.cpython-312.pyc
│ │ │ │ │ │ ├── git.cpython-312.pyc
│ │ │ │ │ │ ├── mercurial.cpython-312.pyc
│ │ │ │ │ │ ├── subversion.cpython-312.pyc
│ │ │ │ │ │ └── versioncontrol.cpython-312.pyc
│ │ │ │ │ ├── bazaar.py
│ │ │ │ │ ├── git.py
│ │ │ │ │ ├── mercurial.py
│ │ │ │ │ ├── subversion.py
│ │ │ │ │ └── versioncontrol.py
│ │ │ │ └── wheel_builder.py
│ │ │ ├── _vendor
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ └── typing_extensions.cpython-312.pyc
│ │ │ │ ├── cachecontrol
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _cmd.cpython-312.pyc
│ │ │ │ │ │ ├── adapter.cpython-312.pyc
│ │ │ │ │ │ ├── cache.cpython-312.pyc
│ │ │ │ │ │ ├── controller.cpython-312.pyc
│ │ │ │ │ │ ├── filewrapper.cpython-312.pyc
│ │ │ │ │ │ ├── heuristics.cpython-312.pyc
│ │ │ │ │ │ ├── serialize.cpython-312.pyc
│ │ │ │ │ │ └── wrapper.cpython-312.pyc
│ │ │ │ │ ├── _cmd.py
│ │ │ │ │ ├── adapter.py
│ │ │ │ │ ├── cache.py
│ │ │ │ │ ├── caches
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── file_cache.cpython-312.pyc
│ │ │ │ │ │ │ └── redis_cache.cpython-312.pyc
│ │ │ │ │ │ ├── file_cache.py
│ │ │ │ │ │ └── redis_cache.py
│ │ │ │ │ ├── controller.py
│ │ │ │ │ ├── filewrapper.py
│ │ │ │ │ ├── heuristics.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── serialize.py
│ │ │ │ │ └── wrapper.py
│ │ │ │ ├── certifi
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── core.cpython-312.pyc
│ │ │ │ │ ├── cacert.pem
│ │ │ │ │ ├── core.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── distlib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── database.cpython-312.pyc
│ │ │ │ │ │ ├── index.cpython-312.pyc
│ │ │ │ │ │ ├── locators.cpython-312.pyc
│ │ │ │ │ │ ├── manifest.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── resources.cpython-312.pyc
│ │ │ │ │ │ ├── scripts.cpython-312.pyc
│ │ │ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── wheel.cpython-312.pyc
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── database.py
│ │ │ │ │ ├── index.py
│ │ │ │ │ ├── locators.py
│ │ │ │ │ ├── manifest.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ ├── scripts.py
│ │ │ │ │ ├── t32.exe
│ │ │ │ │ ├── t64-arm.exe
│ │ │ │ │ ├── t64.exe
│ │ │ │ │ ├── util.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ ├── w32.exe
│ │ │ │ │ ├── w64-arm.exe
│ │ │ │ │ ├── w64.exe
│ │ │ │ │ └── wheel.py
│ │ │ │ ├── distro
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ └── distro.cpython-312.pyc
│ │ │ │ │ ├── distro.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── idna
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── codec.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── core.cpython-312.pyc
│ │ │ │ │ │ ├── idnadata.cpython-312.pyc
│ │ │ │ │ │ ├── intranges.cpython-312.pyc
│ │ │ │ │ │ ├── package_data.cpython-312.pyc
│ │ │ │ │ │ └── uts46data.cpython-312.pyc
│ │ │ │ │ ├── codec.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── core.py
│ │ │ │ │ ├── idnadata.py
│ │ │ │ │ ├── intranges.py
│ │ │ │ │ ├── package_data.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ └── uts46data.py
│ │ │ │ ├── msgpack
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── ext.cpython-312.pyc
│ │ │ │ │ │ └── fallback.cpython-312.pyc
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── ext.py
│ │ │ │ │ └── fallback.py
│ │ │ │ ├── packaging
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _elffile.cpython-312.pyc
│ │ │ │ │ │ ├── _manylinux.cpython-312.pyc
│ │ │ │ │ │ ├── _musllinux.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _structures.cpython-312.pyc
│ │ │ │ │ │ ├── _tokenizer.cpython-312.pyc
│ │ │ │ │ │ ├── markers.cpython-312.pyc
│ │ │ │ │ │ ├── metadata.cpython-312.pyc
│ │ │ │ │ │ ├── requirements.cpython-312.pyc
│ │ │ │ │ │ ├── specifiers.cpython-312.pyc
│ │ │ │ │ │ ├── tags.cpython-312.pyc
│ │ │ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ │ │ └── version.cpython-312.pyc
│ │ │ │ │ ├── _elffile.py
│ │ │ │ │ ├── _manylinux.py
│ │ │ │ │ ├── _musllinux.py
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _structures.py
│ │ │ │ │ ├── _tokenizer.py
│ │ │ │ │ ├── markers.py
│ │ │ │ │ ├── metadata.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── requirements.py
│ │ │ │ │ ├── specifiers.py
│ │ │ │ │ ├── tags.py
│ │ │ │ │ ├── utils.py
│ │ │ │ │ └── version.py
│ │ │ │ ├── pkg_resources
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── __pycache__
│ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ ├── platformdirs
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── android.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── macos.cpython-312.pyc
│ │ │ │ │ │ ├── unix.cpython-312.pyc
│ │ │ │ │ │ ├── version.cpython-312.pyc
│ │ │ │ │ │ └── windows.cpython-312.pyc
│ │ │ │ │ ├── android.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── macos.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── unix.py
│ │ │ │ │ ├── version.py
│ │ │ │ │ └── windows.py
│ │ │ │ ├── pygments
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── cmdline.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── filter.cpython-312.pyc
│ │ │ │ │ │ ├── formatter.cpython-312.pyc
│ │ │ │ │ │ ├── lexer.cpython-312.pyc
│ │ │ │ │ │ ├── modeline.cpython-312.pyc
│ │ │ │ │ │ ├── plugin.cpython-312.pyc
│ │ │ │ │ │ ├── regexopt.cpython-312.pyc
│ │ │ │ │ │ ├── scanner.cpython-312.pyc
│ │ │ │ │ │ ├── sphinxext.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── token.cpython-312.pyc
│ │ │ │ │ │ ├── unistring.cpython-312.pyc
│ │ │ │ │ │ └── util.cpython-312.pyc
│ │ │ │ │ ├── cmdline.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── filter.py
│ │ │ │ │ ├── filters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ └── __pycache__
│ │ │ │ │ │ └── __init__.cpython-312.pyc
│ │ │ │ │ ├── formatter.py
│ │ │ │ │ ├── formatters
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ ├── bbcode.cpython-312.pyc
│ │ │ │ │ │ │ ├── groff.cpython-312.pyc
│ │ │ │ │ │ │ ├── html.cpython-312.pyc
│ │ │ │ │ │ │ ├── img.cpython-312.pyc
│ │ │ │ │ │ │ ├── irc.cpython-312.pyc
│ │ │ │ │ │ │ ├── latex.cpython-312.pyc
│ │ │ │ │ │ │ ├── other.cpython-312.pyc
│ │ │ │ │ │ │ ├── pangomarkup.cpython-312.pyc
│ │ │ │ │ │ │ ├── rtf.cpython-312.pyc
│ │ │ │ │ │ │ ├── svg.cpython-312.pyc
│ │ │ │ │ │ │ ├── terminal.cpython-312.pyc
│ │ │ │ │ │ │ └── terminal256.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ ├── bbcode.py
│ │ │ │ │ │ ├── groff.py
│ │ │ │ │ │ ├── html.py
│ │ │ │ │ │ ├── img.py
│ │ │ │ │ │ ├── irc.py
│ │ │ │ │ │ ├── latex.py
│ │ │ │ │ │ ├── other.py
│ │ │ │ │ │ ├── pangomarkup.py
│ │ │ │ │ │ ├── rtf.py
│ │ │ │ │ │ ├── svg.py
│ │ │ │ │ │ ├── terminal.py
│ │ │ │ │ │ └── terminal256.py
│ │ │ │ │ ├── lexer.py
│ │ │ │ │ ├── lexers
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _mapping.cpython-312.pyc
│ │ │ │ │ │ │ └── python.cpython-312.pyc
│ │ │ │ │ │ ├── _mapping.py
│ │ │ │ │ │ └── python.py
│ │ │ │ │ ├── modeline.py
│ │ │ │ │ ├── plugin.py
│ │ │ │ │ ├── regexopt.py
│ │ │ │ │ ├── scanner.py
│ │ │ │ │ ├── sphinxext.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styles
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── _mapping.cpython-312.pyc
│ │ │ │ │ │ └── _mapping.py
│ │ │ │ │ ├── token.py
│ │ │ │ │ ├── unistring.py
│ │ │ │ │ └── util.py
│ │ │ │ ├── pyproject_hooks
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _compat.cpython-312.pyc
│ │ │ │ │ │ └── _impl.cpython-312.pyc
│ │ │ │ │ ├── _compat.py
│ │ │ │ │ ├── _impl.py
│ │ │ │ │ └── _in_process
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ └── _in_process.cpython-312.pyc
│ │ │ │ │ └── _in_process.py
│ │ │ │ ├── requests
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ │ ├── __version__.py
│ │ │ │ │ ├── _internal_utils.py
│ │ │ │ │ ├── adapters.py
│ │ │ │ │ ├── api.py
│ │ │ │ │ ├── auth.py
│ │ │ │ │ ├── certs.py
│ │ │ │ │ ├── compat.py
│ │ │ │ │ ├── cookies.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── help.py
│ │ │ │ │ ├── hooks.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ ├── packages.py
│ │ │ │ │ ├── sessions.py
│ │ │ │ │ ├── status_codes.py
│ │ │ │ │ ├── structures.py
│ │ │ │ │ └── utils.py
│ │ │ │ ├── resolvelib
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── providers.cpython-312.pyc
│ │ │ │ │ │ ├── reporters.cpython-312.pyc
│ │ │ │ │ │ ├── resolvers.cpython-312.pyc
│ │ │ │ │ │ └── structs.cpython-312.pyc
│ │ │ │ │ ├── compat
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── collections_abc.cpython-312.pyc
│ │ │ │ │ │ └── collections_abc.py
│ │ │ │ │ ├── providers.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── reporters.py
│ │ │ │ │ ├── resolvers.py
│ │ │ │ │ └── structs.py
│ │ │ │ ├── rich
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __main__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── __main__.cpython-312.pyc
│ │ │ │ │ │ ├── _cell_widths.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_codes.cpython-312.pyc
│ │ │ │ │ │ ├── _emoji_replace.cpython-312.pyc
│ │ │ │ │ │ ├── _export_format.cpython-312.pyc
│ │ │ │ │ │ ├── _extension.cpython-312.pyc
│ │ │ │ │ │ ├── _fileno.cpython-312.pyc
│ │ │ │ │ │ ├── _inspect.cpython-312.pyc
│ │ │ │ │ │ ├── _log_render.cpython-312.pyc
│ │ │ │ │ │ ├── _loop.cpython-312.pyc
│ │ │ │ │ │ ├── _null_file.cpython-312.pyc
│ │ │ │ │ │ ├── _palettes.cpython-312.pyc
│ │ │ │ │ │ ├── _pick.cpython-312.pyc
│ │ │ │ │ │ ├── _ratio.cpython-312.pyc
│ │ │ │ │ │ ├── _spinners.cpython-312.pyc
│ │ │ │ │ │ ├── _stack.cpython-312.pyc
│ │ │ │ │ │ ├── _timer.cpython-312.pyc
│ │ │ │ │ │ ├── _win32_console.cpython-312.pyc
│ │ │ │ │ │ ├── _windows_renderer.cpython-312.pyc
│ │ │ │ │ │ ├── _windows.cpython-312.pyc
│ │ │ │ │ │ ├── _wrap.cpython-312.pyc
│ │ │ │ │ │ ├── abc.cpython-312.pyc
│ │ │ │ │ │ ├── align.cpython-312.pyc
│ │ │ │ │ │ ├── ansi.cpython-312.pyc
│ │ │ │ │ │ ├── bar.cpython-312.pyc
│ │ │ │ │ │ ├── box.cpython-312.pyc
│ │ │ │ │ │ ├── cells.cpython-312.pyc
│ │ │ │ │ │ ├── color_triplet.cpython-312.pyc
│ │ │ │ │ │ ├── color.cpython-312.pyc
│ │ │ │ │ │ ├── columns.cpython-312.pyc
│ │ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ │ ├── constrain.cpython-312.pyc
│ │ │ │ │ │ ├── containers.cpython-312.pyc
│ │ │ │ │ │ ├── control.cpython-312.pyc
│ │ │ │ │ │ ├── default_styles.cpython-312.pyc
│ │ │ │ │ │ ├── diagnose.cpython-312.pyc
│ │ │ │ │ │ ├── emoji.cpython-312.pyc
│ │ │ │ │ │ ├── errors.cpython-312.pyc
│ │ │ │ │ │ ├── file_proxy.cpython-312.pyc
│ │ │ │ │ │ ├── filesize.cpython-312.pyc
│ │ │ │ │ │ ├── highlighter.cpython-312.pyc
│ │ │ │ │ │ ├── json.cpython-312.pyc
│ │ │ │ │ │ ├── jupyter.cpython-312.pyc
│ │ │ │ │ │ ├── layout.cpython-312.pyc
│ │ │ │ │ │ ├── live_render.cpython-312.pyc
│ │ │ │ │ │ ├── live.cpython-312.pyc
│ │ │ │ │ │ ├── logging.cpython-312.pyc
│ │ │ │ │ │ ├── markup.cpython-312.pyc
│ │ │ │ │ │ ├── measure.cpython-312.pyc
│ │ │ │ │ │ ├── padding.cpython-312.pyc
│ │ │ │ │ │ ├── pager.cpython-312.pyc
│ │ │ │ │ │ ├── palette.cpython-312.pyc
│ │ │ │ │ │ ├── panel.cpython-312.pyc
│ │ │ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ │ │ ├── progress_bar.cpython-312.pyc
│ │ │ │ │ │ ├── progress.cpython-312.pyc
│ │ │ │ │ │ ├── prompt.cpython-312.pyc
│ │ │ │ │ │ ├── protocol.cpython-312.pyc
│ │ │ │ │ │ ├── region.cpython-312.pyc
│ │ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ │ ├── rule.cpython-312.pyc
│ │ │ │ │ │ ├── scope.cpython-312.pyc
│ │ │ │ │ │ ├── screen.cpython-312.pyc
│ │ │ │ │ │ ├── segment.cpython-312.pyc
│ │ │ │ │ │ ├── spinner.cpython-312.pyc
│ │ │ │ │ │ ├── status.cpython-312.pyc
│ │ │ │ │ │ ├── style.cpython-312.pyc
│ │ │ │ │ │ ├── styled.cpython-312.pyc
│ │ │ │ │ │ ├── syntax.cpython-312.pyc
│ │ │ │ │ │ ├── table.cpython-312.pyc
│ │ │ │ │ │ ├── terminal_theme.cpython-312.pyc
│ │ │ │ │ │ ├── text.cpython-312.pyc
│ │ │ │ │ │ ├── theme.cpython-312.pyc
│ │ │ │ │ │ ├── themes.cpython-312.pyc
│ │ │ │ │ │ ├── traceback.cpython-312.pyc
│ │ │ │ │ │ └── tree.cpython-312.pyc
│ │ │ │ │ ├── _cell_widths.py
│ │ │ │ │ ├── _emoji_codes.py
│ │ │ │ │ ├── _emoji_replace.py
│ │ │ │ │ ├── _export_format.py
│ │ │ │ │ ├── _extension.py
│ │ │ │ │ ├── _fileno.py
│ │ │ │ │ ├── _inspect.py
│ │ │ │ │ ├── _log_render.py
│ │ │ │ │ ├── _loop.py
│ │ │ │ │ ├── _null_file.py
│ │ │ │ │ ├── _palettes.py
│ │ │ │ │ ├── _pick.py
│ │ │ │ │ ├── _ratio.py
│ │ │ │ │ ├── _spinners.py
│ │ │ │ │ ├── _stack.py
│ │ │ │ │ ├── _timer.py
│ │ │ │ │ ├── _win32_console.py
│ │ │ │ │ ├── _windows_renderer.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ ├── _wrap.py
│ │ │ │ │ ├── abc.py
│ │ │ │ │ ├── align.py
│ │ │ │ │ ├── ansi.py
│ │ │ │ │ ├── bar.py
│ │ │ │ │ ├── box.py
│ │ │ │ │ ├── cells.py
│ │ │ │ │ ├── color_triplet.py
│ │ │ │ │ ├── color.py
│ │ │ │ │ ├── columns.py
│ │ │ │ │ ├── console.py
│ │ │ │ │ ├── constrain.py
│ │ │ │ │ ├── containers.py
│ │ │ │ │ ├── control.py
│ │ │ │ │ ├── default_styles.py
│ │ │ │ │ ├── diagnose.py
│ │ │ │ │ ├── emoji.py
│ │ │ │ │ ├── errors.py
│ │ │ │ │ ├── file_proxy.py
│ │ │ │ │ ├── filesize.py
│ │ │ │ │ ├── highlighter.py
│ │ │ │ │ ├── json.py
│ │ │ │ │ ├── jupyter.py
│ │ │ │ │ ├── layout.py
│ │ │ │ │ ├── live_render.py
│ │ │ │ │ ├── live.py
│ │ │ │ │ ├── logging.py
│ │ │ │ │ ├── markup.py
│ │ │ │ │ ├── measure.py
│ │ │ │ │ ├── padding.py
│ │ │ │ │ ├── pager.py
│ │ │ │ │ ├── palette.py
│ │ │ │ │ ├── panel.py
│ │ │ │ │ ├── pretty.py
│ │ │ │ │ ├── progress_bar.py
│ │ │ │ │ ├── progress.py
│ │ │ │ │ ├── prompt.py
│ │ │ │ │ ├── protocol.py
│ │ │ │ │ ├── py.typed
│ │ │ │ │ ├── region.py
│ │ │ │ │ ├── repr.py
│ │ │ │ │ ├── rule.py
│ │ │ │ │ ├── scope.py
│ │ │ │ │ ├── screen.py
│ │ │ │ │ ├── segment.py
│ │ │ │ │ ├── spinner.py
│ │ │ │ │ ├── status.py
│ │ │ │ │ ├── style.py
│ │ │ │ │ ├── styled.py
│ │ │ │ │ ├── syntax.py
│ │ │ │ │ ├── table.py
│ │ │ │ │ ├── terminal_theme.py
│ │ │ │ │ ├── text.py
│ │ │ │ │ ├── theme.py
│ │ │ │ │ ├── themes.py
│ │ │ │ │ ├── traceback.py
│ │ │ │ │ └── tree.py
│ │ │ │ ├── tomli
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _parser.cpython-312.pyc
│ │ │ │ │ │ ├── _re.cpython-312.pyc
│ │ │ │ │ │ └── _types.cpython-312.pyc
│ │ │ │ │ ├── _parser.py
│ │ │ │ │ ├── _re.py
│ │ │ │ │ ├── _types.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── truststore
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _api.cpython-312.pyc
│ │ │ │ │ │ ├── _macos.cpython-312.pyc
│ │ │ │ │ │ ├── _openssl.cpython-312.pyc
│ │ │ │ │ │ ├── _ssl_constants.cpython-312.pyc
│ │ │ │ │ │ └── _windows.cpython-312.pyc
│ │ │ │ │ ├── _api.py
│ │ │ │ │ ├── _macos.py
│ │ │ │ │ ├── _openssl.py
│ │ │ │ │ ├── _ssl_constants.py
│ │ │ │ │ ├── _windows.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── typing_extensions.py
│ │ │ │ ├── urllib3
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── _collections.py
│ │ │ │ │ ├── _version.py
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── connectionpool.py
│ │ │ │ │ ├── contrib
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ ├── _appengine_environ.cpython-312.pyc
│ │ │ │ │ │ │ ├── appengine.cpython-312.pyc
│ │ │ │ │ │ │ ├── ntlmpool.cpython-312.pyc
│ │ │ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ │ │ ├── securetransport.cpython-312.pyc
│ │ │ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ │ │ ├── _appengine_environ.py
│ │ │ │ │ │ ├── _securetransport
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── bindings.cpython-312.pyc
│ │ │ │ │ │ │ │ └── low_level.cpython-312.pyc
│ │ │ │ │ │ │ ├── bindings.py
│ │ │ │ │ │ │ └── low_level.py
│ │ │ │ │ │ ├── appengine.py
│ │ │ │ │ │ ├── ntlmpool.py
│ │ │ │ │ │ ├── pyopenssl.py
│ │ │ │ │ │ ├── securetransport.py
│ │ │ │ │ │ └── socks.py
│ │ │ │ │ ├── exceptions.py
│ │ │ │ │ ├── fields.py
│ │ │ │ │ ├── filepost.py
│ │ │ │ │ ├── packages
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ └── six.cpython-312.pyc
│ │ │ │ │ │ ├── backports
│ │ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ │ │ ├── makefile.cpython-312.pyc
│ │ │ │ │ │ │ │ └── weakref_finalize.cpython-312.pyc
│ │ │ │ │ │ │ ├── makefile.py
│ │ │ │ │ │ │ └── weakref_finalize.py
│ │ │ │ │ │ └── six.py
│ │ │ │ │ ├── poolmanager.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ └── util
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ │ │ ├── queue.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ │ │ └── wait.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── proxy.py
│ │ │ │ │ ├── queue.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ ├── response.py
│ │ │ │ │ ├── retry.py
│ │ │ │ │ ├── ssl_.py
│ │ │ │ │ ├── ssl_match_hostname.py
│ │ │ │ │ ├── ssltransport.py
│ │ │ │ │ ├── timeout.py
│ │ │ │ │ ├── url.py
│ │ │ │ │ └── wait.py
│ │ │ │ └── vendor.txt
│ │ │ └── py.typed
│ │ ├── pip-24.2.dist-info
│ │ │ ├── AUTHORS.txt
│ │ │ ├── entry_points.txt
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── requests
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __version__.cpython-312.pyc
│ │ │ │ ├── _internal_utils.cpython-312.pyc
│ │ │ │ ├── adapters.cpython-312.pyc
│ │ │ │ ├── api.cpython-312.pyc
│ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ ├── certs.cpython-312.pyc
│ │ │ │ ├── compat.cpython-312.pyc
│ │ │ │ ├── cookies.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── help.cpython-312.pyc
│ │ │ │ ├── hooks.cpython-312.pyc
│ │ │ │ ├── models.cpython-312.pyc
│ │ │ │ ├── packages.cpython-312.pyc
│ │ │ │ ├── sessions.cpython-312.pyc
│ │ │ │ ├── status_codes.cpython-312.pyc
│ │ │ │ ├── structures.cpython-312.pyc
│ │ │ │ └── utils.cpython-312.pyc
│ │ │ ├── __version__.py
│ │ │ ├── _internal_utils.py
│ │ │ ├── adapters.py
│ │ │ ├── api.py
│ │ │ ├── auth.py
│ │ │ ├── certs.py
│ │ │ ├── compat.py
│ │ │ ├── cookies.py
│ │ │ ├── exceptions.py
│ │ │ ├── help.py
│ │ │ ├── hooks.py
│ │ │ ├── models.py
│ │ │ ├── packages.py
│ │ │ ├── sessions.py
│ │ │ ├── status_codes.py
│ │ │ ├── structures.py
│ │ │ └── utils.py
│ │ ├── requests-2.32.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── soupsieve
│ │ │ ├── __init__.py
│ │ │ ├── __meta__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── __meta__.cpython-312.pyc
│ │ │ │ ├── css_match.cpython-312.pyc
│ │ │ │ ├── css_parser.cpython-312.pyc
│ │ │ │ ├── css_types.cpython-312.pyc
│ │ │ │ ├── pretty.cpython-312.pyc
│ │ │ │ └── util.cpython-312.pyc
│ │ │ ├── css_match.py
│ │ │ ├── css_parser.py
│ │ │ ├── css_types.py
│ │ │ ├── pretty.py
│ │ │ ├── py.typed
│ │ │ └── util.py
│ │ ├── soupsieve-2.6.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.md
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── urllib3
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _base_connection.cpython-312.pyc
│ │ │ │ ├── _collections.cpython-312.pyc
│ │ │ │ ├── _request_methods.cpython-312.pyc
│ │ │ │ ├── _version.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── connectionpool.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── fields.cpython-312.pyc
│ │ │ │ ├── filepost.cpython-312.pyc
│ │ │ │ ├── poolmanager.cpython-312.pyc
│ │ │ │ └── response.cpython-312.pyc
│ │ │ ├── _base_connection.py
│ │ │ ├── _collections.py
│ │ │ ├── _request_methods.py
│ │ │ ├── _version.py
│ │ │ ├── connection.py
│ │ │ ├── connectionpool.py
│ │ │ ├── contrib
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── pyopenssl.cpython-312.pyc
│ │ │ │ │ └── socks.cpython-312.pyc
│ │ │ │ ├── emscripten
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── __pycache__
│ │ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ │ ├── fetch.cpython-312.pyc
│ │ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ │ ├── connection.py
│ │ │ │ │ ├── emscripten_fetch_worker.js
│ │ │ │ │ ├── fetch.py
│ │ │ │ │ ├── request.py
│ │ │ │ │ └── response.py
│ │ │ │ ├── pyopenssl.py
│ │ │ │ └── socks.py
│ │ │ ├── exceptions.py
│ │ │ ├── fields.py
│ │ │ ├── filepost.py
│ │ │ ├── http2
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ │ └── probe.cpython-312.pyc
│ │ │ │ ├── connection.py
│ │ │ │ └── probe.py
│ │ │ ├── poolmanager.py
│ │ │ ├── py.typed
│ │ │ ├── response.py
│ │ │ └── util
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── connection.cpython-312.pyc
│ │ │ │ ├── proxy.cpython-312.pyc
│ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ ├── retry.cpython-312.pyc
│ │ │ │ ├── ssl_.cpython-312.pyc
│ │ │ │ ├── ssl_match_hostname.cpython-312.pyc
│ │ │ │ ├── ssltransport.cpython-312.pyc
│ │ │ │ ├── timeout.cpython-312.pyc
│ │ │ │ ├── url.cpython-312.pyc
│ │ │ │ ├── util.cpython-312.pyc
│ │ │ │ └── wait.cpython-312.pyc
│ │ │ ├── connection.py
│ │ │ ├── proxy.py
│ │ │ ├── request.py
│ │ │ ├── response.py
│ │ │ ├── retry.py
│ │ │ ├── ssl_.py
│ │ │ ├── ssl_match_hostname.py
│ │ │ ├── ssltransport.py
│ │ │ ├── timeout.py
│ │ │ ├── url.py
│ │ │ ├── util.py
│ │ │ └── wait.py
│ │ ├── urllib3-2.2.3.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── licenses
│ │ │ │ └── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ └── WHEEL
│ │ ├── useragent
│ │ │ ├── __init__.py
│ │ │ ├── __init__.pyc
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── resources
│ │ │ │ └── user_agent_data.json
│ │ │ └── test
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ └── __init__.cpython-312.pyc
│ │ │ ├── test_additional_os.json
│ │ │ ├── test_browser.json
│ │ │ ├── test_device.json
│ │ │ ├── test_firefox.json
│ │ │ ├── test_os.json
│ │ │ └── test_pgts_browser.json
│ │ ├── useragent-0.1.1.dist-info
│ │ │ ├── INSTALLER
│ │ │ ├── LICENSE.txt
│ │ │ ├── METADATA
│ │ │ ├── RECORD
│ │ │ ├── REQUESTED
│ │ │ ├── top_level.txt
│ │ │ └── WHEEL
│ │ ├── werkzeug
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ ├── _internal.cpython-312.pyc
│ │ │ │ ├── _reloader.cpython-312.pyc
│ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ ├── formparser.cpython-312.pyc
│ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ ├── local.cpython-312.pyc
│ │ │ │ ├── security.cpython-312.pyc
│ │ │ │ ├── serving.cpython-312.pyc
│ │ │ │ ├── test.cpython-312.pyc
│ │ │ │ ├── testapp.cpython-312.pyc
│ │ │ │ ├── urls.cpython-312.pyc
│ │ │ │ ├── user_agent.cpython-312.pyc
│ │ │ │ ├── utils.cpython-312.pyc
│ │ │ │ └── wsgi.cpython-312.pyc
│ │ │ ├── _internal.py
│ │ │ ├── _reloader.py
│ │ │ ├── datastructures
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── accept.cpython-312.pyc
│ │ │ │ │ ├── auth.cpython-312.pyc
│ │ │ │ │ ├── cache_control.cpython-312.pyc
│ │ │ │ │ ├── csp.cpython-312.pyc
│ │ │ │ │ ├── etag.cpython-312.pyc
│ │ │ │ │ ├── file_storage.cpython-312.pyc
│ │ │ │ │ ├── headers.cpython-312.pyc
│ │ │ │ │ ├── mixins.cpython-312.pyc
│ │ │ │ │ ├── range.cpython-312.pyc
│ │ │ │ │ └── structures.cpython-312.pyc
│ │ │ │ ├── accept.py
│ │ │ │ ├── accept.pyi
│ │ │ │ ├── auth.py
│ │ │ │ ├── cache_control.py
│ │ │ │ ├── cache_control.pyi
│ │ │ │ ├── csp.py
│ │ │ │ ├── csp.pyi
│ │ │ │ ├── etag.py
│ │ │ │ ├── etag.pyi
│ │ │ │ ├── file_storage.py
│ │ │ │ ├── file_storage.pyi
│ │ │ │ ├── headers.py
│ │ │ │ ├── headers.pyi
│ │ │ │ ├── mixins.py
│ │ │ │ ├── mixins.pyi
│ │ │ │ ├── range.py
│ │ │ │ ├── range.pyi
│ │ │ │ ├── structures.py
│ │ │ │ └── structures.pyi
│ │ │ ├── debug
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── console.cpython-312.pyc
│ │ │ │ │ ├── repr.cpython-312.pyc
│ │ │ │ │ └── tbtools.cpython-312.pyc
│ │ │ │ ├── console.py
│ │ │ │ ├── repr.py
│ │ │ │ ├── shared
│ │ │ │ │ ├── console.png
│ │ │ │ │ ├── debugger.js
│ │ │ │ │ ├── ICON_LICENSE.md
│ │ │ │ │ ├── less.png
│ │ │ │ │ ├── more.png
│ │ │ │ │ └── style.css
│ │ │ │ └── tbtools.py
│ │ │ ├── exceptions.py
│ │ │ ├── formparser.py
│ │ │ ├── http.py
│ │ │ ├── local.py
│ │ │ ├── middleware
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── dispatcher.cpython-312.pyc
│ │ │ │ │ ├── http_proxy.cpython-312.pyc
│ │ │ │ │ ├── lint.cpython-312.pyc
│ │ │ │ │ ├── profiler.cpython-312.pyc
│ │ │ │ │ ├── proxy_fix.cpython-312.pyc
│ │ │ │ │ └── shared_data.cpython-312.pyc
│ │ │ │ ├── dispatcher.py
│ │ │ │ ├── http_proxy.py
│ │ │ │ ├── lint.py
│ │ │ │ ├── profiler.py
│ │ │ │ ├── proxy_fix.py
│ │ │ │ └── shared_data.py
│ │ │ ├── py.typed
│ │ │ ├── routing
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── converters.cpython-312.pyc
│ │ │ │ │ ├── exceptions.cpython-312.pyc
│ │ │ │ │ ├── map.cpython-312.pyc
│ │ │ │ │ ├── matcher.cpython-312.pyc
│ │ │ │ │ └── rules.cpython-312.pyc
│ │ │ │ ├── converters.py
│ │ │ │ ├── exceptions.py
│ │ │ │ ├── map.py
│ │ │ │ ├── matcher.py
│ │ │ │ └── rules.py
│ │ │ ├── sansio
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── http.cpython-312.pyc
│ │ │ │ │ ├── multipart.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ ├── response.cpython-312.pyc
│ │ │ │ │ └── utils.cpython-312.pyc
│ │ │ │ ├── http.py
│ │ │ │ ├── multipart.py
│ │ │ │ ├── request.py
│ │ │ │ ├── response.py
│ │ │ │ └── utils.py
│ │ │ ├── security.py
│ │ │ ├── serving.py
│ │ │ ├── test.py
│ │ │ ├── testapp.py
│ │ │ ├── urls.py
│ │ │ ├── user_agent.py
│ │ │ ├── utils.py
│ │ │ ├── wrappers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── __pycache__
│ │ │ │ │ ├── __init__.cpython-312.pyc
│ │ │ │ │ ├── request.cpython-312.pyc
│ │ │ │ │ └── response.cpython-312.pyc
│ │ │ │ ├── request.py
│ │ │ │ └── response.py
│ │ │ └── wsgi.py
│ │ └── werkzeug-3.0.4.dist-info
│ │ ├── INSTALLER
│ │ ├── LICENSE.txt
│ │ ├── METADATA
│ │ ├── RECORD
│ │ └── WHEEL
│ ├── pyvenv.cfg
│ ├── static
│ │ └── styles.css
│ ├── templates
│ │ └── index.html
│ └── test.py
├── cline_config.json
├── mcp_server.py
├── README.md
├── search_results.json
├── settings.json
└── test_files
├── text1.txt
└── text2.txt
```
# Files
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py:
--------------------------------------------------------------------------------
```python
1 | from collections import defaultdict
2 | from itertools import chain
3 | from operator import itemgetter
4 | from typing import Dict, Iterable, List, Optional, Tuple
5 |
6 | from .align import Align, AlignMethod
7 | from .console import Console, ConsoleOptions, RenderableType, RenderResult
8 | from .constrain import Constrain
9 | from .measure import Measurement
10 | from .padding import Padding, PaddingDimensions
11 | from .table import Table
12 | from .text import TextType
13 | from .jupyter import JupyterMixin
14 |
15 |
16 | class Columns(JupyterMixin):
17 | """Display renderables in neat columns.
18 |
19 | Args:
20 | renderables (Iterable[RenderableType]): Any number of Rich renderables (including str).
21 | width (int, optional): The desired width of the columns, or None to auto detect. Defaults to None.
22 | padding (PaddingDimensions, optional): Optional padding around cells. Defaults to (0, 1).
23 | expand (bool, optional): Expand columns to full width. Defaults to False.
24 | equal (bool, optional): Arrange in to equal sized columns. Defaults to False.
25 | column_first (bool, optional): Align items from top to bottom (rather than left to right). Defaults to False.
26 | right_to_left (bool, optional): Start column from right hand side. Defaults to False.
27 | align (str, optional): Align value ("left", "right", or "center") or None for default. Defaults to None.
28 | title (TextType, optional): Optional title for Columns.
29 | """
30 |
31 | def __init__(
32 | self,
33 | renderables: Optional[Iterable[RenderableType]] = None,
34 | padding: PaddingDimensions = (0, 1),
35 | *,
36 | width: Optional[int] = None,
37 | expand: bool = False,
38 | equal: bool = False,
39 | column_first: bool = False,
40 | right_to_left: bool = False,
41 | align: Optional[AlignMethod] = None,
42 | title: Optional[TextType] = None,
43 | ) -> None:
44 | self.renderables = list(renderables or [])
45 | self.width = width
46 | self.padding = padding
47 | self.expand = expand
48 | self.equal = equal
49 | self.column_first = column_first
50 | self.right_to_left = right_to_left
51 | self.align: Optional[AlignMethod] = align
52 | self.title = title
53 |
54 | def add_renderable(self, renderable: RenderableType) -> None:
55 | """Add a renderable to the columns.
56 |
57 | Args:
58 | renderable (RenderableType): Any renderable object.
59 | """
60 | self.renderables.append(renderable)
61 |
62 | def __rich_console__(
63 | self, console: Console, options: ConsoleOptions
64 | ) -> RenderResult:
65 | render_str = console.render_str
66 | renderables = [
67 | render_str(renderable) if isinstance(renderable, str) else renderable
68 | for renderable in self.renderables
69 | ]
70 | if not renderables:
71 | return
72 | _top, right, _bottom, left = Padding.unpack(self.padding)
73 | width_padding = max(left, right)
74 | max_width = options.max_width
75 | widths: Dict[int, int] = defaultdict(int)
76 | column_count = len(renderables)
77 |
78 | get_measurement = Measurement.get
79 | renderable_widths = [
80 | get_measurement(console, options, renderable).maximum
81 | for renderable in renderables
82 | ]
83 | if self.equal:
84 | renderable_widths = [max(renderable_widths)] * len(renderable_widths)
85 |
86 | def iter_renderables(
87 | column_count: int,
88 | ) -> Iterable[Tuple[int, Optional[RenderableType]]]:
89 | item_count = len(renderables)
90 | if self.column_first:
91 | width_renderables = list(zip(renderable_widths, renderables))
92 |
93 | column_lengths: List[int] = [item_count // column_count] * column_count
94 | for col_no in range(item_count % column_count):
95 | column_lengths[col_no] += 1
96 |
97 | row_count = (item_count + column_count - 1) // column_count
98 | cells = [[-1] * column_count for _ in range(row_count)]
99 | row = col = 0
100 | for index in range(item_count):
101 | cells[row][col] = index
102 | column_lengths[col] -= 1
103 | if column_lengths[col]:
104 | row += 1
105 | else:
106 | col += 1
107 | row = 0
108 | for index in chain.from_iterable(cells):
109 | if index == -1:
110 | break
111 | yield width_renderables[index]
112 | else:
113 | yield from zip(renderable_widths, renderables)
114 | # Pad odd elements with spaces
115 | if item_count % column_count:
116 | for _ in range(column_count - (item_count % column_count)):
117 | yield 0, None
118 |
119 | table = Table.grid(padding=self.padding, collapse_padding=True, pad_edge=False)
120 | table.expand = self.expand
121 | table.title = self.title
122 |
123 | if self.width is not None:
124 | column_count = (max_width) // (self.width + width_padding)
125 | for _ in range(column_count):
126 | table.add_column(width=self.width)
127 | else:
128 | while column_count > 1:
129 | widths.clear()
130 | column_no = 0
131 | for renderable_width, _ in iter_renderables(column_count):
132 | widths[column_no] = max(widths[column_no], renderable_width)
133 | total_width = sum(widths.values()) + width_padding * (
134 | len(widths) - 1
135 | )
136 | if total_width > max_width:
137 | column_count = len(widths) - 1
138 | break
139 | else:
140 | column_no = (column_no + 1) % column_count
141 | else:
142 | break
143 |
144 | get_renderable = itemgetter(1)
145 | _renderables = [
146 | get_renderable(_renderable)
147 | for _renderable in iter_renderables(column_count)
148 | ]
149 | if self.equal:
150 | _renderables = [
151 | None
152 | if renderable is None
153 | else Constrain(renderable, renderable_widths[0])
154 | for renderable in _renderables
155 | ]
156 | if self.align:
157 | align = self.align
158 | _Align = Align
159 | _renderables = [
160 | None if renderable is None else _Align(renderable, align)
161 | for renderable in _renderables
162 | ]
163 |
164 | right_to_left = self.right_to_left
165 | add_row = table.add_row
166 | for start in range(0, len(_renderables), column_count):
167 | row = _renderables[start : start + column_count]
168 | if right_to_left:
169 | row = row[::-1]
170 | add_row(*row)
171 | yield table
172 |
173 |
174 | if __name__ == "__main__": # pragma: no cover
175 | import os
176 |
177 | console = Console()
178 |
179 | files = [f"{i} {s}" for i, s in enumerate(sorted(os.listdir()))]
180 | columns = Columns(files, padding=(0, 1), expand=False, equal=False)
181 | console.print(columns)
182 | console.rule()
183 | columns.column_first = True
184 | console.print(columns)
185 | columns.right_to_left = True
186 | console.rule()
187 | console.print(columns)
188 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | pygments.formatters.svg
3 | ~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Formatter for SVG output.
6 |
7 | :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
8 | :license: BSD, see LICENSE for details.
9 | """
10 |
11 | from pip._vendor.pygments.formatter import Formatter
12 | from pip._vendor.pygments.token import Comment
13 | from pip._vendor.pygments.util import get_bool_opt, get_int_opt
14 |
15 | __all__ = ['SvgFormatter']
16 |
17 |
18 | def escape_html(text):
19 | """Escape &, <, > as well as single and double quotes for HTML."""
20 | return text.replace('&', '&'). \
21 | replace('<', '<'). \
22 | replace('>', '>'). \
23 | replace('"', '"'). \
24 | replace("'", ''')
25 |
26 |
27 | class2style = {}
28 |
29 | class SvgFormatter(Formatter):
30 | """
31 | Format tokens as an SVG graphics file. This formatter is still experimental.
32 | Each line of code is a ``<text>`` element with explicit ``x`` and ``y``
33 | coordinates containing ``<tspan>`` elements with the individual token styles.
34 |
35 | By default, this formatter outputs a full SVG document including doctype
36 | declaration and the ``<svg>`` root element.
37 |
38 | .. versionadded:: 0.9
39 |
40 | Additional options accepted:
41 |
42 | `nowrap`
43 | Don't wrap the SVG ``<text>`` elements in ``<svg><g>`` elements and
44 | don't add a XML declaration and a doctype. If true, the `fontfamily`
45 | and `fontsize` options are ignored. Defaults to ``False``.
46 |
47 | `fontfamily`
48 | The value to give the wrapping ``<g>`` element's ``font-family``
49 | attribute, defaults to ``"monospace"``.
50 |
51 | `fontsize`
52 | The value to give the wrapping ``<g>`` element's ``font-size``
53 | attribute, defaults to ``"14px"``.
54 |
55 | `linenos`
56 | If ``True``, add line numbers (default: ``False``).
57 |
58 | `linenostart`
59 | The line number for the first line (default: ``1``).
60 |
61 | `linenostep`
62 | If set to a number n > 1, only every nth line number is printed.
63 |
64 | `linenowidth`
65 | Maximum width devoted to line numbers (default: ``3*ystep``, sufficient
66 | for up to 4-digit line numbers. Increase width for longer code blocks).
67 |
68 | `xoffset`
69 | Starting offset in X direction, defaults to ``0``.
70 |
71 | `yoffset`
72 | Starting offset in Y direction, defaults to the font size if it is given
73 | in pixels, or ``20`` else. (This is necessary since text coordinates
74 | refer to the text baseline, not the top edge.)
75 |
76 | `ystep`
77 | Offset to add to the Y coordinate for each subsequent line. This should
78 | roughly be the text size plus 5. It defaults to that value if the text
79 | size is given in pixels, or ``25`` else.
80 |
81 | `spacehack`
82 | Convert spaces in the source to `` ``, which are non-breaking
83 | spaces. SVG provides the ``xml:space`` attribute to control how
84 | whitespace inside tags is handled, in theory, the ``preserve`` value
85 | could be used to keep all whitespace as-is. However, many current SVG
86 | viewers don't obey that rule, so this option is provided as a workaround
87 | and defaults to ``True``.
88 | """
89 | name = 'SVG'
90 | aliases = ['svg']
91 | filenames = ['*.svg']
92 |
93 | def __init__(self, **options):
94 | Formatter.__init__(self, **options)
95 | self.nowrap = get_bool_opt(options, 'nowrap', False)
96 | self.fontfamily = options.get('fontfamily', 'monospace')
97 | self.fontsize = options.get('fontsize', '14px')
98 | self.xoffset = get_int_opt(options, 'xoffset', 0)
99 | fs = self.fontsize.strip()
100 | if fs.endswith('px'):
101 | fs = fs[:-2].strip()
102 | try:
103 | int_fs = int(fs)
104 | except ValueError:
105 | int_fs = 20
106 | self.yoffset = get_int_opt(options, 'yoffset', int_fs)
107 | self.ystep = get_int_opt(options, 'ystep', int_fs + 5)
108 | self.spacehack = get_bool_opt(options, 'spacehack', True)
109 | self.linenos = get_bool_opt(options,'linenos',False)
110 | self.linenostart = get_int_opt(options,'linenostart',1)
111 | self.linenostep = get_int_opt(options,'linenostep',1)
112 | self.linenowidth = get_int_opt(options,'linenowidth', 3*self.ystep)
113 | self._stylecache = {}
114 |
115 | def format_unencoded(self, tokensource, outfile):
116 | """
117 | Format ``tokensource``, an iterable of ``(tokentype, tokenstring)``
118 | tuples and write it into ``outfile``.
119 |
120 | For our implementation we put all lines in their own 'line group'.
121 | """
122 | x = self.xoffset
123 | y = self.yoffset
124 | if not self.nowrap:
125 | if self.encoding:
126 | outfile.write(f'<?xml version="1.0" encoding="{self.encoding}"?>\n')
127 | else:
128 | outfile.write('<?xml version="1.0"?>\n')
129 | outfile.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" '
130 | '"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/'
131 | 'svg10.dtd">\n')
132 | outfile.write('<svg xmlns="http://www.w3.org/2000/svg">\n')
133 | outfile.write(f'<g font-family="{self.fontfamily}" font-size="{self.fontsize}">\n')
134 |
135 | counter = self.linenostart
136 | counter_step = self.linenostep
137 | counter_style = self._get_style(Comment)
138 | line_x = x
139 |
140 | if self.linenos:
141 | if counter % counter_step == 0:
142 | outfile.write(f'<text x="{x+self.linenowidth}" y="{y}" {counter_style} text-anchor="end">{counter}</text>')
143 | line_x += self.linenowidth + self.ystep
144 | counter += 1
145 |
146 | outfile.write(f'<text x="{line_x}" y="{y}" xml:space="preserve">')
147 | for ttype, value in tokensource:
148 | style = self._get_style(ttype)
149 | tspan = style and '<tspan' + style + '>' or ''
150 | tspanend = tspan and '</tspan>' or ''
151 | value = escape_html(value)
152 | if self.spacehack:
153 | value = value.expandtabs().replace(' ', ' ')
154 | parts = value.split('\n')
155 | for part in parts[:-1]:
156 | outfile.write(tspan + part + tspanend)
157 | y += self.ystep
158 | outfile.write('</text>\n')
159 | if self.linenos and counter % counter_step == 0:
160 | outfile.write(f'<text x="{x+self.linenowidth}" y="{y}" text-anchor="end" {counter_style}>{counter}</text>')
161 |
162 | counter += 1
163 | outfile.write(f'<text x="{line_x}" y="{y}" ' 'xml:space="preserve">')
164 | outfile.write(tspan + parts[-1] + tspanend)
165 | outfile.write('</text>')
166 |
167 | if not self.nowrap:
168 | outfile.write('</g></svg>\n')
169 |
170 | def _get_style(self, tokentype):
171 | if tokentype in self._stylecache:
172 | return self._stylecache[tokentype]
173 | otokentype = tokentype
174 | while not self.style.styles_token(tokentype):
175 | tokentype = tokentype.parent
176 | value = self.style.style_for_token(tokentype)
177 | result = ''
178 | if value['color']:
179 | result = ' fill="#' + value['color'] + '"'
180 | if value['bold']:
181 | result += ' font-weight="bold"'
182 | if value['italic']:
183 | result += ' font-style="italic"'
184 | self._stylecache[otokentype] = result
185 | return result
186 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/bs4/formatter.py:
--------------------------------------------------------------------------------
```python
1 | from bs4.dammit import EntitySubstitution
2 |
3 | class Formatter(EntitySubstitution):
4 | """Describes a strategy to use when outputting a parse tree to a string.
5 |
6 | Some parts of this strategy come from the distinction between
7 | HTML4, HTML5, and XML. Others are configurable by the user.
8 |
9 | Formatters are passed in as the `formatter` argument to methods
10 | like `PageElement.encode`. Most people won't need to think about
11 | formatters, and most people who need to think about them can pass
12 | in one of these predefined strings as `formatter` rather than
13 | making a new Formatter object:
14 |
15 | For HTML documents:
16 | * 'html' - HTML entity substitution for generic HTML documents. (default)
17 | * 'html5' - HTML entity substitution for HTML5 documents, as
18 | well as some optimizations in the way tags are rendered.
19 | * 'minimal' - Only make the substitutions necessary to guarantee
20 | valid HTML.
21 | * None - Do not perform any substitution. This will be faster
22 | but may result in invalid markup.
23 |
24 | For XML documents:
25 | * 'html' - Entity substitution for XHTML documents.
26 | * 'minimal' - Only make the substitutions necessary to guarantee
27 | valid XML. (default)
28 | * None - Do not perform any substitution. This will be faster
29 | but may result in invalid markup.
30 | """
31 | # Registries of XML and HTML formatters.
32 | XML_FORMATTERS = {}
33 | HTML_FORMATTERS = {}
34 |
35 | HTML = 'html'
36 | XML = 'xml'
37 |
38 | HTML_DEFAULTS = dict(
39 | cdata_containing_tags=set(["script", "style"]),
40 | )
41 |
42 | def _default(self, language, value, kwarg):
43 | if value is not None:
44 | return value
45 | if language == self.XML:
46 | return set()
47 | return self.HTML_DEFAULTS[kwarg]
48 |
49 | def __init__(
50 | self, language=None, entity_substitution=None,
51 | void_element_close_prefix='/', cdata_containing_tags=None,
52 | empty_attributes_are_booleans=False, indent=1,
53 | ):
54 | r"""Constructor.
55 |
56 | :param language: This should be Formatter.XML if you are formatting
57 | XML markup and Formatter.HTML if you are formatting HTML markup.
58 |
59 | :param entity_substitution: A function to call to replace special
60 | characters with XML/HTML entities. For examples, see
61 | bs4.dammit.EntitySubstitution.substitute_html and substitute_xml.
62 | :param void_element_close_prefix: By default, void elements
63 | are represented as <tag/> (XML rules) rather than <tag>
64 | (HTML rules). To get <tag>, pass in the empty string.
65 | :param cdata_containing_tags: The list of tags that are defined
66 | as containing CDATA in this dialect. For example, in HTML,
67 | <script> and <style> tags are defined as containing CDATA,
68 | and their contents should not be formatted.
69 | :param blank_attributes_are_booleans: Render attributes whose value
70 | is the empty string as HTML-style boolean attributes.
71 | (Attributes whose value is None are always rendered this way.)
72 |
73 | :param indent: If indent is a non-negative integer or string,
74 | then the contents of elements will be indented
75 | appropriately when pretty-printing. An indent level of 0,
76 | negative, or "" will only insert newlines. Using a
77 | positive integer indent indents that many spaces per
78 | level. If indent is a string (such as "\t"), that string
79 | is used to indent each level. The default behavior is to
80 | indent one space per level.
81 | """
82 | self.language = language
83 | self.entity_substitution = entity_substitution
84 | self.void_element_close_prefix = void_element_close_prefix
85 | self.cdata_containing_tags = self._default(
86 | language, cdata_containing_tags, 'cdata_containing_tags'
87 | )
88 | self.empty_attributes_are_booleans=empty_attributes_are_booleans
89 | if indent is None:
90 | indent = 0
91 | if isinstance(indent, int):
92 | if indent < 0:
93 | indent = 0
94 | indent = ' ' * indent
95 | elif isinstance(indent, str):
96 | indent = indent
97 | else:
98 | indent = ' '
99 | self.indent = indent
100 |
101 | def substitute(self, ns):
102 | """Process a string that needs to undergo entity substitution.
103 | This may be a string encountered in an attribute value or as
104 | text.
105 |
106 | :param ns: A string.
107 | :return: A string with certain characters replaced by named
108 | or numeric entities.
109 | """
110 | if not self.entity_substitution:
111 | return ns
112 | from .element import NavigableString
113 | if (isinstance(ns, NavigableString)
114 | and ns.parent is not None
115 | and ns.parent.name in self.cdata_containing_tags):
116 | # Do nothing.
117 | return ns
118 | # Substitute.
119 | return self.entity_substitution(ns)
120 |
121 | def attribute_value(self, value):
122 | """Process the value of an attribute.
123 |
124 | :param ns: A string.
125 | :return: A string with certain characters replaced by named
126 | or numeric entities.
127 | """
128 | return self.substitute(value)
129 |
130 | def attributes(self, tag):
131 | """Reorder a tag's attributes however you want.
132 |
133 | By default, attributes are sorted alphabetically. This makes
134 | behavior consistent between Python 2 and Python 3, and preserves
135 | backwards compatibility with older versions of Beautiful Soup.
136 |
137 | If `empty_boolean_attributes` is True, then attributes whose
138 | values are set to the empty string will be treated as boolean
139 | attributes.
140 | """
141 | if tag.attrs is None:
142 | return []
143 | return sorted(
144 | (k, (None if self.empty_attributes_are_booleans and v == '' else v))
145 | for k, v in list(tag.attrs.items())
146 | )
147 |
148 | class HTMLFormatter(Formatter):
149 | """A generic Formatter for HTML."""
150 | REGISTRY = {}
151 | def __init__(self, *args, **kwargs):
152 | super(HTMLFormatter, self).__init__(self.HTML, *args, **kwargs)
153 |
154 |
155 | class XMLFormatter(Formatter):
156 | """A generic Formatter for XML."""
157 | REGISTRY = {}
158 | def __init__(self, *args, **kwargs):
159 | super(XMLFormatter, self).__init__(self.XML, *args, **kwargs)
160 |
161 |
162 | # Set up aliases for the default formatters.
163 | HTMLFormatter.REGISTRY['html'] = HTMLFormatter(
164 | entity_substitution=EntitySubstitution.substitute_html
165 | )
166 | HTMLFormatter.REGISTRY["html5"] = HTMLFormatter(
167 | entity_substitution=EntitySubstitution.substitute_html,
168 | void_element_close_prefix=None,
169 | empty_attributes_are_booleans=True,
170 | )
171 | HTMLFormatter.REGISTRY["minimal"] = HTMLFormatter(
172 | entity_substitution=EntitySubstitution.substitute_xml
173 | )
174 | HTMLFormatter.REGISTRY[None] = HTMLFormatter(
175 | entity_substitution=None
176 | )
177 | XMLFormatter.REGISTRY["html"] = XMLFormatter(
178 | entity_substitution=EntitySubstitution.substitute_html
179 | )
180 | XMLFormatter.REGISTRY["minimal"] = XMLFormatter(
181 | entity_substitution=EntitySubstitution.substitute_xml
182 | )
183 | XMLFormatter.REGISTRY[None] = Formatter(
184 | Formatter(Formatter.XML, entity_substitution=None)
185 | )
186 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/bs4/diagnose.py:
--------------------------------------------------------------------------------
```python
1 | """Diagnostic functions, mainly for use when doing tech support."""
2 |
3 | # Use of this source code is governed by the MIT license.
4 | __license__ = "MIT"
5 |
6 | import cProfile
7 | from io import BytesIO
8 | from html.parser import HTMLParser
9 | import bs4
10 | from bs4 import BeautifulSoup, __version__
11 | from bs4.builder import builder_registry
12 |
13 | import os
14 | import pstats
15 | import random
16 | import tempfile
17 | import time
18 | import traceback
19 | import sys
20 | import cProfile
21 |
22 | def diagnose(data):
23 | """Diagnostic suite for isolating common problems.
24 |
25 | :param data: A string containing markup that needs to be explained.
26 | :return: None; diagnostics are printed to standard output.
27 | """
28 | print(("Diagnostic running on Beautiful Soup %s" % __version__))
29 | print(("Python version %s" % sys.version))
30 |
31 | basic_parsers = ["html.parser", "html5lib", "lxml"]
32 | for name in basic_parsers:
33 | for builder in builder_registry.builders:
34 | if name in builder.features:
35 | break
36 | else:
37 | basic_parsers.remove(name)
38 | print((
39 | "I noticed that %s is not installed. Installing it may help." %
40 | name))
41 |
42 | if 'lxml' in basic_parsers:
43 | basic_parsers.append("lxml-xml")
44 | try:
45 | from lxml import etree
46 | print(("Found lxml version %s" % ".".join(map(str,etree.LXML_VERSION))))
47 | except ImportError as e:
48 | print(
49 | "lxml is not installed or couldn't be imported.")
50 |
51 |
52 | if 'html5lib' in basic_parsers:
53 | try:
54 | import html5lib
55 | print(("Found html5lib version %s" % html5lib.__version__))
56 | except ImportError as e:
57 | print(
58 | "html5lib is not installed or couldn't be imported.")
59 |
60 | if hasattr(data, 'read'):
61 | data = data.read()
62 |
63 | for parser in basic_parsers:
64 | print(("Trying to parse your markup with %s" % parser))
65 | success = False
66 | try:
67 | soup = BeautifulSoup(data, features=parser)
68 | success = True
69 | except Exception as e:
70 | print(("%s could not parse the markup." % parser))
71 | traceback.print_exc()
72 | if success:
73 | print(("Here's what %s did with the markup:" % parser))
74 | print((soup.prettify()))
75 |
76 | print(("-" * 80))
77 |
78 | def lxml_trace(data, html=True, **kwargs):
79 | """Print out the lxml events that occur during parsing.
80 |
81 | This lets you see how lxml parses a document when no Beautiful
82 | Soup code is running. You can use this to determine whether
83 | an lxml-specific problem is in Beautiful Soup's lxml tree builders
84 | or in lxml itself.
85 |
86 | :param data: Some markup.
87 | :param html: If True, markup will be parsed with lxml's HTML parser.
88 | if False, lxml's XML parser will be used.
89 | """
90 | from lxml import etree
91 | recover = kwargs.pop('recover', True)
92 | if isinstance(data, str):
93 | data = data.encode("utf8")
94 | reader = BytesIO(data)
95 | for event, element in etree.iterparse(
96 | reader, html=html, recover=recover, **kwargs
97 | ):
98 | print(("%s, %4s, %s" % (event, element.tag, element.text)))
99 |
100 | class AnnouncingParser(HTMLParser):
101 | """Subclass of HTMLParser that announces parse events, without doing
102 | anything else.
103 |
104 | You can use this to get a picture of how html.parser sees a given
105 | document. The easiest way to do this is to call `htmlparser_trace`.
106 | """
107 |
108 | def _p(self, s):
109 | print(s)
110 |
111 | def handle_starttag(self, name, attrs):
112 | self._p("%s START" % name)
113 |
114 | def handle_endtag(self, name):
115 | self._p("%s END" % name)
116 |
117 | def handle_data(self, data):
118 | self._p("%s DATA" % data)
119 |
120 | def handle_charref(self, name):
121 | self._p("%s CHARREF" % name)
122 |
123 | def handle_entityref(self, name):
124 | self._p("%s ENTITYREF" % name)
125 |
126 | def handle_comment(self, data):
127 | self._p("%s COMMENT" % data)
128 |
129 | def handle_decl(self, data):
130 | self._p("%s DECL" % data)
131 |
132 | def unknown_decl(self, data):
133 | self._p("%s UNKNOWN-DECL" % data)
134 |
135 | def handle_pi(self, data):
136 | self._p("%s PI" % data)
137 |
138 | def htmlparser_trace(data):
139 | """Print out the HTMLParser events that occur during parsing.
140 |
141 | This lets you see how HTMLParser parses a document when no
142 | Beautiful Soup code is running.
143 |
144 | :param data: Some markup.
145 | """
146 | parser = AnnouncingParser()
147 | parser.feed(data)
148 |
149 | _vowels = "aeiou"
150 | _consonants = "bcdfghjklmnpqrstvwxyz"
151 |
152 | def rword(length=5):
153 | "Generate a random word-like string."
154 | s = ''
155 | for i in range(length):
156 | if i % 2 == 0:
157 | t = _consonants
158 | else:
159 | t = _vowels
160 | s += random.choice(t)
161 | return s
162 |
163 | def rsentence(length=4):
164 | "Generate a random sentence-like string."
165 | return " ".join(rword(random.randint(4,9)) for i in range(length))
166 |
167 | def rdoc(num_elements=1000):
168 | """Randomly generate an invalid HTML document."""
169 | tag_names = ['p', 'div', 'span', 'i', 'b', 'script', 'table']
170 | elements = []
171 | for i in range(num_elements):
172 | choice = random.randint(0,3)
173 | if choice == 0:
174 | # New tag.
175 | tag_name = random.choice(tag_names)
176 | elements.append("<%s>" % tag_name)
177 | elif choice == 1:
178 | elements.append(rsentence(random.randint(1,4)))
179 | elif choice == 2:
180 | # Close a tag.
181 | tag_name = random.choice(tag_names)
182 | elements.append("</%s>" % tag_name)
183 | return "<html>" + "\n".join(elements) + "</html>"
184 |
185 | def benchmark_parsers(num_elements=100000):
186 | """Very basic head-to-head performance benchmark."""
187 | print(("Comparative parser benchmark on Beautiful Soup %s" % __version__))
188 | data = rdoc(num_elements)
189 | print(("Generated a large invalid HTML document (%d bytes)." % len(data)))
190 |
191 | for parser in ["lxml", ["lxml", "html"], "html5lib", "html.parser"]:
192 | success = False
193 | try:
194 | a = time.time()
195 | soup = BeautifulSoup(data, parser)
196 | b = time.time()
197 | success = True
198 | except Exception as e:
199 | print(("%s could not parse the markup." % parser))
200 | traceback.print_exc()
201 | if success:
202 | print(("BS4+%s parsed the markup in %.2fs." % (parser, b-a)))
203 |
204 | from lxml import etree
205 | a = time.time()
206 | etree.HTML(data)
207 | b = time.time()
208 | print(("Raw lxml parsed the markup in %.2fs." % (b-a)))
209 |
210 | import html5lib
211 | parser = html5lib.HTMLParser()
212 | a = time.time()
213 | parser.parse(data)
214 | b = time.time()
215 | print(("Raw html5lib parsed the markup in %.2fs." % (b-a)))
216 |
217 | def profile(num_elements=100000, parser="lxml"):
218 | """Use Python's profiler on a randomly generated document."""
219 | filehandle = tempfile.NamedTemporaryFile()
220 | filename = filehandle.name
221 |
222 | data = rdoc(num_elements)
223 | vars = dict(bs4=bs4, data=data, parser=parser)
224 | cProfile.runctx('bs4.BeautifulSoup(data, parser)' , vars, vars, filename)
225 |
226 | stats = pstats.Stats(filename)
227 | # stats.strip_dirs()
228 | stats.sort_stats("cumulative")
229 | stats.print_stats('_html5lib|bs4', 50)
230 |
231 | # If this file is run as a script, standard input is diagnosed.
232 | if __name__ == '__main__':
233 | diagnose(sys.stdin.read())
234 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/pyproject.py:
--------------------------------------------------------------------------------
```python
1 | import importlib.util
2 | import os
3 | import sys
4 | from collections import namedtuple
5 | from typing import Any, List, Optional
6 |
7 | if sys.version_info >= (3, 11):
8 | import tomllib
9 | else:
10 | from pip._vendor import tomli as tomllib
11 |
12 | from pip._vendor.packaging.requirements import InvalidRequirement
13 |
14 | from pip._internal.exceptions import (
15 | InstallationError,
16 | InvalidPyProjectBuildRequires,
17 | MissingPyProjectBuildRequires,
18 | )
19 | from pip._internal.utils.packaging import get_requirement
20 |
21 |
22 | def _is_list_of_str(obj: Any) -> bool:
23 | return isinstance(obj, list) and all(isinstance(item, str) for item in obj)
24 |
25 |
26 | def make_pyproject_path(unpacked_source_directory: str) -> str:
27 | return os.path.join(unpacked_source_directory, "pyproject.toml")
28 |
29 |
30 | BuildSystemDetails = namedtuple(
31 | "BuildSystemDetails", ["requires", "backend", "check", "backend_path"]
32 | )
33 |
34 |
35 | def load_pyproject_toml(
36 | use_pep517: Optional[bool], pyproject_toml: str, setup_py: str, req_name: str
37 | ) -> Optional[BuildSystemDetails]:
38 | """Load the pyproject.toml file.
39 |
40 | Parameters:
41 | use_pep517 - Has the user requested PEP 517 processing? None
42 | means the user hasn't explicitly specified.
43 | pyproject_toml - Location of the project's pyproject.toml file
44 | setup_py - Location of the project's setup.py file
45 | req_name - The name of the requirement we're processing (for
46 | error reporting)
47 |
48 | Returns:
49 | None if we should use the legacy code path, otherwise a tuple
50 | (
51 | requirements from pyproject.toml,
52 | name of PEP 517 backend,
53 | requirements we should check are installed after setting
54 | up the build environment
55 | directory paths to import the backend from (backend-path),
56 | relative to the project root.
57 | )
58 | """
59 | has_pyproject = os.path.isfile(pyproject_toml)
60 | has_setup = os.path.isfile(setup_py)
61 |
62 | if not has_pyproject and not has_setup:
63 | raise InstallationError(
64 | f"{req_name} does not appear to be a Python project: "
65 | f"neither 'setup.py' nor 'pyproject.toml' found."
66 | )
67 |
68 | if has_pyproject:
69 | with open(pyproject_toml, encoding="utf-8") as f:
70 | pp_toml = tomllib.loads(f.read())
71 | build_system = pp_toml.get("build-system")
72 | else:
73 | build_system = None
74 |
75 | # The following cases must use PEP 517
76 | # We check for use_pep517 being non-None and falsey because that means
77 | # the user explicitly requested --no-use-pep517. The value 0 as
78 | # opposed to False can occur when the value is provided via an
79 | # environment variable or config file option (due to the quirk of
80 | # strtobool() returning an integer in pip's configuration code).
81 | if has_pyproject and not has_setup:
82 | if use_pep517 is not None and not use_pep517:
83 | raise InstallationError(
84 | "Disabling PEP 517 processing is invalid: "
85 | "project does not have a setup.py"
86 | )
87 | use_pep517 = True
88 | elif build_system and "build-backend" in build_system:
89 | if use_pep517 is not None and not use_pep517:
90 | raise InstallationError(
91 | "Disabling PEP 517 processing is invalid: "
92 | "project specifies a build backend of {} "
93 | "in pyproject.toml".format(build_system["build-backend"])
94 | )
95 | use_pep517 = True
96 |
97 | # If we haven't worked out whether to use PEP 517 yet,
98 | # and the user hasn't explicitly stated a preference,
99 | # we do so if the project has a pyproject.toml file
100 | # or if we cannot import setuptools or wheels.
101 |
102 | # We fallback to PEP 517 when without setuptools or without the wheel package,
103 | # so setuptools can be installed as a default build backend.
104 | # For more info see:
105 | # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9
106 | # https://github.com/pypa/pip/issues/8559
107 | elif use_pep517 is None:
108 | use_pep517 = (
109 | has_pyproject
110 | or not importlib.util.find_spec("setuptools")
111 | or not importlib.util.find_spec("wheel")
112 | )
113 |
114 | # At this point, we know whether we're going to use PEP 517.
115 | assert use_pep517 is not None
116 |
117 | # If we're using the legacy code path, there is nothing further
118 | # for us to do here.
119 | if not use_pep517:
120 | return None
121 |
122 | if build_system is None:
123 | # Either the user has a pyproject.toml with no build-system
124 | # section, or the user has no pyproject.toml, but has opted in
125 | # explicitly via --use-pep517.
126 | # In the absence of any explicit backend specification, we
127 | # assume the setuptools backend that most closely emulates the
128 | # traditional direct setup.py execution, and require wheel and
129 | # a version of setuptools that supports that backend.
130 |
131 | build_system = {
132 | "requires": ["setuptools>=40.8.0"],
133 | "build-backend": "setuptools.build_meta:__legacy__",
134 | }
135 |
136 | # If we're using PEP 517, we have build system information (either
137 | # from pyproject.toml, or defaulted by the code above).
138 | # Note that at this point, we do not know if the user has actually
139 | # specified a backend, though.
140 | assert build_system is not None
141 |
142 | # Ensure that the build-system section in pyproject.toml conforms
143 | # to PEP 518.
144 |
145 | # Specifying the build-system table but not the requires key is invalid
146 | if "requires" not in build_system:
147 | raise MissingPyProjectBuildRequires(package=req_name)
148 |
149 | # Error out if requires is not a list of strings
150 | requires = build_system["requires"]
151 | if not _is_list_of_str(requires):
152 | raise InvalidPyProjectBuildRequires(
153 | package=req_name,
154 | reason="It is not a list of strings.",
155 | )
156 |
157 | # Each requirement must be valid as per PEP 508
158 | for requirement in requires:
159 | try:
160 | get_requirement(requirement)
161 | except InvalidRequirement as error:
162 | raise InvalidPyProjectBuildRequires(
163 | package=req_name,
164 | reason=f"It contains an invalid requirement: {requirement!r}",
165 | ) from error
166 |
167 | backend = build_system.get("build-backend")
168 | backend_path = build_system.get("backend-path", [])
169 | check: List[str] = []
170 | if backend is None:
171 | # If the user didn't specify a backend, we assume they want to use
172 | # the setuptools backend. But we can't be sure they have included
173 | # a version of setuptools which supplies the backend. So we
174 | # make a note to check that this requirement is present once
175 | # we have set up the environment.
176 | # This is quite a lot of work to check for a very specific case. But
177 | # the problem is, that case is potentially quite common - projects that
178 | # adopted PEP 518 early for the ability to specify requirements to
179 | # execute setup.py, but never considered needing to mention the build
180 | # tools themselves. The original PEP 518 code had a similar check (but
181 | # implemented in a different way).
182 | backend = "setuptools.build_meta:__legacy__"
183 | check = ["setuptools>=40.8.0"]
184 |
185 | return BuildSystemDetails(requires, backend, check, backend_path)
186 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/werkzeug/routing/converters.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import re
4 | import typing as t
5 | import uuid
6 | from urllib.parse import quote
7 |
8 | if t.TYPE_CHECKING:
9 | from .map import Map
10 |
11 |
12 | class ValidationError(ValueError):
13 | """Validation error. If a rule converter raises this exception the rule
14 | does not match the current URL and the next URL is tried.
15 | """
16 |
17 |
18 | class BaseConverter:
19 | """Base class for all converters.
20 |
21 | .. versionchanged:: 2.3
22 | ``part_isolating`` defaults to ``False`` if ``regex`` contains a ``/``.
23 | """
24 |
25 | regex = "[^/]+"
26 | weight = 100
27 | part_isolating = True
28 |
29 | def __init_subclass__(cls, **kwargs: t.Any) -> None:
30 | super().__init_subclass__(**kwargs)
31 |
32 | # If the converter isn't inheriting its regex, disable part_isolating by default
33 | # if the regex contains a / character.
34 | if "regex" in cls.__dict__ and "part_isolating" not in cls.__dict__:
35 | cls.part_isolating = "/" not in cls.regex
36 |
37 | def __init__(self, map: Map, *args: t.Any, **kwargs: t.Any) -> None:
38 | self.map = map
39 |
40 | def to_python(self, value: str) -> t.Any:
41 | return value
42 |
43 | def to_url(self, value: t.Any) -> str:
44 | # safe = https://url.spec.whatwg.org/#url-path-segment-string
45 | return quote(str(value), safe="!$&'()*+,/:;=@")
46 |
47 |
48 | class UnicodeConverter(BaseConverter):
49 | """This converter is the default converter and accepts any string but
50 | only one path segment. Thus the string can not include a slash.
51 |
52 | This is the default validator.
53 |
54 | Example::
55 |
56 | Rule('/pages/<page>'),
57 | Rule('/<string(length=2):lang_code>')
58 |
59 | :param map: the :class:`Map`.
60 | :param minlength: the minimum length of the string. Must be greater
61 | or equal 1.
62 | :param maxlength: the maximum length of the string.
63 | :param length: the exact length of the string.
64 | """
65 |
66 | def __init__(
67 | self,
68 | map: Map,
69 | minlength: int = 1,
70 | maxlength: int | None = None,
71 | length: int | None = None,
72 | ) -> None:
73 | super().__init__(map)
74 | if length is not None:
75 | length_regex = f"{{{int(length)}}}"
76 | else:
77 | if maxlength is None:
78 | maxlength_value = ""
79 | else:
80 | maxlength_value = str(int(maxlength))
81 | length_regex = f"{{{int(minlength)},{maxlength_value}}}"
82 | self.regex = f"[^/]{length_regex}"
83 |
84 |
85 | class AnyConverter(BaseConverter):
86 | """Matches one of the items provided. Items can either be Python
87 | identifiers or strings::
88 |
89 | Rule('/<any(about, help, imprint, class, "foo,bar"):page_name>')
90 |
91 | :param map: the :class:`Map`.
92 | :param items: this function accepts the possible items as positional
93 | arguments.
94 |
95 | .. versionchanged:: 2.2
96 | Value is validated when building a URL.
97 | """
98 |
99 | def __init__(self, map: Map, *items: str) -> None:
100 | super().__init__(map)
101 | self.items = set(items)
102 | self.regex = f"(?:{'|'.join([re.escape(x) for x in items])})"
103 |
104 | def to_url(self, value: t.Any) -> str:
105 | if value in self.items:
106 | return str(value)
107 |
108 | valid_values = ", ".join(f"'{item}'" for item in sorted(self.items))
109 | raise ValueError(f"'{value}' is not one of {valid_values}")
110 |
111 |
112 | class PathConverter(BaseConverter):
113 | """Like the default :class:`UnicodeConverter`, but it also matches
114 | slashes. This is useful for wikis and similar applications::
115 |
116 | Rule('/<path:wikipage>')
117 | Rule('/<path:wikipage>/edit')
118 |
119 | :param map: the :class:`Map`.
120 | """
121 |
122 | part_isolating = False
123 | regex = "[^/].*?"
124 | weight = 200
125 |
126 |
127 | class NumberConverter(BaseConverter):
128 | """Baseclass for `IntegerConverter` and `FloatConverter`.
129 |
130 | :internal:
131 | """
132 |
133 | weight = 50
134 | num_convert: t.Callable[[t.Any], t.Any] = int
135 |
136 | def __init__(
137 | self,
138 | map: Map,
139 | fixed_digits: int = 0,
140 | min: int | None = None,
141 | max: int | None = None,
142 | signed: bool = False,
143 | ) -> None:
144 | if signed:
145 | self.regex = self.signed_regex
146 | super().__init__(map)
147 | self.fixed_digits = fixed_digits
148 | self.min = min
149 | self.max = max
150 | self.signed = signed
151 |
152 | def to_python(self, value: str) -> t.Any:
153 | if self.fixed_digits and len(value) != self.fixed_digits:
154 | raise ValidationError()
155 | value_num = self.num_convert(value)
156 | if (self.min is not None and value_num < self.min) or (
157 | self.max is not None and value_num > self.max
158 | ):
159 | raise ValidationError()
160 | return value_num
161 |
162 | def to_url(self, value: t.Any) -> str:
163 | value_str = str(self.num_convert(value))
164 | if self.fixed_digits:
165 | value_str = value_str.zfill(self.fixed_digits)
166 | return value_str
167 |
168 | @property
169 | def signed_regex(self) -> str:
170 | return f"-?{self.regex}"
171 |
172 |
173 | class IntegerConverter(NumberConverter):
174 | """This converter only accepts integer values::
175 |
176 | Rule("/page/<int:page>")
177 |
178 | By default it only accepts unsigned, positive values. The ``signed``
179 | parameter will enable signed, negative values. ::
180 |
181 | Rule("/page/<int(signed=True):page>")
182 |
183 | :param map: The :class:`Map`.
184 | :param fixed_digits: The number of fixed digits in the URL. If you
185 | set this to ``4`` for example, the rule will only match if the
186 | URL looks like ``/0001/``. The default is variable length.
187 | :param min: The minimal value.
188 | :param max: The maximal value.
189 | :param signed: Allow signed (negative) values.
190 |
191 | .. versionadded:: 0.15
192 | The ``signed`` parameter.
193 | """
194 |
195 | regex = r"\d+"
196 |
197 |
198 | class FloatConverter(NumberConverter):
199 | """This converter only accepts floating point values::
200 |
201 | Rule("/probability/<float:probability>")
202 |
203 | By default it only accepts unsigned, positive values. The ``signed``
204 | parameter will enable signed, negative values. ::
205 |
206 | Rule("/offset/<float(signed=True):offset>")
207 |
208 | :param map: The :class:`Map`.
209 | :param min: The minimal value.
210 | :param max: The maximal value.
211 | :param signed: Allow signed (negative) values.
212 |
213 | .. versionadded:: 0.15
214 | The ``signed`` parameter.
215 | """
216 |
217 | regex = r"\d+\.\d+"
218 | num_convert = float
219 |
220 | def __init__(
221 | self,
222 | map: Map,
223 | min: float | None = None,
224 | max: float | None = None,
225 | signed: bool = False,
226 | ) -> None:
227 | super().__init__(map, min=min, max=max, signed=signed) # type: ignore
228 |
229 |
230 | class UUIDConverter(BaseConverter):
231 | """This converter only accepts UUID strings::
232 |
233 | Rule('/object/<uuid:identifier>')
234 |
235 | .. versionadded:: 0.10
236 |
237 | :param map: the :class:`Map`.
238 | """
239 |
240 | regex = (
241 | r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-"
242 | r"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}"
243 | )
244 |
245 | def to_python(self, value: str) -> uuid.UUID:
246 | return uuid.UUID(value)
247 |
248 | def to_url(self, value: uuid.UUID) -> str:
249 | return str(value)
250 |
251 |
252 | #: the default converter mapping for the map.
253 | DEFAULT_CONVERTERS: t.Mapping[str, type[BaseConverter]] = {
254 | "default": UnicodeConverter,
255 | "string": UnicodeConverter,
256 | "any": AnyConverter,
257 | "path": PathConverter,
258 | "int": IntegerConverter,
259 | "float": FloatConverter,
260 | "uuid": UUIDConverter,
261 | }
262 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py:
--------------------------------------------------------------------------------
```python
1 | import functools
2 | import importlib.metadata
3 | import logging
4 | import os
5 | import pathlib
6 | import sys
7 | import zipfile
8 | import zipimport
9 | from typing import Iterator, List, Optional, Sequence, Set, Tuple
10 |
11 | from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
12 |
13 | from pip._internal.metadata.base import BaseDistribution, BaseEnvironment
14 | from pip._internal.models.wheel import Wheel
15 | from pip._internal.utils.deprecation import deprecated
16 | from pip._internal.utils.filetypes import WHEEL_EXTENSION
17 |
18 | from ._compat import BadMetadata, BasePath, get_dist_canonical_name, get_info_location
19 | from ._dists import Distribution
20 |
21 | logger = logging.getLogger(__name__)
22 |
23 |
24 | def _looks_like_wheel(location: str) -> bool:
25 | if not location.endswith(WHEEL_EXTENSION):
26 | return False
27 | if not os.path.isfile(location):
28 | return False
29 | if not Wheel.wheel_file_re.match(os.path.basename(location)):
30 | return False
31 | return zipfile.is_zipfile(location)
32 |
33 |
34 | class _DistributionFinder:
35 | """Finder to locate distributions.
36 |
37 | The main purpose of this class is to memoize found distributions' names, so
38 | only one distribution is returned for each package name. At lot of pip code
39 | assumes this (because it is setuptools's behavior), and not doing the same
40 | can potentially cause a distribution in lower precedence path to override a
41 | higher precedence one if the caller is not careful.
42 |
43 | Eventually we probably want to make it possible to see lower precedence
44 | installations as well. It's useful feature, after all.
45 | """
46 |
47 | FoundResult = Tuple[importlib.metadata.Distribution, Optional[BasePath]]
48 |
49 | def __init__(self) -> None:
50 | self._found_names: Set[NormalizedName] = set()
51 |
52 | def _find_impl(self, location: str) -> Iterator[FoundResult]:
53 | """Find distributions in a location."""
54 | # Skip looking inside a wheel. Since a package inside a wheel is not
55 | # always valid (due to .data directories etc.), its .dist-info entry
56 | # should not be considered an installed distribution.
57 | if _looks_like_wheel(location):
58 | return
59 | # To know exactly where we find a distribution, we have to feed in the
60 | # paths one by one, instead of dumping the list to importlib.metadata.
61 | for dist in importlib.metadata.distributions(path=[location]):
62 | info_location = get_info_location(dist)
63 | try:
64 | name = get_dist_canonical_name(dist)
65 | except BadMetadata as e:
66 | logger.warning("Skipping %s due to %s", info_location, e.reason)
67 | continue
68 | if name in self._found_names:
69 | continue
70 | self._found_names.add(name)
71 | yield dist, info_location
72 |
73 | def find(self, location: str) -> Iterator[BaseDistribution]:
74 | """Find distributions in a location.
75 |
76 | The path can be either a directory, or a ZIP archive.
77 | """
78 | for dist, info_location in self._find_impl(location):
79 | if info_location is None:
80 | installed_location: Optional[BasePath] = None
81 | else:
82 | installed_location = info_location.parent
83 | yield Distribution(dist, info_location, installed_location)
84 |
85 | def find_linked(self, location: str) -> Iterator[BaseDistribution]:
86 | """Read location in egg-link files and return distributions in there.
87 |
88 | The path should be a directory; otherwise this returns nothing. This
89 | follows how setuptools does this for compatibility. The first non-empty
90 | line in the egg-link is read as a path (resolved against the egg-link's
91 | containing directory if relative). Distributions found at that linked
92 | location are returned.
93 | """
94 | path = pathlib.Path(location)
95 | if not path.is_dir():
96 | return
97 | for child in path.iterdir():
98 | if child.suffix != ".egg-link":
99 | continue
100 | with child.open() as f:
101 | lines = (line.strip() for line in f)
102 | target_rel = next((line for line in lines if line), "")
103 | if not target_rel:
104 | continue
105 | target_location = str(path.joinpath(target_rel))
106 | for dist, info_location in self._find_impl(target_location):
107 | yield Distribution(dist, info_location, path)
108 |
109 | def _find_eggs_in_dir(self, location: str) -> Iterator[BaseDistribution]:
110 | from pip._vendor.pkg_resources import find_distributions
111 |
112 | from pip._internal.metadata import pkg_resources as legacy
113 |
114 | with os.scandir(location) as it:
115 | for entry in it:
116 | if not entry.name.endswith(".egg"):
117 | continue
118 | for dist in find_distributions(entry.path):
119 | yield legacy.Distribution(dist)
120 |
121 | def _find_eggs_in_zip(self, location: str) -> Iterator[BaseDistribution]:
122 | from pip._vendor.pkg_resources import find_eggs_in_zip
123 |
124 | from pip._internal.metadata import pkg_resources as legacy
125 |
126 | try:
127 | importer = zipimport.zipimporter(location)
128 | except zipimport.ZipImportError:
129 | return
130 | for dist in find_eggs_in_zip(importer, location):
131 | yield legacy.Distribution(dist)
132 |
133 | def find_eggs(self, location: str) -> Iterator[BaseDistribution]:
134 | """Find eggs in a location.
135 |
136 | This actually uses the old *pkg_resources* backend. We likely want to
137 | deprecate this so we can eventually remove the *pkg_resources*
138 | dependency entirely. Before that, this should first emit a deprecation
139 | warning for some versions when using the fallback since importing
140 | *pkg_resources* is slow for those who don't need it.
141 | """
142 | if os.path.isdir(location):
143 | yield from self._find_eggs_in_dir(location)
144 | if zipfile.is_zipfile(location):
145 | yield from self._find_eggs_in_zip(location)
146 |
147 |
148 | @functools.lru_cache(maxsize=None) # Warn a distribution exactly once.
149 | def _emit_egg_deprecation(location: Optional[str]) -> None:
150 | deprecated(
151 | reason=f"Loading egg at {location} is deprecated.",
152 | replacement="to use pip for package installation",
153 | gone_in="24.3",
154 | issue=12330,
155 | )
156 |
157 |
158 | class Environment(BaseEnvironment):
159 | def __init__(self, paths: Sequence[str]) -> None:
160 | self._paths = paths
161 |
162 | @classmethod
163 | def default(cls) -> BaseEnvironment:
164 | return cls(sys.path)
165 |
166 | @classmethod
167 | def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment:
168 | if paths is None:
169 | return cls(sys.path)
170 | return cls(paths)
171 |
172 | def _iter_distributions(self) -> Iterator[BaseDistribution]:
173 | finder = _DistributionFinder()
174 | for location in self._paths:
175 | yield from finder.find(location)
176 | for dist in finder.find_eggs(location):
177 | _emit_egg_deprecation(dist.location)
178 | yield dist
179 | # This must go last because that's how pkg_resources tie-breaks.
180 | yield from finder.find_linked(location)
181 |
182 | def get_distribution(self, name: str) -> Optional[BaseDistribution]:
183 | canonical_name = canonicalize_name(name)
184 | matches = (
185 | distribution
186 | for distribution in self.iter_all_distributions()
187 | if distribution.canonical_name == canonical_name
188 | )
189 | return next(matches, None)
190 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/commands/show.py:
--------------------------------------------------------------------------------
```python
1 | import logging
2 | from optparse import Values
3 | from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional
4 |
5 | from pip._vendor.packaging.requirements import InvalidRequirement
6 | from pip._vendor.packaging.utils import canonicalize_name
7 |
8 | from pip._internal.cli.base_command import Command
9 | from pip._internal.cli.status_codes import ERROR, SUCCESS
10 | from pip._internal.metadata import BaseDistribution, get_default_environment
11 | from pip._internal.utils.misc import write_output
12 |
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | class ShowCommand(Command):
17 | """
18 | Show information about one or more installed packages.
19 |
20 | The output is in RFC-compliant mail header format.
21 | """
22 |
23 | usage = """
24 | %prog [options] <package> ..."""
25 | ignore_require_venv = True
26 |
27 | def add_options(self) -> None:
28 | self.cmd_opts.add_option(
29 | "-f",
30 | "--files",
31 | dest="files",
32 | action="store_true",
33 | default=False,
34 | help="Show the full list of installed files for each package.",
35 | )
36 |
37 | self.parser.insert_option_group(0, self.cmd_opts)
38 |
39 | def run(self, options: Values, args: List[str]) -> int:
40 | if not args:
41 | logger.warning("ERROR: Please provide a package name or names.")
42 | return ERROR
43 | query = args
44 |
45 | results = search_packages_info(query)
46 | if not print_results(
47 | results, list_files=options.files, verbose=options.verbose
48 | ):
49 | return ERROR
50 | return SUCCESS
51 |
52 |
53 | class _PackageInfo(NamedTuple):
54 | name: str
55 | version: str
56 | location: str
57 | editable_project_location: Optional[str]
58 | requires: List[str]
59 | required_by: List[str]
60 | installer: str
61 | metadata_version: str
62 | classifiers: List[str]
63 | summary: str
64 | homepage: str
65 | project_urls: List[str]
66 | author: str
67 | author_email: str
68 | license: str
69 | entry_points: List[str]
70 | files: Optional[List[str]]
71 |
72 |
73 | def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None]:
74 | """
75 | Gather details from installed distributions. Print distribution name,
76 | version, location, and installed files. Installed files requires a
77 | pip generated 'installed-files.txt' in the distributions '.egg-info'
78 | directory.
79 | """
80 | env = get_default_environment()
81 |
82 | installed = {dist.canonical_name: dist for dist in env.iter_all_distributions()}
83 | query_names = [canonicalize_name(name) for name in query]
84 | missing = sorted(
85 | [name for name, pkg in zip(query, query_names) if pkg not in installed]
86 | )
87 | if missing:
88 | logger.warning("Package(s) not found: %s", ", ".join(missing))
89 |
90 | def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
91 | return (
92 | dist.metadata["Name"] or "UNKNOWN"
93 | for dist in installed.values()
94 | if current_dist.canonical_name
95 | in {canonicalize_name(d.name) for d in dist.iter_dependencies()}
96 | )
97 |
98 | for query_name in query_names:
99 | try:
100 | dist = installed[query_name]
101 | except KeyError:
102 | continue
103 |
104 | try:
105 | requires = sorted(
106 | # Avoid duplicates in requirements (e.g. due to environment markers).
107 | {req.name for req in dist.iter_dependencies()},
108 | key=str.lower,
109 | )
110 | except InvalidRequirement:
111 | requires = sorted(dist.iter_raw_dependencies(), key=str.lower)
112 |
113 | try:
114 | required_by = sorted(_get_requiring_packages(dist), key=str.lower)
115 | except InvalidRequirement:
116 | required_by = ["#N/A"]
117 |
118 | try:
119 | entry_points_text = dist.read_text("entry_points.txt")
120 | entry_points = entry_points_text.splitlines(keepends=False)
121 | except FileNotFoundError:
122 | entry_points = []
123 |
124 | files_iter = dist.iter_declared_entries()
125 | if files_iter is None:
126 | files: Optional[List[str]] = None
127 | else:
128 | files = sorted(files_iter)
129 |
130 | metadata = dist.metadata
131 |
132 | project_urls = metadata.get_all("Project-URL", [])
133 | homepage = metadata.get("Home-page", "")
134 | if not homepage:
135 | # It's common that there is a "homepage" Project-URL, but Home-page
136 | # remains unset (especially as PEP 621 doesn't surface the field).
137 | #
138 | # This logic was taken from PyPI's codebase.
139 | for url in project_urls:
140 | url_label, url = url.split(",", maxsplit=1)
141 | normalized_label = (
142 | url_label.casefold().replace("-", "").replace("_", "").strip()
143 | )
144 | if normalized_label == "homepage":
145 | homepage = url.strip()
146 | break
147 |
148 | yield _PackageInfo(
149 | name=dist.raw_name,
150 | version=dist.raw_version,
151 | location=dist.location or "",
152 | editable_project_location=dist.editable_project_location,
153 | requires=requires,
154 | required_by=required_by,
155 | installer=dist.installer,
156 | metadata_version=dist.metadata_version or "",
157 | classifiers=metadata.get_all("Classifier", []),
158 | summary=metadata.get("Summary", ""),
159 | homepage=homepage,
160 | project_urls=project_urls,
161 | author=metadata.get("Author", ""),
162 | author_email=metadata.get("Author-email", ""),
163 | license=metadata.get("License", ""),
164 | entry_points=entry_points,
165 | files=files,
166 | )
167 |
168 |
169 | def print_results(
170 | distributions: Iterable[_PackageInfo],
171 | list_files: bool,
172 | verbose: bool,
173 | ) -> bool:
174 | """
175 | Print the information from installed distributions found.
176 | """
177 | results_printed = False
178 | for i, dist in enumerate(distributions):
179 | results_printed = True
180 | if i > 0:
181 | write_output("---")
182 |
183 | write_output("Name: %s", dist.name)
184 | write_output("Version: %s", dist.version)
185 | write_output("Summary: %s", dist.summary)
186 | write_output("Home-page: %s", dist.homepage)
187 | write_output("Author: %s", dist.author)
188 | write_output("Author-email: %s", dist.author_email)
189 | write_output("License: %s", dist.license)
190 | write_output("Location: %s", dist.location)
191 | if dist.editable_project_location is not None:
192 | write_output(
193 | "Editable project location: %s", dist.editable_project_location
194 | )
195 | write_output("Requires: %s", ", ".join(dist.requires))
196 | write_output("Required-by: %s", ", ".join(dist.required_by))
197 |
198 | if verbose:
199 | write_output("Metadata-Version: %s", dist.metadata_version)
200 | write_output("Installer: %s", dist.installer)
201 | write_output("Classifiers:")
202 | for classifier in dist.classifiers:
203 | write_output(" %s", classifier)
204 | write_output("Entry-points:")
205 | for entry in dist.entry_points:
206 | write_output(" %s", entry.strip())
207 | write_output("Project-URLs:")
208 | for project_url in dist.project_urls:
209 | write_output(" %s", project_url)
210 | if list_files:
211 | write_output("Files:")
212 | if dist.files is None:
213 | write_output("Cannot locate RECORD or installed-files.txt")
214 | else:
215 | for line in dist.files:
216 | write_output(" %s", line.strip())
217 | return results_printed
218 |
```