This is page 65 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/distlib/scripts.py:
--------------------------------------------------------------------------------
```python
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright (C) 2013-2023 Vinay Sajip.
4 | # Licensed to the Python Software Foundation under a contributor agreement.
5 | # See LICENSE.txt and CONTRIBUTORS.txt.
6 | #
7 | from io import BytesIO
8 | import logging
9 | import os
10 | import re
11 | import struct
12 | import sys
13 | import time
14 | from zipfile import ZipInfo
15 |
16 | from .compat import sysconfig, detect_encoding, ZipFile
17 | from .resources import finder
18 | from .util import (FileOperator, get_export_entry, convert_path,
19 | get_executable, get_platform, in_venv)
20 |
21 | logger = logging.getLogger(__name__)
22 |
23 | _DEFAULT_MANIFEST = '''
24 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
25 | <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
26 | <assemblyIdentity version="1.0.0.0"
27 | processorArchitecture="X86"
28 | name="%s"
29 | type="win32"/>
30 |
31 | <!-- Identify the application security requirements. -->
32 | <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
33 | <security>
34 | <requestedPrivileges>
35 | <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
36 | </requestedPrivileges>
37 | </security>
38 | </trustInfo>
39 | </assembly>'''.strip()
40 |
41 | # check if Python is called on the first line with this expression
42 | FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$')
43 | SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*-
44 | import re
45 | import sys
46 | from %(module)s import %(import_name)s
47 | if __name__ == '__main__':
48 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
49 | sys.exit(%(func)s())
50 | '''
51 |
52 | # Pre-fetch the contents of all executable wrapper stubs.
53 | # This is to address https://github.com/pypa/pip/issues/12666.
54 | # When updating pip, we rename the old pip in place before installing the
55 | # new version. If we try to fetch a wrapper *after* that rename, the finder
56 | # machinery will be confused as the package is no longer available at the
57 | # location where it was imported from. So we load everything into memory in
58 | # advance.
59 |
60 | # Issue 31: don't hardcode an absolute package name, but
61 | # determine it relative to the current package
62 | distlib_package = __name__.rsplit('.', 1)[0]
63 |
64 | WRAPPERS = {
65 | r.name: r.bytes
66 | for r in finder(distlib_package).iterator("")
67 | if r.name.endswith(".exe")
68 | }
69 |
70 |
71 | def enquote_executable(executable):
72 | if ' ' in executable:
73 | # make sure we quote only the executable in case of env
74 | # for example /usr/bin/env "/dir with spaces/bin/jython"
75 | # instead of "/usr/bin/env /dir with spaces/bin/jython"
76 | # otherwise whole
77 | if executable.startswith('/usr/bin/env '):
78 | env, _executable = executable.split(' ', 1)
79 | if ' ' in _executable and not _executable.startswith('"'):
80 | executable = '%s "%s"' % (env, _executable)
81 | else:
82 | if not executable.startswith('"'):
83 | executable = '"%s"' % executable
84 | return executable
85 |
86 |
87 | # Keep the old name around (for now), as there is at least one project using it!
88 | _enquote_executable = enquote_executable
89 |
90 |
91 | class ScriptMaker(object):
92 | """
93 | A class to copy or create scripts from source scripts or callable
94 | specifications.
95 | """
96 | script_template = SCRIPT_TEMPLATE
97 |
98 | executable = None # for shebangs
99 |
100 | def __init__(self,
101 | source_dir,
102 | target_dir,
103 | add_launchers=True,
104 | dry_run=False,
105 | fileop=None):
106 | self.source_dir = source_dir
107 | self.target_dir = target_dir
108 | self.add_launchers = add_launchers
109 | self.force = False
110 | self.clobber = False
111 | # It only makes sense to set mode bits on POSIX.
112 | self.set_mode = (os.name == 'posix') or (os.name == 'java'
113 | and os._name == 'posix')
114 | self.variants = set(('', 'X.Y'))
115 | self._fileop = fileop or FileOperator(dry_run)
116 |
117 | self._is_nt = os.name == 'nt' or (os.name == 'java'
118 | and os._name == 'nt')
119 | self.version_info = sys.version_info
120 |
121 | def _get_alternate_executable(self, executable, options):
122 | if options.get('gui', False) and self._is_nt: # pragma: no cover
123 | dn, fn = os.path.split(executable)
124 | fn = fn.replace('python', 'pythonw')
125 | executable = os.path.join(dn, fn)
126 | return executable
127 |
128 | if sys.platform.startswith('java'): # pragma: no cover
129 |
130 | def _is_shell(self, executable):
131 | """
132 | Determine if the specified executable is a script
133 | (contains a #! line)
134 | """
135 | try:
136 | with open(executable) as fp:
137 | return fp.read(2) == '#!'
138 | except (OSError, IOError):
139 | logger.warning('Failed to open %s', executable)
140 | return False
141 |
142 | def _fix_jython_executable(self, executable):
143 | if self._is_shell(executable):
144 | # Workaround for Jython is not needed on Linux systems.
145 | import java
146 |
147 | if java.lang.System.getProperty('os.name') == 'Linux':
148 | return executable
149 | elif executable.lower().endswith('jython.exe'):
150 | # Use wrapper exe for Jython on Windows
151 | return executable
152 | return '/usr/bin/env %s' % executable
153 |
154 | def _build_shebang(self, executable, post_interp):
155 | """
156 | Build a shebang line. In the simple case (on Windows, or a shebang line
157 | which is not too long or contains spaces) use a simple formulation for
158 | the shebang. Otherwise, use /bin/sh as the executable, with a contrived
159 | shebang which allows the script to run either under Python or sh, using
160 | suitable quoting. Thanks to Harald Nordgren for his input.
161 |
162 | See also: http://www.in-ulm.de/~mascheck/various/shebang/#length
163 | https://hg.mozilla.org/mozilla-central/file/tip/mach
164 | """
165 | if os.name != 'posix':
166 | simple_shebang = True
167 | else:
168 | # Add 3 for '#!' prefix and newline suffix.
169 | shebang_length = len(executable) + len(post_interp) + 3
170 | if sys.platform == 'darwin':
171 | max_shebang_length = 512
172 | else:
173 | max_shebang_length = 127
174 | simple_shebang = ((b' ' not in executable)
175 | and (shebang_length <= max_shebang_length))
176 |
177 | if simple_shebang:
178 | result = b'#!' + executable + post_interp + b'\n'
179 | else:
180 | result = b'#!/bin/sh\n'
181 | result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n'
182 | result += b"' '''"
183 | return result
184 |
185 | def _get_shebang(self, encoding, post_interp=b'', options=None):
186 | enquote = True
187 | if self.executable:
188 | executable = self.executable
189 | enquote = False # assume this will be taken care of
190 | elif not sysconfig.is_python_build():
191 | executable = get_executable()
192 | elif in_venv(): # pragma: no cover
193 | executable = os.path.join(
194 | sysconfig.get_path('scripts'),
195 | 'python%s' % sysconfig.get_config_var('EXE'))
196 | else: # pragma: no cover
197 | if os.name == 'nt':
198 | # for Python builds from source on Windows, no Python executables with
199 | # a version suffix are created, so we use python.exe
200 | executable = os.path.join(
201 | sysconfig.get_config_var('BINDIR'),
202 | 'python%s' % (sysconfig.get_config_var('EXE')))
203 | else:
204 | executable = os.path.join(
205 | sysconfig.get_config_var('BINDIR'),
206 | 'python%s%s' % (sysconfig.get_config_var('VERSION'),
207 | sysconfig.get_config_var('EXE')))
208 | if options:
209 | executable = self._get_alternate_executable(executable, options)
210 |
211 | if sys.platform.startswith('java'): # pragma: no cover
212 | executable = self._fix_jython_executable(executable)
213 |
214 | # Normalise case for Windows - COMMENTED OUT
215 | # executable = os.path.normcase(executable)
216 | # N.B. The normalising operation above has been commented out: See
217 | # issue #124. Although paths in Windows are generally case-insensitive,
218 | # they aren't always. For example, a path containing a ẞ (which is a
219 | # LATIN CAPITAL LETTER SHARP S - U+1E9E) is normcased to ß (which is a
220 | # LATIN SMALL LETTER SHARP S' - U+00DF). The two are not considered by
221 | # Windows as equivalent in path names.
222 |
223 | # If the user didn't specify an executable, it may be necessary to
224 | # cater for executable paths with spaces (not uncommon on Windows)
225 | if enquote:
226 | executable = enquote_executable(executable)
227 | # Issue #51: don't use fsencode, since we later try to
228 | # check that the shebang is decodable using utf-8.
229 | executable = executable.encode('utf-8')
230 | # in case of IronPython, play safe and enable frames support
231 | if (sys.platform == 'cli' and '-X:Frames' not in post_interp
232 | and '-X:FullFrames' not in post_interp): # pragma: no cover
233 | post_interp += b' -X:Frames'
234 | shebang = self._build_shebang(executable, post_interp)
235 | # Python parser starts to read a script using UTF-8 until
236 | # it gets a #coding:xxx cookie. The shebang has to be the
237 | # first line of a file, the #coding:xxx cookie cannot be
238 | # written before. So the shebang has to be decodable from
239 | # UTF-8.
240 | try:
241 | shebang.decode('utf-8')
242 | except UnicodeDecodeError: # pragma: no cover
243 | raise ValueError('The shebang (%r) is not decodable from utf-8' %
244 | shebang)
245 | # If the script is encoded to a custom encoding (use a
246 | # #coding:xxx cookie), the shebang has to be decodable from
247 | # the script encoding too.
248 | if encoding != 'utf-8':
249 | try:
250 | shebang.decode(encoding)
251 | except UnicodeDecodeError: # pragma: no cover
252 | raise ValueError('The shebang (%r) is not decodable '
253 | 'from the script encoding (%r)' %
254 | (shebang, encoding))
255 | return shebang
256 |
257 | def _get_script_text(self, entry):
258 | return self.script_template % dict(
259 | module=entry.prefix,
260 | import_name=entry.suffix.split('.')[0],
261 | func=entry.suffix)
262 |
263 | manifest = _DEFAULT_MANIFEST
264 |
265 | def get_manifest(self, exename):
266 | base = os.path.basename(exename)
267 | return self.manifest % base
268 |
269 | def _write_script(self, names, shebang, script_bytes, filenames, ext):
270 | use_launcher = self.add_launchers and self._is_nt
271 | linesep = os.linesep.encode('utf-8')
272 | if not shebang.endswith(linesep):
273 | shebang += linesep
274 | if not use_launcher:
275 | script_bytes = shebang + script_bytes
276 | else: # pragma: no cover
277 | if ext == 'py':
278 | launcher = self._get_launcher('t')
279 | else:
280 | launcher = self._get_launcher('w')
281 | stream = BytesIO()
282 | with ZipFile(stream, 'w') as zf:
283 | source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH')
284 | if source_date_epoch:
285 | date_time = time.gmtime(int(source_date_epoch))[:6]
286 | zinfo = ZipInfo(filename='__main__.py',
287 | date_time=date_time)
288 | zf.writestr(zinfo, script_bytes)
289 | else:
290 | zf.writestr('__main__.py', script_bytes)
291 | zip_data = stream.getvalue()
292 | script_bytes = launcher + shebang + zip_data
293 | for name in names:
294 | outname = os.path.join(self.target_dir, name)
295 | if use_launcher: # pragma: no cover
296 | n, e = os.path.splitext(outname)
297 | if e.startswith('.py'):
298 | outname = n
299 | outname = '%s.exe' % outname
300 | try:
301 | self._fileop.write_binary_file(outname, script_bytes)
302 | except Exception:
303 | # Failed writing an executable - it might be in use.
304 | logger.warning('Failed to write executable - trying to '
305 | 'use .deleteme logic')
306 | dfname = '%s.deleteme' % outname
307 | if os.path.exists(dfname):
308 | os.remove(dfname) # Not allowed to fail here
309 | os.rename(outname, dfname) # nor here
310 | self._fileop.write_binary_file(outname, script_bytes)
311 | logger.debug('Able to replace executable using '
312 | '.deleteme logic')
313 | try:
314 | os.remove(dfname)
315 | except Exception:
316 | pass # still in use - ignore error
317 | else:
318 | if self._is_nt and not outname.endswith(
319 | '.' + ext): # pragma: no cover
320 | outname = '%s.%s' % (outname, ext)
321 | if os.path.exists(outname) and not self.clobber:
322 | logger.warning('Skipping existing file %s', outname)
323 | continue
324 | self._fileop.write_binary_file(outname, script_bytes)
325 | if self.set_mode:
326 | self._fileop.set_executable_mode([outname])
327 | filenames.append(outname)
328 |
329 | variant_separator = '-'
330 |
331 | def get_script_filenames(self, name):
332 | result = set()
333 | if '' in self.variants:
334 | result.add(name)
335 | if 'X' in self.variants:
336 | result.add('%s%s' % (name, self.version_info[0]))
337 | if 'X.Y' in self.variants:
338 | result.add('%s%s%s.%s' %
339 | (name, self.variant_separator, self.version_info[0],
340 | self.version_info[1]))
341 | return result
342 |
343 | def _make_script(self, entry, filenames, options=None):
344 | post_interp = b''
345 | if options:
346 | args = options.get('interpreter_args', [])
347 | if args:
348 | args = ' %s' % ' '.join(args)
349 | post_interp = args.encode('utf-8')
350 | shebang = self._get_shebang('utf-8', post_interp, options=options)
351 | script = self._get_script_text(entry).encode('utf-8')
352 | scriptnames = self.get_script_filenames(entry.name)
353 | if options and options.get('gui', False):
354 | ext = 'pyw'
355 | else:
356 | ext = 'py'
357 | self._write_script(scriptnames, shebang, script, filenames, ext)
358 |
359 | def _copy_script(self, script, filenames):
360 | adjust = False
361 | script = os.path.join(self.source_dir, convert_path(script))
362 | outname = os.path.join(self.target_dir, os.path.basename(script))
363 | if not self.force and not self._fileop.newer(script, outname):
364 | logger.debug('not copying %s (up-to-date)', script)
365 | return
366 |
367 | # Always open the file, but ignore failures in dry-run mode --
368 | # that way, we'll get accurate feedback if we can read the
369 | # script.
370 | try:
371 | f = open(script, 'rb')
372 | except IOError: # pragma: no cover
373 | if not self.dry_run:
374 | raise
375 | f = None
376 | else:
377 | first_line = f.readline()
378 | if not first_line: # pragma: no cover
379 | logger.warning('%s is an empty file (skipping)', script)
380 | return
381 |
382 | match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n'))
383 | if match:
384 | adjust = True
385 | post_interp = match.group(1) or b''
386 |
387 | if not adjust:
388 | if f:
389 | f.close()
390 | self._fileop.copy_file(script, outname)
391 | if self.set_mode:
392 | self._fileop.set_executable_mode([outname])
393 | filenames.append(outname)
394 | else:
395 | logger.info('copying and adjusting %s -> %s', script,
396 | self.target_dir)
397 | if not self._fileop.dry_run:
398 | encoding, lines = detect_encoding(f.readline)
399 | f.seek(0)
400 | shebang = self._get_shebang(encoding, post_interp)
401 | if b'pythonw' in first_line: # pragma: no cover
402 | ext = 'pyw'
403 | else:
404 | ext = 'py'
405 | n = os.path.basename(outname)
406 | self._write_script([n], shebang, f.read(), filenames, ext)
407 | if f:
408 | f.close()
409 |
410 | @property
411 | def dry_run(self):
412 | return self._fileop.dry_run
413 |
414 | @dry_run.setter
415 | def dry_run(self, value):
416 | self._fileop.dry_run = value
417 |
418 | if os.name == 'nt' or (os.name == 'java'
419 | and os._name == 'nt'): # pragma: no cover
420 | # Executable launcher support.
421 | # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/
422 |
423 | def _get_launcher(self, kind):
424 | if struct.calcsize('P') == 8: # 64-bit
425 | bits = '64'
426 | else:
427 | bits = '32'
428 | platform_suffix = '-arm' if get_platform() == 'win-arm64' else ''
429 | name = '%s%s%s.exe' % (kind, bits, platform_suffix)
430 | if name not in WRAPPERS:
431 | msg = ('Unable to find resource %s in package %s' %
432 | (name, distlib_package))
433 | raise ValueError(msg)
434 | return WRAPPERS[name]
435 |
436 | # Public API follows
437 |
438 | def make(self, specification, options=None):
439 | """
440 | Make a script.
441 |
442 | :param specification: The specification, which is either a valid export
443 | entry specification (to make a script from a
444 | callable) or a filename (to make a script by
445 | copying from a source location).
446 | :param options: A dictionary of options controlling script generation.
447 | :return: A list of all absolute pathnames written to.
448 | """
449 | filenames = []
450 | entry = get_export_entry(specification)
451 | if entry is None:
452 | self._copy_script(specification, filenames)
453 | else:
454 | self._make_script(entry, filenames, options=options)
455 | return filenames
456 |
457 | def make_multiple(self, specifications, options=None):
458 | """
459 | Take a list of specifications and make scripts from them,
460 | :param specifications: A list of specifications.
461 | :return: A list of all absolute pathnames written to,
462 | """
463 | filenames = []
464 | for specification in specifications:
465 | filenames.extend(self.make(specification, options))
466 | return filenames
467 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py:
--------------------------------------------------------------------------------
```python
1 | # This file is dual licensed under the terms of the Apache License, Version
2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 | # for complete details.
4 |
5 | from __future__ import annotations
6 |
7 | import logging
8 | import platform
9 | import re
10 | import struct
11 | import subprocess
12 | import sys
13 | import sysconfig
14 | from importlib.machinery import EXTENSION_SUFFIXES
15 | from typing import (
16 | Iterable,
17 | Iterator,
18 | Sequence,
19 | Tuple,
20 | cast,
21 | )
22 |
23 | from . import _manylinux, _musllinux
24 |
25 | logger = logging.getLogger(__name__)
26 |
27 | PythonVersion = Sequence[int]
28 | MacVersion = Tuple[int, int]
29 |
30 | INTERPRETER_SHORT_NAMES: dict[str, str] = {
31 | "python": "py", # Generic.
32 | "cpython": "cp",
33 | "pypy": "pp",
34 | "ironpython": "ip",
35 | "jython": "jy",
36 | }
37 |
38 |
39 | _32_BIT_INTERPRETER = struct.calcsize("P") == 4
40 |
41 |
42 | class Tag:
43 | """
44 | A representation of the tag triple for a wheel.
45 |
46 | Instances are considered immutable and thus are hashable. Equality checking
47 | is also supported.
48 | """
49 |
50 | __slots__ = ["_interpreter", "_abi", "_platform", "_hash"]
51 |
52 | def __init__(self, interpreter: str, abi: str, platform: str) -> None:
53 | self._interpreter = interpreter.lower()
54 | self._abi = abi.lower()
55 | self._platform = platform.lower()
56 | # The __hash__ of every single element in a Set[Tag] will be evaluated each time
57 | # that a set calls its `.disjoint()` method, which may be called hundreds of
58 | # times when scanning a page of links for packages with tags matching that
59 | # Set[Tag]. Pre-computing the value here produces significant speedups for
60 | # downstream consumers.
61 | self._hash = hash((self._interpreter, self._abi, self._platform))
62 |
63 | @property
64 | def interpreter(self) -> str:
65 | return self._interpreter
66 |
67 | @property
68 | def abi(self) -> str:
69 | return self._abi
70 |
71 | @property
72 | def platform(self) -> str:
73 | return self._platform
74 |
75 | def __eq__(self, other: object) -> bool:
76 | if not isinstance(other, Tag):
77 | return NotImplemented
78 |
79 | return (
80 | (self._hash == other._hash) # Short-circuit ASAP for perf reasons.
81 | and (self._platform == other._platform)
82 | and (self._abi == other._abi)
83 | and (self._interpreter == other._interpreter)
84 | )
85 |
86 | def __hash__(self) -> int:
87 | return self._hash
88 |
89 | def __str__(self) -> str:
90 | return f"{self._interpreter}-{self._abi}-{self._platform}"
91 |
92 | def __repr__(self) -> str:
93 | return f"<{self} @ {id(self)}>"
94 |
95 |
96 | def parse_tag(tag: str) -> frozenset[Tag]:
97 | """
98 | Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances.
99 |
100 | Returning a set is required due to the possibility that the tag is a
101 | compressed tag set.
102 | """
103 | tags = set()
104 | interpreters, abis, platforms = tag.split("-")
105 | for interpreter in interpreters.split("."):
106 | for abi in abis.split("."):
107 | for platform_ in platforms.split("."):
108 | tags.add(Tag(interpreter, abi, platform_))
109 | return frozenset(tags)
110 |
111 |
112 | def _get_config_var(name: str, warn: bool = False) -> int | str | None:
113 | value: int | str | None = sysconfig.get_config_var(name)
114 | if value is None and warn:
115 | logger.debug(
116 | "Config variable '%s' is unset, Python ABI tag may be incorrect", name
117 | )
118 | return value
119 |
120 |
121 | def _normalize_string(string: str) -> str:
122 | return string.replace(".", "_").replace("-", "_").replace(" ", "_")
123 |
124 |
125 | def _is_threaded_cpython(abis: list[str]) -> bool:
126 | """
127 | Determine if the ABI corresponds to a threaded (`--disable-gil`) build.
128 |
129 | The threaded builds are indicated by a "t" in the abiflags.
130 | """
131 | if len(abis) == 0:
132 | return False
133 | # expect e.g., cp313
134 | m = re.match(r"cp\d+(.*)", abis[0])
135 | if not m:
136 | return False
137 | abiflags = m.group(1)
138 | return "t" in abiflags
139 |
140 |
141 | def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool:
142 | """
143 | Determine if the Python version supports abi3.
144 |
145 | PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`)
146 | builds do not support abi3.
147 | """
148 | return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading
149 |
150 |
151 | def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]:
152 | py_version = tuple(py_version) # To allow for version comparison.
153 | abis = []
154 | version = _version_nodot(py_version[:2])
155 | threading = debug = pymalloc = ucs4 = ""
156 | with_debug = _get_config_var("Py_DEBUG", warn)
157 | has_refcount = hasattr(sys, "gettotalrefcount")
158 | # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
159 | # extension modules is the best option.
160 | # https://github.com/pypa/pip/issues/3383#issuecomment-173267692
161 | has_ext = "_d.pyd" in EXTENSION_SUFFIXES
162 | if with_debug or (with_debug is None and (has_refcount or has_ext)):
163 | debug = "d"
164 | if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn):
165 | threading = "t"
166 | if py_version < (3, 8):
167 | with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
168 | if with_pymalloc or with_pymalloc is None:
169 | pymalloc = "m"
170 | if py_version < (3, 3):
171 | unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
172 | if unicode_size == 4 or (
173 | unicode_size is None and sys.maxunicode == 0x10FFFF
174 | ):
175 | ucs4 = "u"
176 | elif debug:
177 | # Debug builds can also load "normal" extension modules.
178 | # We can also assume no UCS-4 or pymalloc requirement.
179 | abis.append(f"cp{version}{threading}")
180 | abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}")
181 | return abis
182 |
183 |
184 | def cpython_tags(
185 | python_version: PythonVersion | None = None,
186 | abis: Iterable[str] | None = None,
187 | platforms: Iterable[str] | None = None,
188 | *,
189 | warn: bool = False,
190 | ) -> Iterator[Tag]:
191 | """
192 | Yields the tags for a CPython interpreter.
193 |
194 | The tags consist of:
195 | - cp<python_version>-<abi>-<platform>
196 | - cp<python_version>-abi3-<platform>
197 | - cp<python_version>-none-<platform>
198 | - cp<less than python_version>-abi3-<platform> # Older Python versions down to 3.2.
199 |
200 | If python_version only specifies a major version then user-provided ABIs and
201 | the 'none' ABItag will be used.
202 |
203 | If 'abi3' or 'none' are specified in 'abis' then they will be yielded at
204 | their normal position and not at the beginning.
205 | """
206 | if not python_version:
207 | python_version = sys.version_info[:2]
208 |
209 | interpreter = f"cp{_version_nodot(python_version[:2])}"
210 |
211 | if abis is None:
212 | if len(python_version) > 1:
213 | abis = _cpython_abis(python_version, warn)
214 | else:
215 | abis = []
216 | abis = list(abis)
217 | # 'abi3' and 'none' are explicitly handled later.
218 | for explicit_abi in ("abi3", "none"):
219 | try:
220 | abis.remove(explicit_abi)
221 | except ValueError:
222 | pass
223 |
224 | platforms = list(platforms or platform_tags())
225 | for abi in abis:
226 | for platform_ in platforms:
227 | yield Tag(interpreter, abi, platform_)
228 |
229 | threading = _is_threaded_cpython(abis)
230 | use_abi3 = _abi3_applies(python_version, threading)
231 | if use_abi3:
232 | yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms)
233 | yield from (Tag(interpreter, "none", platform_) for platform_ in platforms)
234 |
235 | if use_abi3:
236 | for minor_version in range(python_version[1] - 1, 1, -1):
237 | for platform_ in platforms:
238 | interpreter = "cp{version}".format(
239 | version=_version_nodot((python_version[0], minor_version))
240 | )
241 | yield Tag(interpreter, "abi3", platform_)
242 |
243 |
244 | def _generic_abi() -> list[str]:
245 | """
246 | Return the ABI tag based on EXT_SUFFIX.
247 | """
248 | # The following are examples of `EXT_SUFFIX`.
249 | # We want to keep the parts which are related to the ABI and remove the
250 | # parts which are related to the platform:
251 | # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310
252 | # - mac: '.cpython-310-darwin.so' => cp310
253 | # - win: '.cp310-win_amd64.pyd' => cp310
254 | # - win: '.pyd' => cp37 (uses _cpython_abis())
255 | # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73
256 | # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib'
257 | # => graalpy_38_native
258 |
259 | ext_suffix = _get_config_var("EXT_SUFFIX", warn=True)
260 | if not isinstance(ext_suffix, str) or ext_suffix[0] != ".":
261 | raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')")
262 | parts = ext_suffix.split(".")
263 | if len(parts) < 3:
264 | # CPython3.7 and earlier uses ".pyd" on Windows.
265 | return _cpython_abis(sys.version_info[:2])
266 | soabi = parts[1]
267 | if soabi.startswith("cpython"):
268 | # non-windows
269 | abi = "cp" + soabi.split("-")[1]
270 | elif soabi.startswith("cp"):
271 | # windows
272 | abi = soabi.split("-")[0]
273 | elif soabi.startswith("pypy"):
274 | abi = "-".join(soabi.split("-")[:2])
275 | elif soabi.startswith("graalpy"):
276 | abi = "-".join(soabi.split("-")[:3])
277 | elif soabi:
278 | # pyston, ironpython, others?
279 | abi = soabi
280 | else:
281 | return []
282 | return [_normalize_string(abi)]
283 |
284 |
285 | def generic_tags(
286 | interpreter: str | None = None,
287 | abis: Iterable[str] | None = None,
288 | platforms: Iterable[str] | None = None,
289 | *,
290 | warn: bool = False,
291 | ) -> Iterator[Tag]:
292 | """
293 | Yields the tags for a generic interpreter.
294 |
295 | The tags consist of:
296 | - <interpreter>-<abi>-<platform>
297 |
298 | The "none" ABI will be added if it was not explicitly provided.
299 | """
300 | if not interpreter:
301 | interp_name = interpreter_name()
302 | interp_version = interpreter_version(warn=warn)
303 | interpreter = "".join([interp_name, interp_version])
304 | if abis is None:
305 | abis = _generic_abi()
306 | else:
307 | abis = list(abis)
308 | platforms = list(platforms or platform_tags())
309 | if "none" not in abis:
310 | abis.append("none")
311 | for abi in abis:
312 | for platform_ in platforms:
313 | yield Tag(interpreter, abi, platform_)
314 |
315 |
316 | def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]:
317 | """
318 | Yields Python versions in descending order.
319 |
320 | After the latest version, the major-only version will be yielded, and then
321 | all previous versions of that major version.
322 | """
323 | if len(py_version) > 1:
324 | yield f"py{_version_nodot(py_version[:2])}"
325 | yield f"py{py_version[0]}"
326 | if len(py_version) > 1:
327 | for minor in range(py_version[1] - 1, -1, -1):
328 | yield f"py{_version_nodot((py_version[0], minor))}"
329 |
330 |
331 | def compatible_tags(
332 | python_version: PythonVersion | None = None,
333 | interpreter: str | None = None,
334 | platforms: Iterable[str] | None = None,
335 | ) -> Iterator[Tag]:
336 | """
337 | Yields the sequence of tags that are compatible with a specific version of Python.
338 |
339 | The tags consist of:
340 | - py*-none-<platform>
341 | - <interpreter>-none-any # ... if `interpreter` is provided.
342 | - py*-none-any
343 | """
344 | if not python_version:
345 | python_version = sys.version_info[:2]
346 | platforms = list(platforms or platform_tags())
347 | for version in _py_interpreter_range(python_version):
348 | for platform_ in platforms:
349 | yield Tag(version, "none", platform_)
350 | if interpreter:
351 | yield Tag(interpreter, "none", "any")
352 | for version in _py_interpreter_range(python_version):
353 | yield Tag(version, "none", "any")
354 |
355 |
356 | def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
357 | if not is_32bit:
358 | return arch
359 |
360 | if arch.startswith("ppc"):
361 | return "ppc"
362 |
363 | return "i386"
364 |
365 |
366 | def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
367 | formats = [cpu_arch]
368 | if cpu_arch == "x86_64":
369 | if version < (10, 4):
370 | return []
371 | formats.extend(["intel", "fat64", "fat32"])
372 |
373 | elif cpu_arch == "i386":
374 | if version < (10, 4):
375 | return []
376 | formats.extend(["intel", "fat32", "fat"])
377 |
378 | elif cpu_arch == "ppc64":
379 | # TODO: Need to care about 32-bit PPC for ppc64 through 10.2?
380 | if version > (10, 5) or version < (10, 4):
381 | return []
382 | formats.append("fat64")
383 |
384 | elif cpu_arch == "ppc":
385 | if version > (10, 6):
386 | return []
387 | formats.extend(["fat32", "fat"])
388 |
389 | if cpu_arch in {"arm64", "x86_64"}:
390 | formats.append("universal2")
391 |
392 | if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}:
393 | formats.append("universal")
394 |
395 | return formats
396 |
397 |
398 | def mac_platforms(
399 | version: MacVersion | None = None, arch: str | None = None
400 | ) -> Iterator[str]:
401 | """
402 | Yields the platform tags for a macOS system.
403 |
404 | The `version` parameter is a two-item tuple specifying the macOS version to
405 | generate platform tags for. The `arch` parameter is the CPU architecture to
406 | generate platform tags for. Both parameters default to the appropriate value
407 | for the current system.
408 | """
409 | version_str, _, cpu_arch = platform.mac_ver()
410 | if version is None:
411 | version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
412 | if version == (10, 16):
413 | # When built against an older macOS SDK, Python will report macOS 10.16
414 | # instead of the real version.
415 | version_str = subprocess.run(
416 | [
417 | sys.executable,
418 | "-sS",
419 | "-c",
420 | "import platform; print(platform.mac_ver()[0])",
421 | ],
422 | check=True,
423 | env={"SYSTEM_VERSION_COMPAT": "0"},
424 | stdout=subprocess.PIPE,
425 | text=True,
426 | ).stdout
427 | version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
428 | else:
429 | version = version
430 | if arch is None:
431 | arch = _mac_arch(cpu_arch)
432 | else:
433 | arch = arch
434 |
435 | if (10, 0) <= version and version < (11, 0):
436 | # Prior to Mac OS 11, each yearly release of Mac OS bumped the
437 | # "minor" version number. The major version was always 10.
438 | for minor_version in range(version[1], -1, -1):
439 | compat_version = 10, minor_version
440 | binary_formats = _mac_binary_formats(compat_version, arch)
441 | for binary_format in binary_formats:
442 | yield "macosx_{major}_{minor}_{binary_format}".format(
443 | major=10, minor=minor_version, binary_format=binary_format
444 | )
445 |
446 | if version >= (11, 0):
447 | # Starting with Mac OS 11, each yearly release bumps the major version
448 | # number. The minor versions are now the midyear updates.
449 | for major_version in range(version[0], 10, -1):
450 | compat_version = major_version, 0
451 | binary_formats = _mac_binary_formats(compat_version, arch)
452 | for binary_format in binary_formats:
453 | yield "macosx_{major}_{minor}_{binary_format}".format(
454 | major=major_version, minor=0, binary_format=binary_format
455 | )
456 |
457 | if version >= (11, 0):
458 | # Mac OS 11 on x86_64 is compatible with binaries from previous releases.
459 | # Arm64 support was introduced in 11.0, so no Arm binaries from previous
460 | # releases exist.
461 | #
462 | # However, the "universal2" binary format can have a
463 | # macOS version earlier than 11.0 when the x86_64 part of the binary supports
464 | # that version of macOS.
465 | if arch == "x86_64":
466 | for minor_version in range(16, 3, -1):
467 | compat_version = 10, minor_version
468 | binary_formats = _mac_binary_formats(compat_version, arch)
469 | for binary_format in binary_formats:
470 | yield "macosx_{major}_{minor}_{binary_format}".format(
471 | major=compat_version[0],
472 | minor=compat_version[1],
473 | binary_format=binary_format,
474 | )
475 | else:
476 | for minor_version in range(16, 3, -1):
477 | compat_version = 10, minor_version
478 | binary_format = "universal2"
479 | yield "macosx_{major}_{minor}_{binary_format}".format(
480 | major=compat_version[0],
481 | minor=compat_version[1],
482 | binary_format=binary_format,
483 | )
484 |
485 |
486 | def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
487 | linux = _normalize_string(sysconfig.get_platform())
488 | if not linux.startswith("linux_"):
489 | # we should never be here, just yield the sysconfig one and return
490 | yield linux
491 | return
492 | if is_32bit:
493 | if linux == "linux_x86_64":
494 | linux = "linux_i686"
495 | elif linux == "linux_aarch64":
496 | linux = "linux_armv8l"
497 | _, arch = linux.split("_", 1)
498 | archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch])
499 | yield from _manylinux.platform_tags(archs)
500 | yield from _musllinux.platform_tags(archs)
501 | for arch in archs:
502 | yield f"linux_{arch}"
503 |
504 |
505 | def _generic_platforms() -> Iterator[str]:
506 | yield _normalize_string(sysconfig.get_platform())
507 |
508 |
509 | def platform_tags() -> Iterator[str]:
510 | """
511 | Provides the platform tags for this installation.
512 | """
513 | if platform.system() == "Darwin":
514 | return mac_platforms()
515 | elif platform.system() == "Linux":
516 | return _linux_platforms()
517 | else:
518 | return _generic_platforms()
519 |
520 |
521 | def interpreter_name() -> str:
522 | """
523 | Returns the name of the running interpreter.
524 |
525 | Some implementations have a reserved, two-letter abbreviation which will
526 | be returned when appropriate.
527 | """
528 | name = sys.implementation.name
529 | return INTERPRETER_SHORT_NAMES.get(name) or name
530 |
531 |
532 | def interpreter_version(*, warn: bool = False) -> str:
533 | """
534 | Returns the version of the running interpreter.
535 | """
536 | version = _get_config_var("py_version_nodot", warn=warn)
537 | if version:
538 | version = str(version)
539 | else:
540 | version = _version_nodot(sys.version_info[:2])
541 | return version
542 |
543 |
544 | def _version_nodot(version: PythonVersion) -> str:
545 | return "".join(map(str, version))
546 |
547 |
548 | def sys_tags(*, warn: bool = False) -> Iterator[Tag]:
549 | """
550 | Returns the sequence of tag triples for the running interpreter.
551 |
552 | The order of the sequence corresponds to priority order for the
553 | interpreter, from most to least important.
554 | """
555 |
556 | interp_name = interpreter_name()
557 | if interp_name == "cp":
558 | yield from cpython_tags(warn=warn)
559 | else:
560 | yield from generic_tags()
561 |
562 | if interp_name == "pp":
563 | interp = "pp3"
564 | elif interp_name == "cp":
565 | interp = "cp" + interpreter_version(warn=warn)
566 | else:
567 | interp = None
568 | yield from compatible_tags(interpreter=interp)
569 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/click/parser.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | This module started out as largely a copy paste from the stdlib's
3 | optparse module with the features removed that we do not need from
4 | optparse because we implement them in Click on a higher level (for
5 | instance type handling, help formatting and a lot more).
6 |
7 | The plan is to remove more and more from here over time.
8 |
9 | The reason this is a different module and not optparse from the stdlib
10 | is that there are differences in 2.x and 3.x about the error messages
11 | generated and optparse in the stdlib uses gettext for no good reason
12 | and might cause us issues.
13 |
14 | Click uses parts of optparse written by Gregory P. Ward and maintained
15 | by the Python Software Foundation. This is limited to code in parser.py.
16 |
17 | Copyright 2001-2006 Gregory P. Ward. All rights reserved.
18 | Copyright 2002-2006 Python Software Foundation. All rights reserved.
19 | """
20 | # This code uses parts of optparse written by Gregory P. Ward and
21 | # maintained by the Python Software Foundation.
22 | # Copyright 2001-2006 Gregory P. Ward
23 | # Copyright 2002-2006 Python Software Foundation
24 | import typing as t
25 | from collections import deque
26 | from gettext import gettext as _
27 | from gettext import ngettext
28 |
29 | from .exceptions import BadArgumentUsage
30 | from .exceptions import BadOptionUsage
31 | from .exceptions import NoSuchOption
32 | from .exceptions import UsageError
33 |
34 | if t.TYPE_CHECKING:
35 | import typing_extensions as te
36 | from .core import Argument as CoreArgument
37 | from .core import Context
38 | from .core import Option as CoreOption
39 | from .core import Parameter as CoreParameter
40 |
41 | V = t.TypeVar("V")
42 |
43 | # Sentinel value that indicates an option was passed as a flag without a
44 | # value but is not a flag option. Option.consume_value uses this to
45 | # prompt or use the flag_value.
46 | _flag_needs_value = object()
47 |
48 |
49 | def _unpack_args(
50 | args: t.Sequence[str], nargs_spec: t.Sequence[int]
51 | ) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]:
52 | """Given an iterable of arguments and an iterable of nargs specifications,
53 | it returns a tuple with all the unpacked arguments at the first index
54 | and all remaining arguments as the second.
55 |
56 | The nargs specification is the number of arguments that should be consumed
57 | or `-1` to indicate that this position should eat up all the remainders.
58 |
59 | Missing items are filled with `None`.
60 | """
61 | args = deque(args)
62 | nargs_spec = deque(nargs_spec)
63 | rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = []
64 | spos: t.Optional[int] = None
65 |
66 | def _fetch(c: "te.Deque[V]") -> t.Optional[V]:
67 | try:
68 | if spos is None:
69 | return c.popleft()
70 | else:
71 | return c.pop()
72 | except IndexError:
73 | return None
74 |
75 | while nargs_spec:
76 | nargs = _fetch(nargs_spec)
77 |
78 | if nargs is None:
79 | continue
80 |
81 | if nargs == 1:
82 | rv.append(_fetch(args))
83 | elif nargs > 1:
84 | x = [_fetch(args) for _ in range(nargs)]
85 |
86 | # If we're reversed, we're pulling in the arguments in reverse,
87 | # so we need to turn them around.
88 | if spos is not None:
89 | x.reverse()
90 |
91 | rv.append(tuple(x))
92 | elif nargs < 0:
93 | if spos is not None:
94 | raise TypeError("Cannot have two nargs < 0")
95 |
96 | spos = len(rv)
97 | rv.append(None)
98 |
99 | # spos is the position of the wildcard (star). If it's not `None`,
100 | # we fill it with the remainder.
101 | if spos is not None:
102 | rv[spos] = tuple(args)
103 | args = []
104 | rv[spos + 1 :] = reversed(rv[spos + 1 :])
105 |
106 | return tuple(rv), list(args)
107 |
108 |
109 | def split_opt(opt: str) -> t.Tuple[str, str]:
110 | first = opt[:1]
111 | if first.isalnum():
112 | return "", opt
113 | if opt[1:2] == first:
114 | return opt[:2], opt[2:]
115 | return first, opt[1:]
116 |
117 |
118 | def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str:
119 | if ctx is None or ctx.token_normalize_func is None:
120 | return opt
121 | prefix, opt = split_opt(opt)
122 | return f"{prefix}{ctx.token_normalize_func(opt)}"
123 |
124 |
125 | def split_arg_string(string: str) -> t.List[str]:
126 | """Split an argument string as with :func:`shlex.split`, but don't
127 | fail if the string is incomplete. Ignores a missing closing quote or
128 | incomplete escape sequence and uses the partial token as-is.
129 |
130 | .. code-block:: python
131 |
132 | split_arg_string("example 'my file")
133 | ["example", "my file"]
134 |
135 | split_arg_string("example my\\")
136 | ["example", "my"]
137 |
138 | :param string: String to split.
139 | """
140 | import shlex
141 |
142 | lex = shlex.shlex(string, posix=True)
143 | lex.whitespace_split = True
144 | lex.commenters = ""
145 | out = []
146 |
147 | try:
148 | for token in lex:
149 | out.append(token)
150 | except ValueError:
151 | # Raised when end-of-string is reached in an invalid state. Use
152 | # the partial token as-is. The quote or escape character is in
153 | # lex.state, not lex.token.
154 | out.append(lex.token)
155 |
156 | return out
157 |
158 |
159 | class Option:
160 | def __init__(
161 | self,
162 | obj: "CoreOption",
163 | opts: t.Sequence[str],
164 | dest: t.Optional[str],
165 | action: t.Optional[str] = None,
166 | nargs: int = 1,
167 | const: t.Optional[t.Any] = None,
168 | ):
169 | self._short_opts = []
170 | self._long_opts = []
171 | self.prefixes: t.Set[str] = set()
172 |
173 | for opt in opts:
174 | prefix, value = split_opt(opt)
175 | if not prefix:
176 | raise ValueError(f"Invalid start character for option ({opt})")
177 | self.prefixes.add(prefix[0])
178 | if len(prefix) == 1 and len(value) == 1:
179 | self._short_opts.append(opt)
180 | else:
181 | self._long_opts.append(opt)
182 | self.prefixes.add(prefix)
183 |
184 | if action is None:
185 | action = "store"
186 |
187 | self.dest = dest
188 | self.action = action
189 | self.nargs = nargs
190 | self.const = const
191 | self.obj = obj
192 |
193 | @property
194 | def takes_value(self) -> bool:
195 | return self.action in ("store", "append")
196 |
197 | def process(self, value: t.Any, state: "ParsingState") -> None:
198 | if self.action == "store":
199 | state.opts[self.dest] = value # type: ignore
200 | elif self.action == "store_const":
201 | state.opts[self.dest] = self.const # type: ignore
202 | elif self.action == "append":
203 | state.opts.setdefault(self.dest, []).append(value) # type: ignore
204 | elif self.action == "append_const":
205 | state.opts.setdefault(self.dest, []).append(self.const) # type: ignore
206 | elif self.action == "count":
207 | state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore
208 | else:
209 | raise ValueError(f"unknown action '{self.action}'")
210 | state.order.append(self.obj)
211 |
212 |
213 | class Argument:
214 | def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1):
215 | self.dest = dest
216 | self.nargs = nargs
217 | self.obj = obj
218 |
219 | def process(
220 | self,
221 | value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]],
222 | state: "ParsingState",
223 | ) -> None:
224 | if self.nargs > 1:
225 | assert value is not None
226 | holes = sum(1 for x in value if x is None)
227 | if holes == len(value):
228 | value = None
229 | elif holes != 0:
230 | raise BadArgumentUsage(
231 | _("Argument {name!r} takes {nargs} values.").format(
232 | name=self.dest, nargs=self.nargs
233 | )
234 | )
235 |
236 | if self.nargs == -1 and self.obj.envvar is not None and value == ():
237 | # Replace empty tuple with None so that a value from the
238 | # environment may be tried.
239 | value = None
240 |
241 | state.opts[self.dest] = value # type: ignore
242 | state.order.append(self.obj)
243 |
244 |
245 | class ParsingState:
246 | def __init__(self, rargs: t.List[str]) -> None:
247 | self.opts: t.Dict[str, t.Any] = {}
248 | self.largs: t.List[str] = []
249 | self.rargs = rargs
250 | self.order: t.List["CoreParameter"] = []
251 |
252 |
253 | class OptionParser:
254 | """The option parser is an internal class that is ultimately used to
255 | parse options and arguments. It's modelled after optparse and brings
256 | a similar but vastly simplified API. It should generally not be used
257 | directly as the high level Click classes wrap it for you.
258 |
259 | It's not nearly as extensible as optparse or argparse as it does not
260 | implement features that are implemented on a higher level (such as
261 | types or defaults).
262 |
263 | :param ctx: optionally the :class:`~click.Context` where this parser
264 | should go with.
265 | """
266 |
267 | def __init__(self, ctx: t.Optional["Context"] = None) -> None:
268 | #: The :class:`~click.Context` for this parser. This might be
269 | #: `None` for some advanced use cases.
270 | self.ctx = ctx
271 | #: This controls how the parser deals with interspersed arguments.
272 | #: If this is set to `False`, the parser will stop on the first
273 | #: non-option. Click uses this to implement nested subcommands
274 | #: safely.
275 | self.allow_interspersed_args: bool = True
276 | #: This tells the parser how to deal with unknown options. By
277 | #: default it will error out (which is sensible), but there is a
278 | #: second mode where it will ignore it and continue processing
279 | #: after shifting all the unknown options into the resulting args.
280 | self.ignore_unknown_options: bool = False
281 |
282 | if ctx is not None:
283 | self.allow_interspersed_args = ctx.allow_interspersed_args
284 | self.ignore_unknown_options = ctx.ignore_unknown_options
285 |
286 | self._short_opt: t.Dict[str, Option] = {}
287 | self._long_opt: t.Dict[str, Option] = {}
288 | self._opt_prefixes = {"-", "--"}
289 | self._args: t.List[Argument] = []
290 |
291 | def add_option(
292 | self,
293 | obj: "CoreOption",
294 | opts: t.Sequence[str],
295 | dest: t.Optional[str],
296 | action: t.Optional[str] = None,
297 | nargs: int = 1,
298 | const: t.Optional[t.Any] = None,
299 | ) -> None:
300 | """Adds a new option named `dest` to the parser. The destination
301 | is not inferred (unlike with optparse) and needs to be explicitly
302 | provided. Action can be any of ``store``, ``store_const``,
303 | ``append``, ``append_const`` or ``count``.
304 |
305 | The `obj` can be used to identify the option in the order list
306 | that is returned from the parser.
307 | """
308 | opts = [normalize_opt(opt, self.ctx) for opt in opts]
309 | option = Option(obj, opts, dest, action=action, nargs=nargs, const=const)
310 | self._opt_prefixes.update(option.prefixes)
311 | for opt in option._short_opts:
312 | self._short_opt[opt] = option
313 | for opt in option._long_opts:
314 | self._long_opt[opt] = option
315 |
316 | def add_argument(
317 | self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1
318 | ) -> None:
319 | """Adds a positional argument named `dest` to the parser.
320 |
321 | The `obj` can be used to identify the option in the order list
322 | that is returned from the parser.
323 | """
324 | self._args.append(Argument(obj, dest=dest, nargs=nargs))
325 |
326 | def parse_args(
327 | self, args: t.List[str]
328 | ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]:
329 | """Parses positional arguments and returns ``(values, args, order)``
330 | for the parsed options and arguments as well as the leftover
331 | arguments if there are any. The order is a list of objects as they
332 | appear on the command line. If arguments appear multiple times they
333 | will be memorized multiple times as well.
334 | """
335 | state = ParsingState(args)
336 | try:
337 | self._process_args_for_options(state)
338 | self._process_args_for_args(state)
339 | except UsageError:
340 | if self.ctx is None or not self.ctx.resilient_parsing:
341 | raise
342 | return state.opts, state.largs, state.order
343 |
344 | def _process_args_for_args(self, state: ParsingState) -> None:
345 | pargs, args = _unpack_args(
346 | state.largs + state.rargs, [x.nargs for x in self._args]
347 | )
348 |
349 | for idx, arg in enumerate(self._args):
350 | arg.process(pargs[idx], state)
351 |
352 | state.largs = args
353 | state.rargs = []
354 |
355 | def _process_args_for_options(self, state: ParsingState) -> None:
356 | while state.rargs:
357 | arg = state.rargs.pop(0)
358 | arglen = len(arg)
359 | # Double dashes always handled explicitly regardless of what
360 | # prefixes are valid.
361 | if arg == "--":
362 | return
363 | elif arg[:1] in self._opt_prefixes and arglen > 1:
364 | self._process_opts(arg, state)
365 | elif self.allow_interspersed_args:
366 | state.largs.append(arg)
367 | else:
368 | state.rargs.insert(0, arg)
369 | return
370 |
371 | # Say this is the original argument list:
372 | # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)]
373 | # ^
374 | # (we are about to process arg(i)).
375 | #
376 | # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of
377 | # [arg0, ..., arg(i-1)] (any options and their arguments will have
378 | # been removed from largs).
379 | #
380 | # The while loop will usually consume 1 or more arguments per pass.
381 | # If it consumes 1 (eg. arg is an option that takes no arguments),
382 | # then after _process_arg() is done the situation is:
383 | #
384 | # largs = subset of [arg0, ..., arg(i)]
385 | # rargs = [arg(i+1), ..., arg(N-1)]
386 | #
387 | # If allow_interspersed_args is false, largs will always be
388 | # *empty* -- still a subset of [arg0, ..., arg(i-1)], but
389 | # not a very interesting subset!
390 |
391 | def _match_long_opt(
392 | self, opt: str, explicit_value: t.Optional[str], state: ParsingState
393 | ) -> None:
394 | if opt not in self._long_opt:
395 | from difflib import get_close_matches
396 |
397 | possibilities = get_close_matches(opt, self._long_opt)
398 | raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx)
399 |
400 | option = self._long_opt[opt]
401 | if option.takes_value:
402 | # At this point it's safe to modify rargs by injecting the
403 | # explicit value, because no exception is raised in this
404 | # branch. This means that the inserted value will be fully
405 | # consumed.
406 | if explicit_value is not None:
407 | state.rargs.insert(0, explicit_value)
408 |
409 | value = self._get_value_from_state(opt, option, state)
410 |
411 | elif explicit_value is not None:
412 | raise BadOptionUsage(
413 | opt, _("Option {name!r} does not take a value.").format(name=opt)
414 | )
415 |
416 | else:
417 | value = None
418 |
419 | option.process(value, state)
420 |
421 | def _match_short_opt(self, arg: str, state: ParsingState) -> None:
422 | stop = False
423 | i = 1
424 | prefix = arg[0]
425 | unknown_options = []
426 |
427 | for ch in arg[1:]:
428 | opt = normalize_opt(f"{prefix}{ch}", self.ctx)
429 | option = self._short_opt.get(opt)
430 | i += 1
431 |
432 | if not option:
433 | if self.ignore_unknown_options:
434 | unknown_options.append(ch)
435 | continue
436 | raise NoSuchOption(opt, ctx=self.ctx)
437 | if option.takes_value:
438 | # Any characters left in arg? Pretend they're the
439 | # next arg, and stop consuming characters of arg.
440 | if i < len(arg):
441 | state.rargs.insert(0, arg[i:])
442 | stop = True
443 |
444 | value = self._get_value_from_state(opt, option, state)
445 |
446 | else:
447 | value = None
448 |
449 | option.process(value, state)
450 |
451 | if stop:
452 | break
453 |
454 | # If we got any unknown options we recombine the string of the
455 | # remaining options and re-attach the prefix, then report that
456 | # to the state as new larg. This way there is basic combinatorics
457 | # that can be achieved while still ignoring unknown arguments.
458 | if self.ignore_unknown_options and unknown_options:
459 | state.largs.append(f"{prefix}{''.join(unknown_options)}")
460 |
461 | def _get_value_from_state(
462 | self, option_name: str, option: Option, state: ParsingState
463 | ) -> t.Any:
464 | nargs = option.nargs
465 |
466 | if len(state.rargs) < nargs:
467 | if option.obj._flag_needs_value:
468 | # Option allows omitting the value.
469 | value = _flag_needs_value
470 | else:
471 | raise BadOptionUsage(
472 | option_name,
473 | ngettext(
474 | "Option {name!r} requires an argument.",
475 | "Option {name!r} requires {nargs} arguments.",
476 | nargs,
477 | ).format(name=option_name, nargs=nargs),
478 | )
479 | elif nargs == 1:
480 | next_rarg = state.rargs[0]
481 |
482 | if (
483 | option.obj._flag_needs_value
484 | and isinstance(next_rarg, str)
485 | and next_rarg[:1] in self._opt_prefixes
486 | and len(next_rarg) > 1
487 | ):
488 | # The next arg looks like the start of an option, don't
489 | # use it as the value if omitting the value is allowed.
490 | value = _flag_needs_value
491 | else:
492 | value = state.rargs.pop(0)
493 | else:
494 | value = tuple(state.rargs[:nargs])
495 | del state.rargs[:nargs]
496 |
497 | return value
498 |
499 | def _process_opts(self, arg: str, state: ParsingState) -> None:
500 | explicit_value = None
501 | # Long option handling happens in two parts. The first part is
502 | # supporting explicitly attached values. In any case, we will try
503 | # to long match the option first.
504 | if "=" in arg:
505 | long_opt, explicit_value = arg.split("=", 1)
506 | else:
507 | long_opt = arg
508 | norm_long_opt = normalize_opt(long_opt, self.ctx)
509 |
510 | # At this point we will match the (assumed) long option through
511 | # the long option matching code. Note that this allows options
512 | # like "-foo" to be matched as long options.
513 | try:
514 | self._match_long_opt(norm_long_opt, explicit_value, state)
515 | except NoSuchOption:
516 | # At this point the long option matching failed, and we need
517 | # to try with short options. However there is a special rule
518 | # which says, that if we have a two character options prefix
519 | # (applies to "--foo" for instance), we do not dispatch to the
520 | # short option code and will instead raise the no option
521 | # error.
522 | if arg[:2] not in self._opt_prefixes:
523 | self._match_short_opt(arg, state)
524 | return
525 |
526 | if not self.ignore_unknown_options:
527 | raise
528 |
529 | state.largs.append(arg)
530 |
```