#
tokens: 47188/50000 3/808 files (page 60/168)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 60 of 168. Use http://codebase.md/romanshablio/mcp_server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .DS_Store
├── .venv
│   ├── __pycache__
│   │   └── hello.cpython-312.pyc
│   ├── bin
│   │   ├── activate
│   │   ├── activate.csh
│   │   ├── activate.fish
│   │   ├── Activate.ps1
│   │   ├── flask
│   │   ├── normalizer
│   │   ├── pip
│   │   ├── pip3
│   │   ├── pip3.12
│   │   ├── python
│   │   ├── python3
│   │   └── python3.12
│   ├── hello.py
│   ├── lib
│   │   └── python3.12
│   │       └── site-packages
│   │           ├── beautifulsoup4-4.12.3.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── licenses
│   │           │   │   ├── AUTHORS
│   │           │   │   └── LICENSE
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   └── WHEEL
│   │           ├── blinker
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _utilities.cpython-312.pyc
│   │           │   │   └── base.cpython-312.pyc
│   │           │   ├── _utilities.py
│   │           │   ├── base.py
│   │           │   └── py.typed
│   │           ├── blinker-1.8.2.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── bs4
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── css.cpython-312.pyc
│   │           │   │   ├── dammit.cpython-312.pyc
│   │           │   │   ├── diagnose.cpython-312.pyc
│   │           │   │   ├── element.cpython-312.pyc
│   │           │   │   └── formatter.cpython-312.pyc
│   │           │   ├── builder
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── _html5lib.cpython-312.pyc
│   │           │   │   │   ├── _htmlparser.cpython-312.pyc
│   │           │   │   │   └── _lxml.cpython-312.pyc
│   │           │   │   ├── _html5lib.py
│   │           │   │   ├── _htmlparser.py
│   │           │   │   └── _lxml.py
│   │           │   ├── css.py
│   │           │   ├── dammit.py
│   │           │   ├── diagnose.py
│   │           │   ├── element.py
│   │           │   ├── formatter.py
│   │           │   └── tests
│   │           │       ├── __init__.py
│   │           │       ├── __pycache__
│   │           │       │   ├── __init__.cpython-312.pyc
│   │           │       │   ├── test_builder_registry.cpython-312.pyc
│   │           │       │   ├── test_builder.cpython-312.pyc
│   │           │       │   ├── test_css.cpython-312.pyc
│   │           │       │   ├── test_dammit.cpython-312.pyc
│   │           │       │   ├── test_docs.cpython-312.pyc
│   │           │       │   ├── test_element.cpython-312.pyc
│   │           │       │   ├── test_formatter.cpython-312.pyc
│   │           │       │   ├── test_fuzz.cpython-312.pyc
│   │           │       │   ├── test_html5lib.cpython-312.pyc
│   │           │       │   ├── test_htmlparser.cpython-312.pyc
│   │           │       │   ├── test_lxml.cpython-312.pyc
│   │           │       │   ├── test_navigablestring.cpython-312.pyc
│   │           │       │   ├── test_pageelement.cpython-312.pyc
│   │           │       │   ├── test_soup.cpython-312.pyc
│   │           │       │   ├── test_tag.cpython-312.pyc
│   │           │       │   └── test_tree.cpython-312.pyc
│   │           │       ├── fuzz
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase
│   │           │       │   ├── clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase
│   │           │       │   ├── crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase
│   │           │       │   └── crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase
│   │           │       ├── test_builder_registry.py
│   │           │       ├── test_builder.py
│   │           │       ├── test_css.py
│   │           │       ├── test_dammit.py
│   │           │       ├── test_docs.py
│   │           │       ├── test_element.py
│   │           │       ├── test_formatter.py
│   │           │       ├── test_fuzz.py
│   │           │       ├── test_html5lib.py
│   │           │       ├── test_htmlparser.py
│   │           │       ├── test_lxml.py
│   │           │       ├── test_navigablestring.py
│   │           │       ├── test_pageelement.py
│   │           │       ├── test_soup.py
│   │           │       ├── test_tag.py
│   │           │       └── test_tree.py
│   │           ├── certifi
│   │           │   ├── __init__.py
│   │           │   ├── __main__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __main__.cpython-312.pyc
│   │           │   │   └── core.cpython-312.pyc
│   │           │   ├── cacert.pem
│   │           │   ├── core.py
│   │           │   └── py.typed
│   │           ├── certifi-2024.8.30.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── charset_normalizer
│   │           │   ├── __init__.py
│   │           │   ├── __main__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __main__.cpython-312.pyc
│   │           │   │   ├── api.cpython-312.pyc
│   │           │   │   ├── cd.cpython-312.pyc
│   │           │   │   ├── constant.cpython-312.pyc
│   │           │   │   ├── legacy.cpython-312.pyc
│   │           │   │   ├── md.cpython-312.pyc
│   │           │   │   ├── models.cpython-312.pyc
│   │           │   │   ├── utils.cpython-312.pyc
│   │           │   │   └── version.cpython-312.pyc
│   │           │   ├── api.py
│   │           │   ├── cd.py
│   │           │   ├── cli
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __main__.py
│   │           │   │   └── __pycache__
│   │           │   │       ├── __init__.cpython-312.pyc
│   │           │   │       └── __main__.cpython-312.pyc
│   │           │   ├── constant.py
│   │           │   ├── legacy.py
│   │           │   ├── md__mypyc.cpython-312-darwin.so
│   │           │   ├── md.cpython-312-darwin.so
│   │           │   ├── md.py
│   │           │   ├── models.py
│   │           │   ├── py.typed
│   │           │   ├── utils.py
│   │           │   └── version.py
│   │           ├── charset_normalizer-3.4.0.dist-info
│   │           │   ├── entry_points.txt
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── click
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _compat.cpython-312.pyc
│   │           │   │   ├── _termui_impl.cpython-312.pyc
│   │           │   │   ├── _textwrap.cpython-312.pyc
│   │           │   │   ├── _winconsole.cpython-312.pyc
│   │           │   │   ├── core.cpython-312.pyc
│   │           │   │   ├── decorators.cpython-312.pyc
│   │           │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   ├── formatting.cpython-312.pyc
│   │           │   │   ├── globals.cpython-312.pyc
│   │           │   │   ├── parser.cpython-312.pyc
│   │           │   │   ├── shell_completion.cpython-312.pyc
│   │           │   │   ├── termui.cpython-312.pyc
│   │           │   │   ├── testing.cpython-312.pyc
│   │           │   │   ├── types.cpython-312.pyc
│   │           │   │   └── utils.cpython-312.pyc
│   │           │   ├── _compat.py
│   │           │   ├── _termui_impl.py
│   │           │   ├── _textwrap.py
│   │           │   ├── _winconsole.py
│   │           │   ├── core.py
│   │           │   ├── decorators.py
│   │           │   ├── exceptions.py
│   │           │   ├── formatting.py
│   │           │   ├── globals.py
│   │           │   ├── parser.py
│   │           │   ├── py.typed
│   │           │   ├── shell_completion.py
│   │           │   ├── termui.py
│   │           │   ├── testing.py
│   │           │   ├── types.py
│   │           │   └── utils.py
│   │           ├── click-8.1.7.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.rst
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── fake_useragent
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── errors.cpython-312.pyc
│   │           │   │   ├── fake.cpython-312.pyc
│   │           │   │   ├── log.cpython-312.pyc
│   │           │   │   ├── settings.cpython-312.pyc
│   │           │   │   └── utils.cpython-312.pyc
│   │           │   ├── data
│   │           │   │   └── browsers.json
│   │           │   ├── errors.py
│   │           │   ├── fake.py
│   │           │   ├── log.py
│   │           │   ├── settings.py
│   │           │   └── utils.py
│   │           ├── fake_useragent-1.5.1.dist-info
│   │           │   ├── AUTHORS
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── flask
│   │           │   ├── __init__.py
│   │           │   ├── __main__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __main__.cpython-312.pyc
│   │           │   │   ├── app.cpython-312.pyc
│   │           │   │   ├── blueprints.cpython-312.pyc
│   │           │   │   ├── cli.cpython-312.pyc
│   │           │   │   ├── config.cpython-312.pyc
│   │           │   │   ├── ctx.cpython-312.pyc
│   │           │   │   ├── debughelpers.cpython-312.pyc
│   │           │   │   ├── globals.cpython-312.pyc
│   │           │   │   ├── helpers.cpython-312.pyc
│   │           │   │   ├── logging.cpython-312.pyc
│   │           │   │   ├── sessions.cpython-312.pyc
│   │           │   │   ├── signals.cpython-312.pyc
│   │           │   │   ├── templating.cpython-312.pyc
│   │           │   │   ├── testing.cpython-312.pyc
│   │           │   │   ├── typing.cpython-312.pyc
│   │           │   │   ├── views.cpython-312.pyc
│   │           │   │   └── wrappers.cpython-312.pyc
│   │           │   ├── app.py
│   │           │   ├── blueprints.py
│   │           │   ├── cli.py
│   │           │   ├── config.py
│   │           │   ├── ctx.py
│   │           │   ├── debughelpers.py
│   │           │   ├── globals.py
│   │           │   ├── helpers.py
│   │           │   ├── json
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── provider.cpython-312.pyc
│   │           │   │   │   └── tag.cpython-312.pyc
│   │           │   │   ├── provider.py
│   │           │   │   └── tag.py
│   │           │   ├── logging.py
│   │           │   ├── py.typed
│   │           │   ├── sansio
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── app.cpython-312.pyc
│   │           │   │   │   ├── blueprints.cpython-312.pyc
│   │           │   │   │   └── scaffold.cpython-312.pyc
│   │           │   │   ├── app.py
│   │           │   │   ├── blueprints.py
│   │           │   │   ├── README.md
│   │           │   │   └── scaffold.py
│   │           │   ├── sessions.py
│   │           │   ├── signals.py
│   │           │   ├── templating.py
│   │           │   ├── testing.py
│   │           │   ├── typing.py
│   │           │   ├── views.py
│   │           │   └── wrappers.py
│   │           ├── flask-3.0.3.dist-info
│   │           │   ├── entry_points.txt
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   └── WHEEL
│   │           ├── idna
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── codec.cpython-312.pyc
│   │           │   │   ├── compat.cpython-312.pyc
│   │           │   │   ├── core.cpython-312.pyc
│   │           │   │   ├── idnadata.cpython-312.pyc
│   │           │   │   ├── intranges.cpython-312.pyc
│   │           │   │   ├── package_data.cpython-312.pyc
│   │           │   │   └── uts46data.cpython-312.pyc
│   │           │   ├── codec.py
│   │           │   ├── compat.py
│   │           │   ├── core.py
│   │           │   ├── idnadata.py
│   │           │   ├── intranges.py
│   │           │   ├── package_data.py
│   │           │   ├── py.typed
│   │           │   └── uts46data.py
│   │           ├── idna-3.10.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.md
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── itsdangerous
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _json.cpython-312.pyc
│   │           │   │   ├── encoding.cpython-312.pyc
│   │           │   │   ├── exc.cpython-312.pyc
│   │           │   │   ├── serializer.cpython-312.pyc
│   │           │   │   ├── signer.cpython-312.pyc
│   │           │   │   ├── timed.cpython-312.pyc
│   │           │   │   └── url_safe.cpython-312.pyc
│   │           │   ├── _json.py
│   │           │   ├── encoding.py
│   │           │   ├── exc.py
│   │           │   ├── py.typed
│   │           │   ├── serializer.py
│   │           │   ├── signer.py
│   │           │   ├── timed.py
│   │           │   └── url_safe.py
│   │           ├── itsdangerous-2.2.0.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── jinja2
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _identifier.cpython-312.pyc
│   │           │   │   ├── async_utils.cpython-312.pyc
│   │           │   │   ├── bccache.cpython-312.pyc
│   │           │   │   ├── compiler.cpython-312.pyc
│   │           │   │   ├── constants.cpython-312.pyc
│   │           │   │   ├── debug.cpython-312.pyc
│   │           │   │   ├── defaults.cpython-312.pyc
│   │           │   │   ├── environment.cpython-312.pyc
│   │           │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   ├── ext.cpython-312.pyc
│   │           │   │   ├── filters.cpython-312.pyc
│   │           │   │   ├── idtracking.cpython-312.pyc
│   │           │   │   ├── lexer.cpython-312.pyc
│   │           │   │   ├── loaders.cpython-312.pyc
│   │           │   │   ├── meta.cpython-312.pyc
│   │           │   │   ├── nativetypes.cpython-312.pyc
│   │           │   │   ├── nodes.cpython-312.pyc
│   │           │   │   ├── optimizer.cpython-312.pyc
│   │           │   │   ├── parser.cpython-312.pyc
│   │           │   │   ├── runtime.cpython-312.pyc
│   │           │   │   ├── sandbox.cpython-312.pyc
│   │           │   │   ├── tests.cpython-312.pyc
│   │           │   │   ├── utils.cpython-312.pyc
│   │           │   │   └── visitor.cpython-312.pyc
│   │           │   ├── _identifier.py
│   │           │   ├── async_utils.py
│   │           │   ├── bccache.py
│   │           │   ├── compiler.py
│   │           │   ├── constants.py
│   │           │   ├── debug.py
│   │           │   ├── defaults.py
│   │           │   ├── environment.py
│   │           │   ├── exceptions.py
│   │           │   ├── ext.py
│   │           │   ├── filters.py
│   │           │   ├── idtracking.py
│   │           │   ├── lexer.py
│   │           │   ├── loaders.py
│   │           │   ├── meta.py
│   │           │   ├── nativetypes.py
│   │           │   ├── nodes.py
│   │           │   ├── optimizer.py
│   │           │   ├── parser.py
│   │           │   ├── py.typed
│   │           │   ├── runtime.py
│   │           │   ├── sandbox.py
│   │           │   ├── tests.py
│   │           │   ├── utils.py
│   │           │   └── visitor.py
│   │           ├── jinja2-3.1.4.dist-info
│   │           │   ├── entry_points.txt
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── lxml
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _elementpath.cpython-312.pyc
│   │           │   │   ├── builder.cpython-312.pyc
│   │           │   │   ├── cssselect.cpython-312.pyc
│   │           │   │   ├── doctestcompare.cpython-312.pyc
│   │           │   │   ├── ElementInclude.cpython-312.pyc
│   │           │   │   ├── pyclasslookup.cpython-312.pyc
│   │           │   │   ├── sax.cpython-312.pyc
│   │           │   │   └── usedoctest.cpython-312.pyc
│   │           │   ├── _elementpath.cpython-312-darwin.so
│   │           │   ├── _elementpath.py
│   │           │   ├── apihelpers.pxi
│   │           │   ├── builder.cpython-312-darwin.so
│   │           │   ├── builder.py
│   │           │   ├── classlookup.pxi
│   │           │   ├── cleanup.pxi
│   │           │   ├── cssselect.py
│   │           │   ├── debug.pxi
│   │           │   ├── docloader.pxi
│   │           │   ├── doctestcompare.py
│   │           │   ├── dtd.pxi
│   │           │   ├── ElementInclude.py
│   │           │   ├── etree_api.h
│   │           │   ├── etree.cpython-312-darwin.so
│   │           │   ├── etree.h
│   │           │   ├── etree.pyx
│   │           │   ├── extensions.pxi
│   │           │   ├── html
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── _diffcommand.cpython-312.pyc
│   │           │   │   │   ├── _html5builder.cpython-312.pyc
│   │           │   │   │   ├── _setmixin.cpython-312.pyc
│   │           │   │   │   ├── builder.cpython-312.pyc
│   │           │   │   │   ├── clean.cpython-312.pyc
│   │           │   │   │   ├── defs.cpython-312.pyc
│   │           │   │   │   ├── diff.cpython-312.pyc
│   │           │   │   │   ├── ElementSoup.cpython-312.pyc
│   │           │   │   │   ├── formfill.cpython-312.pyc
│   │           │   │   │   ├── html5parser.cpython-312.pyc
│   │           │   │   │   ├── soupparser.cpython-312.pyc
│   │           │   │   │   └── usedoctest.cpython-312.pyc
│   │           │   │   ├── _diffcommand.py
│   │           │   │   ├── _html5builder.py
│   │           │   │   ├── _setmixin.py
│   │           │   │   ├── builder.py
│   │           │   │   ├── clean.py
│   │           │   │   ├── defs.py
│   │           │   │   ├── diff.cpython-312-darwin.so
│   │           │   │   ├── diff.py
│   │           │   │   ├── ElementSoup.py
│   │           │   │   ├── formfill.py
│   │           │   │   ├── html5parser.py
│   │           │   │   ├── soupparser.py
│   │           │   │   └── usedoctest.py
│   │           │   ├── includes
│   │           │   │   ├── __init__.pxd
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   ├── c14n.pxd
│   │           │   │   ├── config.pxd
│   │           │   │   ├── dtdvalid.pxd
│   │           │   │   ├── etree_defs.h
│   │           │   │   ├── etreepublic.pxd
│   │           │   │   ├── extlibs
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   │   ├── libcharset.h
│   │           │   │   │   ├── localcharset.h
│   │           │   │   │   ├── zconf.h
│   │           │   │   │   └── zlib.h
│   │           │   │   ├── htmlparser.pxd
│   │           │   │   ├── libexslt
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   │   ├── exslt.h
│   │           │   │   │   ├── exsltconfig.h
│   │           │   │   │   └── exsltexports.h
│   │           │   │   ├── libxml
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   │   ├── c14n.h
│   │           │   │   │   ├── catalog.h
│   │           │   │   │   ├── chvalid.h
│   │           │   │   │   ├── debugXML.h
│   │           │   │   │   ├── dict.h
│   │           │   │   │   ├── encoding.h
│   │           │   │   │   ├── entities.h
│   │           │   │   │   ├── globals.h
│   │           │   │   │   ├── hash.h
│   │           │   │   │   ├── HTMLparser.h
│   │           │   │   │   ├── HTMLtree.h
│   │           │   │   │   ├── list.h
│   │           │   │   │   ├── nanoftp.h
│   │           │   │   │   ├── nanohttp.h
│   │           │   │   │   ├── parser.h
│   │           │   │   │   ├── parserInternals.h
│   │           │   │   │   ├── relaxng.h
│   │           │   │   │   ├── SAX.h
│   │           │   │   │   ├── SAX2.h
│   │           │   │   │   ├── schemasInternals.h
│   │           │   │   │   ├── schematron.h
│   │           │   │   │   ├── threads.h
│   │           │   │   │   ├── tree.h
│   │           │   │   │   ├── uri.h
│   │           │   │   │   ├── valid.h
│   │           │   │   │   ├── xinclude.h
│   │           │   │   │   ├── xlink.h
│   │           │   │   │   ├── xmlautomata.h
│   │           │   │   │   ├── xmlerror.h
│   │           │   │   │   ├── xmlexports.h
│   │           │   │   │   ├── xmlIO.h
│   │           │   │   │   ├── xmlmemory.h
│   │           │   │   │   ├── xmlmodule.h
│   │           │   │   │   ├── xmlreader.h
│   │           │   │   │   ├── xmlregexp.h
│   │           │   │   │   ├── xmlsave.h
│   │           │   │   │   ├── xmlschemas.h
│   │           │   │   │   ├── xmlschemastypes.h
│   │           │   │   │   ├── xmlstring.h
│   │           │   │   │   ├── xmlunicode.h
│   │           │   │   │   ├── xmlversion.h
│   │           │   │   │   ├── xmlwriter.h
│   │           │   │   │   ├── xpath.h
│   │           │   │   │   ├── xpathInternals.h
│   │           │   │   │   └── xpointer.h
│   │           │   │   ├── libxslt
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   │   ├── attributes.h
│   │           │   │   │   ├── documents.h
│   │           │   │   │   ├── extensions.h
│   │           │   │   │   ├── extra.h
│   │           │   │   │   ├── functions.h
│   │           │   │   │   ├── imports.h
│   │           │   │   │   ├── keys.h
│   │           │   │   │   ├── namespaces.h
│   │           │   │   │   ├── numbersInternals.h
│   │           │   │   │   ├── pattern.h
│   │           │   │   │   ├── preproc.h
│   │           │   │   │   ├── security.h
│   │           │   │   │   ├── templates.h
│   │           │   │   │   ├── transform.h
│   │           │   │   │   ├── variables.h
│   │           │   │   │   ├── xslt.h
│   │           │   │   │   ├── xsltconfig.h
│   │           │   │   │   ├── xsltexports.h
│   │           │   │   │   ├── xsltInternals.h
│   │           │   │   │   ├── xsltlocale.h
│   │           │   │   │   └── xsltutils.h
│   │           │   │   ├── lxml-version.h
│   │           │   │   ├── relaxng.pxd
│   │           │   │   ├── schematron.pxd
│   │           │   │   ├── tree.pxd
│   │           │   │   ├── uri.pxd
│   │           │   │   ├── xinclude.pxd
│   │           │   │   ├── xmlerror.pxd
│   │           │   │   ├── xmlparser.pxd
│   │           │   │   ├── xmlschema.pxd
│   │           │   │   ├── xpath.pxd
│   │           │   │   └── xslt.pxd
│   │           │   ├── isoschematron
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   └── __init__.cpython-312.pyc
│   │           │   │   └── resources
│   │           │   │       ├── rng
│   │           │   │       │   └── iso-schematron.rng
│   │           │   │       └── xsl
│   │           │   │           ├── iso-schematron-xslt1
│   │           │   │           │   ├── iso_abstract_expand.xsl
│   │           │   │           │   ├── iso_dsdl_include.xsl
│   │           │   │           │   ├── iso_schematron_message.xsl
│   │           │   │           │   ├── iso_schematron_skeleton_for_xslt1.xsl
│   │           │   │           │   ├── iso_svrl_for_xslt1.xsl
│   │           │   │           │   └── readme.txt
│   │           │   │           ├── RNG2Schtrn.xsl
│   │           │   │           └── XSD2Schtrn.xsl
│   │           │   ├── iterparse.pxi
│   │           │   ├── lxml.etree_api.h
│   │           │   ├── lxml.etree.h
│   │           │   ├── nsclasses.pxi
│   │           │   ├── objectify.cpython-312-darwin.so
│   │           │   ├── objectify.pyx
│   │           │   ├── objectpath.pxi
│   │           │   ├── parser.pxi
│   │           │   ├── parsertarget.pxi
│   │           │   ├── proxy.pxi
│   │           │   ├── public-api.pxi
│   │           │   ├── pyclasslookup.py
│   │           │   ├── readonlytree.pxi
│   │           │   ├── relaxng.pxi
│   │           │   ├── sax.cpython-312-darwin.so
│   │           │   ├── sax.py
│   │           │   ├── saxparser.pxi
│   │           │   ├── schematron.pxi
│   │           │   ├── serializer.pxi
│   │           │   ├── usedoctest.py
│   │           │   ├── xinclude.pxi
│   │           │   ├── xmlerror.pxi
│   │           │   ├── xmlid.pxi
│   │           │   ├── xmlschema.pxi
│   │           │   ├── xpath.pxi
│   │           │   ├── xslt.pxi
│   │           │   └── xsltext.pxi
│   │           ├── lxml-5.3.0.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── LICENSES.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── markupsafe
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   └── _native.cpython-312.pyc
│   │           │   ├── _native.py
│   │           │   ├── _speedups.c
│   │           │   ├── _speedups.cpython-312-darwin.so
│   │           │   ├── _speedups.pyi
│   │           │   └── py.typed
│   │           ├── MarkupSafe-3.0.1.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── pip
│   │           │   ├── __init__.py
│   │           │   ├── __main__.py
│   │           │   ├── __pip-runner__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __main__.cpython-312.pyc
│   │           │   │   └── __pip-runner__.cpython-312.pyc
│   │           │   ├── _internal
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── build_env.cpython-312.pyc
│   │           │   │   │   ├── cache.cpython-312.pyc
│   │           │   │   │   ├── configuration.cpython-312.pyc
│   │           │   │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   │   ├── main.cpython-312.pyc
│   │           │   │   │   ├── pyproject.cpython-312.pyc
│   │           │   │   │   ├── self_outdated_check.cpython-312.pyc
│   │           │   │   │   └── wheel_builder.cpython-312.pyc
│   │           │   │   ├── build_env.py
│   │           │   │   ├── cache.py
│   │           │   │   ├── cli
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── autocompletion.cpython-312.pyc
│   │           │   │   │   │   ├── base_command.cpython-312.pyc
│   │           │   │   │   │   ├── cmdoptions.cpython-312.pyc
│   │           │   │   │   │   ├── command_context.cpython-312.pyc
│   │           │   │   │   │   ├── index_command.cpython-312.pyc
│   │           │   │   │   │   ├── main_parser.cpython-312.pyc
│   │           │   │   │   │   ├── main.cpython-312.pyc
│   │           │   │   │   │   ├── parser.cpython-312.pyc
│   │           │   │   │   │   ├── progress_bars.cpython-312.pyc
│   │           │   │   │   │   ├── req_command.cpython-312.pyc
│   │           │   │   │   │   ├── spinners.cpython-312.pyc
│   │           │   │   │   │   └── status_codes.cpython-312.pyc
│   │           │   │   │   ├── autocompletion.py
│   │           │   │   │   ├── base_command.py
│   │           │   │   │   ├── cmdoptions.py
│   │           │   │   │   ├── command_context.py
│   │           │   │   │   ├── index_command.py
│   │           │   │   │   ├── main_parser.py
│   │           │   │   │   ├── main.py
│   │           │   │   │   ├── parser.py
│   │           │   │   │   ├── progress_bars.py
│   │           │   │   │   ├── req_command.py
│   │           │   │   │   ├── spinners.py
│   │           │   │   │   └── status_codes.py
│   │           │   │   ├── commands
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── cache.cpython-312.pyc
│   │           │   │   │   │   ├── check.cpython-312.pyc
│   │           │   │   │   │   ├── completion.cpython-312.pyc
│   │           │   │   │   │   ├── configuration.cpython-312.pyc
│   │           │   │   │   │   ├── debug.cpython-312.pyc
│   │           │   │   │   │   ├── download.cpython-312.pyc
│   │           │   │   │   │   ├── freeze.cpython-312.pyc
│   │           │   │   │   │   ├── hash.cpython-312.pyc
│   │           │   │   │   │   ├── help.cpython-312.pyc
│   │           │   │   │   │   ├── index.cpython-312.pyc
│   │           │   │   │   │   ├── inspect.cpython-312.pyc
│   │           │   │   │   │   ├── install.cpython-312.pyc
│   │           │   │   │   │   ├── list.cpython-312.pyc
│   │           │   │   │   │   ├── search.cpython-312.pyc
│   │           │   │   │   │   ├── show.cpython-312.pyc
│   │           │   │   │   │   ├── uninstall.cpython-312.pyc
│   │           │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   ├── cache.py
│   │           │   │   │   ├── check.py
│   │           │   │   │   ├── completion.py
│   │           │   │   │   ├── configuration.py
│   │           │   │   │   ├── debug.py
│   │           │   │   │   ├── download.py
│   │           │   │   │   ├── freeze.py
│   │           │   │   │   ├── hash.py
│   │           │   │   │   ├── help.py
│   │           │   │   │   ├── index.py
│   │           │   │   │   ├── inspect.py
│   │           │   │   │   ├── install.py
│   │           │   │   │   ├── list.py
│   │           │   │   │   ├── search.py
│   │           │   │   │   ├── show.py
│   │           │   │   │   ├── uninstall.py
│   │           │   │   │   └── wheel.py
│   │           │   │   ├── configuration.py
│   │           │   │   ├── distributions
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── base.cpython-312.pyc
│   │           │   │   │   │   ├── installed.cpython-312.pyc
│   │           │   │   │   │   ├── sdist.cpython-312.pyc
│   │           │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   ├── base.py
│   │           │   │   │   ├── installed.py
│   │           │   │   │   ├── sdist.py
│   │           │   │   │   └── wheel.py
│   │           │   │   ├── exceptions.py
│   │           │   │   ├── index
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── collector.cpython-312.pyc
│   │           │   │   │   │   ├── package_finder.cpython-312.pyc
│   │           │   │   │   │   └── sources.cpython-312.pyc
│   │           │   │   │   ├── collector.py
│   │           │   │   │   ├── package_finder.py
│   │           │   │   │   └── sources.py
│   │           │   │   ├── locations
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _distutils.cpython-312.pyc
│   │           │   │   │   │   ├── _sysconfig.cpython-312.pyc
│   │           │   │   │   │   └── base.cpython-312.pyc
│   │           │   │   │   ├── _distutils.py
│   │           │   │   │   ├── _sysconfig.py
│   │           │   │   │   └── base.py
│   │           │   │   ├── main.py
│   │           │   │   ├── metadata
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _json.cpython-312.pyc
│   │           │   │   │   │   ├── base.cpython-312.pyc
│   │           │   │   │   │   └── pkg_resources.cpython-312.pyc
│   │           │   │   │   ├── _json.py
│   │           │   │   │   ├── base.py
│   │           │   │   │   ├── importlib
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── _compat.cpython-312.pyc
│   │           │   │   │   │   │   ├── _dists.cpython-312.pyc
│   │           │   │   │   │   │   └── _envs.cpython-312.pyc
│   │           │   │   │   │   ├── _compat.py
│   │           │   │   │   │   ├── _dists.py
│   │           │   │   │   │   └── _envs.py
│   │           │   │   │   └── pkg_resources.py
│   │           │   │   ├── models
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── candidate.cpython-312.pyc
│   │           │   │   │   │   ├── direct_url.cpython-312.pyc
│   │           │   │   │   │   ├── format_control.cpython-312.pyc
│   │           │   │   │   │   ├── index.cpython-312.pyc
│   │           │   │   │   │   ├── installation_report.cpython-312.pyc
│   │           │   │   │   │   ├── link.cpython-312.pyc
│   │           │   │   │   │   ├── scheme.cpython-312.pyc
│   │           │   │   │   │   ├── search_scope.cpython-312.pyc
│   │           │   │   │   │   ├── selection_prefs.cpython-312.pyc
│   │           │   │   │   │   ├── target_python.cpython-312.pyc
│   │           │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   ├── candidate.py
│   │           │   │   │   ├── direct_url.py
│   │           │   │   │   ├── format_control.py
│   │           │   │   │   ├── index.py
│   │           │   │   │   ├── installation_report.py
│   │           │   │   │   ├── link.py
│   │           │   │   │   ├── scheme.py
│   │           │   │   │   ├── search_scope.py
│   │           │   │   │   ├── selection_prefs.py
│   │           │   │   │   ├── target_python.py
│   │           │   │   │   └── wheel.py
│   │           │   │   ├── network
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── auth.cpython-312.pyc
│   │           │   │   │   │   ├── cache.cpython-312.pyc
│   │           │   │   │   │   ├── download.cpython-312.pyc
│   │           │   │   │   │   ├── lazy_wheel.cpython-312.pyc
│   │           │   │   │   │   ├── session.cpython-312.pyc
│   │           │   │   │   │   ├── utils.cpython-312.pyc
│   │           │   │   │   │   └── xmlrpc.cpython-312.pyc
│   │           │   │   │   ├── auth.py
│   │           │   │   │   ├── cache.py
│   │           │   │   │   ├── download.py
│   │           │   │   │   ├── lazy_wheel.py
│   │           │   │   │   ├── session.py
│   │           │   │   │   ├── utils.py
│   │           │   │   │   └── xmlrpc.py
│   │           │   │   ├── operations
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── check.cpython-312.pyc
│   │           │   │   │   │   ├── freeze.cpython-312.pyc
│   │           │   │   │   │   └── prepare.cpython-312.pyc
│   │           │   │   │   ├── build
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── build_tracker.cpython-312.pyc
│   │           │   │   │   │   │   ├── metadata_editable.cpython-312.pyc
│   │           │   │   │   │   │   ├── metadata_legacy.cpython-312.pyc
│   │           │   │   │   │   │   ├── metadata.cpython-312.pyc
│   │           │   │   │   │   │   ├── wheel_editable.cpython-312.pyc
│   │           │   │   │   │   │   ├── wheel_legacy.cpython-312.pyc
│   │           │   │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   │   ├── build_tracker.py
│   │           │   │   │   │   ├── metadata_editable.py
│   │           │   │   │   │   ├── metadata_legacy.py
│   │           │   │   │   │   ├── metadata.py
│   │           │   │   │   │   ├── wheel_editable.py
│   │           │   │   │   │   ├── wheel_legacy.py
│   │           │   │   │   │   └── wheel.py
│   │           │   │   │   ├── check.py
│   │           │   │   │   ├── freeze.py
│   │           │   │   │   ├── install
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── editable_legacy.cpython-312.pyc
│   │           │   │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   │   ├── editable_legacy.py
│   │           │   │   │   │   └── wheel.py
│   │           │   │   │   └── prepare.py
│   │           │   │   ├── pyproject.py
│   │           │   │   ├── req
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── constructors.cpython-312.pyc
│   │           │   │   │   │   ├── req_file.cpython-312.pyc
│   │           │   │   │   │   ├── req_install.cpython-312.pyc
│   │           │   │   │   │   ├── req_set.cpython-312.pyc
│   │           │   │   │   │   └── req_uninstall.cpython-312.pyc
│   │           │   │   │   ├── constructors.py
│   │           │   │   │   ├── req_file.py
│   │           │   │   │   ├── req_install.py
│   │           │   │   │   ├── req_set.py
│   │           │   │   │   └── req_uninstall.py
│   │           │   │   ├── resolution
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   └── base.cpython-312.pyc
│   │           │   │   │   ├── base.py
│   │           │   │   │   ├── legacy
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   └── resolver.cpython-312.pyc
│   │           │   │   │   │   └── resolver.py
│   │           │   │   │   └── resolvelib
│   │           │   │   │       ├── __init__.py
│   │           │   │   │       ├── __pycache__
│   │           │   │   │       │   ├── __init__.cpython-312.pyc
│   │           │   │   │       │   ├── base.cpython-312.pyc
│   │           │   │   │       │   ├── candidates.cpython-312.pyc
│   │           │   │   │       │   ├── factory.cpython-312.pyc
│   │           │   │   │       │   ├── found_candidates.cpython-312.pyc
│   │           │   │   │       │   ├── provider.cpython-312.pyc
│   │           │   │   │       │   ├── reporter.cpython-312.pyc
│   │           │   │   │       │   ├── requirements.cpython-312.pyc
│   │           │   │   │       │   └── resolver.cpython-312.pyc
│   │           │   │   │       ├── base.py
│   │           │   │   │       ├── candidates.py
│   │           │   │   │       ├── factory.py
│   │           │   │   │       ├── found_candidates.py
│   │           │   │   │       ├── provider.py
│   │           │   │   │       ├── reporter.py
│   │           │   │   │       ├── requirements.py
│   │           │   │   │       └── resolver.py
│   │           │   │   ├── self_outdated_check.py
│   │           │   │   ├── utils
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _jaraco_text.cpython-312.pyc
│   │           │   │   │   │   ├── _log.cpython-312.pyc
│   │           │   │   │   │   ├── appdirs.cpython-312.pyc
│   │           │   │   │   │   ├── compat.cpython-312.pyc
│   │           │   │   │   │   ├── compatibility_tags.cpython-312.pyc
│   │           │   │   │   │   ├── datetime.cpython-312.pyc
│   │           │   │   │   │   ├── deprecation.cpython-312.pyc
│   │           │   │   │   │   ├── direct_url_helpers.cpython-312.pyc
│   │           │   │   │   │   ├── egg_link.cpython-312.pyc
│   │           │   │   │   │   ├── encoding.cpython-312.pyc
│   │           │   │   │   │   ├── entrypoints.cpython-312.pyc
│   │           │   │   │   │   ├── filesystem.cpython-312.pyc
│   │           │   │   │   │   ├── filetypes.cpython-312.pyc
│   │           │   │   │   │   ├── glibc.cpython-312.pyc
│   │           │   │   │   │   ├── hashes.cpython-312.pyc
│   │           │   │   │   │   ├── logging.cpython-312.pyc
│   │           │   │   │   │   ├── misc.cpython-312.pyc
│   │           │   │   │   │   ├── packaging.cpython-312.pyc
│   │           │   │   │   │   ├── retry.cpython-312.pyc
│   │           │   │   │   │   ├── setuptools_build.cpython-312.pyc
│   │           │   │   │   │   ├── subprocess.cpython-312.pyc
│   │           │   │   │   │   ├── temp_dir.cpython-312.pyc
│   │           │   │   │   │   ├── unpacking.cpython-312.pyc
│   │           │   │   │   │   ├── urls.cpython-312.pyc
│   │           │   │   │   │   ├── virtualenv.cpython-312.pyc
│   │           │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   ├── _jaraco_text.py
│   │           │   │   │   ├── _log.py
│   │           │   │   │   ├── appdirs.py
│   │           │   │   │   ├── compat.py
│   │           │   │   │   ├── compatibility_tags.py
│   │           │   │   │   ├── datetime.py
│   │           │   │   │   ├── deprecation.py
│   │           │   │   │   ├── direct_url_helpers.py
│   │           │   │   │   ├── egg_link.py
│   │           │   │   │   ├── encoding.py
│   │           │   │   │   ├── entrypoints.py
│   │           │   │   │   ├── filesystem.py
│   │           │   │   │   ├── filetypes.py
│   │           │   │   │   ├── glibc.py
│   │           │   │   │   ├── hashes.py
│   │           │   │   │   ├── logging.py
│   │           │   │   │   ├── misc.py
│   │           │   │   │   ├── packaging.py
│   │           │   │   │   ├── retry.py
│   │           │   │   │   ├── setuptools_build.py
│   │           │   │   │   ├── subprocess.py
│   │           │   │   │   ├── temp_dir.py
│   │           │   │   │   ├── unpacking.py
│   │           │   │   │   ├── urls.py
│   │           │   │   │   ├── virtualenv.py
│   │           │   │   │   └── wheel.py
│   │           │   │   ├── vcs
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── bazaar.cpython-312.pyc
│   │           │   │   │   │   ├── git.cpython-312.pyc
│   │           │   │   │   │   ├── mercurial.cpython-312.pyc
│   │           │   │   │   │   ├── subversion.cpython-312.pyc
│   │           │   │   │   │   └── versioncontrol.cpython-312.pyc
│   │           │   │   │   ├── bazaar.py
│   │           │   │   │   ├── git.py
│   │           │   │   │   ├── mercurial.py
│   │           │   │   │   ├── subversion.py
│   │           │   │   │   └── versioncontrol.py
│   │           │   │   └── wheel_builder.py
│   │           │   ├── _vendor
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   └── typing_extensions.cpython-312.pyc
│   │           │   │   ├── cachecontrol
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _cmd.cpython-312.pyc
│   │           │   │   │   │   ├── adapter.cpython-312.pyc
│   │           │   │   │   │   ├── cache.cpython-312.pyc
│   │           │   │   │   │   ├── controller.cpython-312.pyc
│   │           │   │   │   │   ├── filewrapper.cpython-312.pyc
│   │           │   │   │   │   ├── heuristics.cpython-312.pyc
│   │           │   │   │   │   ├── serialize.cpython-312.pyc
│   │           │   │   │   │   └── wrapper.cpython-312.pyc
│   │           │   │   │   ├── _cmd.py
│   │           │   │   │   ├── adapter.py
│   │           │   │   │   ├── cache.py
│   │           │   │   │   ├── caches
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── file_cache.cpython-312.pyc
│   │           │   │   │   │   │   └── redis_cache.cpython-312.pyc
│   │           │   │   │   │   ├── file_cache.py
│   │           │   │   │   │   └── redis_cache.py
│   │           │   │   │   ├── controller.py
│   │           │   │   │   ├── filewrapper.py
│   │           │   │   │   ├── heuristics.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   ├── serialize.py
│   │           │   │   │   └── wrapper.py
│   │           │   │   ├── certifi
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __main__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __main__.cpython-312.pyc
│   │           │   │   │   │   └── core.cpython-312.pyc
│   │           │   │   │   ├── cacert.pem
│   │           │   │   │   ├── core.py
│   │           │   │   │   └── py.typed
│   │           │   │   ├── distlib
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── compat.cpython-312.pyc
│   │           │   │   │   │   ├── database.cpython-312.pyc
│   │           │   │   │   │   ├── index.cpython-312.pyc
│   │           │   │   │   │   ├── locators.cpython-312.pyc
│   │           │   │   │   │   ├── manifest.cpython-312.pyc
│   │           │   │   │   │   ├── markers.cpython-312.pyc
│   │           │   │   │   │   ├── metadata.cpython-312.pyc
│   │           │   │   │   │   ├── resources.cpython-312.pyc
│   │           │   │   │   │   ├── scripts.cpython-312.pyc
│   │           │   │   │   │   ├── util.cpython-312.pyc
│   │           │   │   │   │   ├── version.cpython-312.pyc
│   │           │   │   │   │   └── wheel.cpython-312.pyc
│   │           │   │   │   ├── compat.py
│   │           │   │   │   ├── database.py
│   │           │   │   │   ├── index.py
│   │           │   │   │   ├── locators.py
│   │           │   │   │   ├── manifest.py
│   │           │   │   │   ├── markers.py
│   │           │   │   │   ├── metadata.py
│   │           │   │   │   ├── resources.py
│   │           │   │   │   ├── scripts.py
│   │           │   │   │   ├── t32.exe
│   │           │   │   │   ├── t64-arm.exe
│   │           │   │   │   ├── t64.exe
│   │           │   │   │   ├── util.py
│   │           │   │   │   ├── version.py
│   │           │   │   │   ├── w32.exe
│   │           │   │   │   ├── w64-arm.exe
│   │           │   │   │   ├── w64.exe
│   │           │   │   │   └── wheel.py
│   │           │   │   ├── distro
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __main__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __main__.cpython-312.pyc
│   │           │   │   │   │   └── distro.cpython-312.pyc
│   │           │   │   │   ├── distro.py
│   │           │   │   │   └── py.typed
│   │           │   │   ├── idna
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── codec.cpython-312.pyc
│   │           │   │   │   │   ├── compat.cpython-312.pyc
│   │           │   │   │   │   ├── core.cpython-312.pyc
│   │           │   │   │   │   ├── idnadata.cpython-312.pyc
│   │           │   │   │   │   ├── intranges.cpython-312.pyc
│   │           │   │   │   │   ├── package_data.cpython-312.pyc
│   │           │   │   │   │   └── uts46data.cpython-312.pyc
│   │           │   │   │   ├── codec.py
│   │           │   │   │   ├── compat.py
│   │           │   │   │   ├── core.py
│   │           │   │   │   ├── idnadata.py
│   │           │   │   │   ├── intranges.py
│   │           │   │   │   ├── package_data.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   └── uts46data.py
│   │           │   │   ├── msgpack
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   │   │   ├── ext.cpython-312.pyc
│   │           │   │   │   │   └── fallback.cpython-312.pyc
│   │           │   │   │   ├── exceptions.py
│   │           │   │   │   ├── ext.py
│   │           │   │   │   └── fallback.py
│   │           │   │   ├── packaging
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _elffile.cpython-312.pyc
│   │           │   │   │   │   ├── _manylinux.cpython-312.pyc
│   │           │   │   │   │   ├── _musllinux.cpython-312.pyc
│   │           │   │   │   │   ├── _parser.cpython-312.pyc
│   │           │   │   │   │   ├── _structures.cpython-312.pyc
│   │           │   │   │   │   ├── _tokenizer.cpython-312.pyc
│   │           │   │   │   │   ├── markers.cpython-312.pyc
│   │           │   │   │   │   ├── metadata.cpython-312.pyc
│   │           │   │   │   │   ├── requirements.cpython-312.pyc
│   │           │   │   │   │   ├── specifiers.cpython-312.pyc
│   │           │   │   │   │   ├── tags.cpython-312.pyc
│   │           │   │   │   │   ├── utils.cpython-312.pyc
│   │           │   │   │   │   └── version.cpython-312.pyc
│   │           │   │   │   ├── _elffile.py
│   │           │   │   │   ├── _manylinux.py
│   │           │   │   │   ├── _musllinux.py
│   │           │   │   │   ├── _parser.py
│   │           │   │   │   ├── _structures.py
│   │           │   │   │   ├── _tokenizer.py
│   │           │   │   │   ├── markers.py
│   │           │   │   │   ├── metadata.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   ├── requirements.py
│   │           │   │   │   ├── specifiers.py
│   │           │   │   │   ├── tags.py
│   │           │   │   │   ├── utils.py
│   │           │   │   │   └── version.py
│   │           │   │   ├── pkg_resources
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   └── __pycache__
│   │           │   │   │       └── __init__.cpython-312.pyc
│   │           │   │   ├── platformdirs
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __main__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __main__.cpython-312.pyc
│   │           │   │   │   │   ├── android.cpython-312.pyc
│   │           │   │   │   │   ├── api.cpython-312.pyc
│   │           │   │   │   │   ├── macos.cpython-312.pyc
│   │           │   │   │   │   ├── unix.cpython-312.pyc
│   │           │   │   │   │   ├── version.cpython-312.pyc
│   │           │   │   │   │   └── windows.cpython-312.pyc
│   │           │   │   │   ├── android.py
│   │           │   │   │   ├── api.py
│   │           │   │   │   ├── macos.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   ├── unix.py
│   │           │   │   │   ├── version.py
│   │           │   │   │   └── windows.py
│   │           │   │   ├── pygments
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __main__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __main__.cpython-312.pyc
│   │           │   │   │   │   ├── cmdline.cpython-312.pyc
│   │           │   │   │   │   ├── console.cpython-312.pyc
│   │           │   │   │   │   ├── filter.cpython-312.pyc
│   │           │   │   │   │   ├── formatter.cpython-312.pyc
│   │           │   │   │   │   ├── lexer.cpython-312.pyc
│   │           │   │   │   │   ├── modeline.cpython-312.pyc
│   │           │   │   │   │   ├── plugin.cpython-312.pyc
│   │           │   │   │   │   ├── regexopt.cpython-312.pyc
│   │           │   │   │   │   ├── scanner.cpython-312.pyc
│   │           │   │   │   │   ├── sphinxext.cpython-312.pyc
│   │           │   │   │   │   ├── style.cpython-312.pyc
│   │           │   │   │   │   ├── token.cpython-312.pyc
│   │           │   │   │   │   ├── unistring.cpython-312.pyc
│   │           │   │   │   │   └── util.cpython-312.pyc
│   │           │   │   │   ├── cmdline.py
│   │           │   │   │   ├── console.py
│   │           │   │   │   ├── filter.py
│   │           │   │   │   ├── filters
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   └── __pycache__
│   │           │   │   │   │       └── __init__.cpython-312.pyc
│   │           │   │   │   ├── formatter.py
│   │           │   │   │   ├── formatters
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── _mapping.cpython-312.pyc
│   │           │   │   │   │   │   ├── bbcode.cpython-312.pyc
│   │           │   │   │   │   │   ├── groff.cpython-312.pyc
│   │           │   │   │   │   │   ├── html.cpython-312.pyc
│   │           │   │   │   │   │   ├── img.cpython-312.pyc
│   │           │   │   │   │   │   ├── irc.cpython-312.pyc
│   │           │   │   │   │   │   ├── latex.cpython-312.pyc
│   │           │   │   │   │   │   ├── other.cpython-312.pyc
│   │           │   │   │   │   │   ├── pangomarkup.cpython-312.pyc
│   │           │   │   │   │   │   ├── rtf.cpython-312.pyc
│   │           │   │   │   │   │   ├── svg.cpython-312.pyc
│   │           │   │   │   │   │   ├── terminal.cpython-312.pyc
│   │           │   │   │   │   │   └── terminal256.cpython-312.pyc
│   │           │   │   │   │   ├── _mapping.py
│   │           │   │   │   │   ├── bbcode.py
│   │           │   │   │   │   ├── groff.py
│   │           │   │   │   │   ├── html.py
│   │           │   │   │   │   ├── img.py
│   │           │   │   │   │   ├── irc.py
│   │           │   │   │   │   ├── latex.py
│   │           │   │   │   │   ├── other.py
│   │           │   │   │   │   ├── pangomarkup.py
│   │           │   │   │   │   ├── rtf.py
│   │           │   │   │   │   ├── svg.py
│   │           │   │   │   │   ├── terminal.py
│   │           │   │   │   │   └── terminal256.py
│   │           │   │   │   ├── lexer.py
│   │           │   │   │   ├── lexers
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── _mapping.cpython-312.pyc
│   │           │   │   │   │   │   └── python.cpython-312.pyc
│   │           │   │   │   │   ├── _mapping.py
│   │           │   │   │   │   └── python.py
│   │           │   │   │   ├── modeline.py
│   │           │   │   │   ├── plugin.py
│   │           │   │   │   ├── regexopt.py
│   │           │   │   │   ├── scanner.py
│   │           │   │   │   ├── sphinxext.py
│   │           │   │   │   ├── style.py
│   │           │   │   │   ├── styles
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   └── _mapping.cpython-312.pyc
│   │           │   │   │   │   └── _mapping.py
│   │           │   │   │   ├── token.py
│   │           │   │   │   ├── unistring.py
│   │           │   │   │   └── util.py
│   │           │   │   ├── pyproject_hooks
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _compat.cpython-312.pyc
│   │           │   │   │   │   └── _impl.cpython-312.pyc
│   │           │   │   │   ├── _compat.py
│   │           │   │   │   ├── _impl.py
│   │           │   │   │   └── _in_process
│   │           │   │   │       ├── __init__.py
│   │           │   │   │       ├── __pycache__
│   │           │   │   │       │   ├── __init__.cpython-312.pyc
│   │           │   │   │       │   └── _in_process.cpython-312.pyc
│   │           │   │   │       └── _in_process.py
│   │           │   │   ├── requests
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __version__.cpython-312.pyc
│   │           │   │   │   │   ├── _internal_utils.cpython-312.pyc
│   │           │   │   │   │   ├── adapters.cpython-312.pyc
│   │           │   │   │   │   ├── api.cpython-312.pyc
│   │           │   │   │   │   ├── auth.cpython-312.pyc
│   │           │   │   │   │   ├── certs.cpython-312.pyc
│   │           │   │   │   │   ├── compat.cpython-312.pyc
│   │           │   │   │   │   ├── cookies.cpython-312.pyc
│   │           │   │   │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   │   │   ├── help.cpython-312.pyc
│   │           │   │   │   │   ├── hooks.cpython-312.pyc
│   │           │   │   │   │   ├── models.cpython-312.pyc
│   │           │   │   │   │   ├── packages.cpython-312.pyc
│   │           │   │   │   │   ├── sessions.cpython-312.pyc
│   │           │   │   │   │   ├── status_codes.cpython-312.pyc
│   │           │   │   │   │   ├── structures.cpython-312.pyc
│   │           │   │   │   │   └── utils.cpython-312.pyc
│   │           │   │   │   ├── __version__.py
│   │           │   │   │   ├── _internal_utils.py
│   │           │   │   │   ├── adapters.py
│   │           │   │   │   ├── api.py
│   │           │   │   │   ├── auth.py
│   │           │   │   │   ├── certs.py
│   │           │   │   │   ├── compat.py
│   │           │   │   │   ├── cookies.py
│   │           │   │   │   ├── exceptions.py
│   │           │   │   │   ├── help.py
│   │           │   │   │   ├── hooks.py
│   │           │   │   │   ├── models.py
│   │           │   │   │   ├── packages.py
│   │           │   │   │   ├── sessions.py
│   │           │   │   │   ├── status_codes.py
│   │           │   │   │   ├── structures.py
│   │           │   │   │   └── utils.py
│   │           │   │   ├── resolvelib
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── providers.cpython-312.pyc
│   │           │   │   │   │   ├── reporters.cpython-312.pyc
│   │           │   │   │   │   ├── resolvers.cpython-312.pyc
│   │           │   │   │   │   └── structs.cpython-312.pyc
│   │           │   │   │   ├── compat
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   └── collections_abc.cpython-312.pyc
│   │           │   │   │   │   └── collections_abc.py
│   │           │   │   │   ├── providers.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   ├── reporters.py
│   │           │   │   │   ├── resolvers.py
│   │           │   │   │   └── structs.py
│   │           │   │   ├── rich
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __main__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── __main__.cpython-312.pyc
│   │           │   │   │   │   ├── _cell_widths.cpython-312.pyc
│   │           │   │   │   │   ├── _emoji_codes.cpython-312.pyc
│   │           │   │   │   │   ├── _emoji_replace.cpython-312.pyc
│   │           │   │   │   │   ├── _export_format.cpython-312.pyc
│   │           │   │   │   │   ├── _extension.cpython-312.pyc
│   │           │   │   │   │   ├── _fileno.cpython-312.pyc
│   │           │   │   │   │   ├── _inspect.cpython-312.pyc
│   │           │   │   │   │   ├── _log_render.cpython-312.pyc
│   │           │   │   │   │   ├── _loop.cpython-312.pyc
│   │           │   │   │   │   ├── _null_file.cpython-312.pyc
│   │           │   │   │   │   ├── _palettes.cpython-312.pyc
│   │           │   │   │   │   ├── _pick.cpython-312.pyc
│   │           │   │   │   │   ├── _ratio.cpython-312.pyc
│   │           │   │   │   │   ├── _spinners.cpython-312.pyc
│   │           │   │   │   │   ├── _stack.cpython-312.pyc
│   │           │   │   │   │   ├── _timer.cpython-312.pyc
│   │           │   │   │   │   ├── _win32_console.cpython-312.pyc
│   │           │   │   │   │   ├── _windows_renderer.cpython-312.pyc
│   │           │   │   │   │   ├── _windows.cpython-312.pyc
│   │           │   │   │   │   ├── _wrap.cpython-312.pyc
│   │           │   │   │   │   ├── abc.cpython-312.pyc
│   │           │   │   │   │   ├── align.cpython-312.pyc
│   │           │   │   │   │   ├── ansi.cpython-312.pyc
│   │           │   │   │   │   ├── bar.cpython-312.pyc
│   │           │   │   │   │   ├── box.cpython-312.pyc
│   │           │   │   │   │   ├── cells.cpython-312.pyc
│   │           │   │   │   │   ├── color_triplet.cpython-312.pyc
│   │           │   │   │   │   ├── color.cpython-312.pyc
│   │           │   │   │   │   ├── columns.cpython-312.pyc
│   │           │   │   │   │   ├── console.cpython-312.pyc
│   │           │   │   │   │   ├── constrain.cpython-312.pyc
│   │           │   │   │   │   ├── containers.cpython-312.pyc
│   │           │   │   │   │   ├── control.cpython-312.pyc
│   │           │   │   │   │   ├── default_styles.cpython-312.pyc
│   │           │   │   │   │   ├── diagnose.cpython-312.pyc
│   │           │   │   │   │   ├── emoji.cpython-312.pyc
│   │           │   │   │   │   ├── errors.cpython-312.pyc
│   │           │   │   │   │   ├── file_proxy.cpython-312.pyc
│   │           │   │   │   │   ├── filesize.cpython-312.pyc
│   │           │   │   │   │   ├── highlighter.cpython-312.pyc
│   │           │   │   │   │   ├── json.cpython-312.pyc
│   │           │   │   │   │   ├── jupyter.cpython-312.pyc
│   │           │   │   │   │   ├── layout.cpython-312.pyc
│   │           │   │   │   │   ├── live_render.cpython-312.pyc
│   │           │   │   │   │   ├── live.cpython-312.pyc
│   │           │   │   │   │   ├── logging.cpython-312.pyc
│   │           │   │   │   │   ├── markup.cpython-312.pyc
│   │           │   │   │   │   ├── measure.cpython-312.pyc
│   │           │   │   │   │   ├── padding.cpython-312.pyc
│   │           │   │   │   │   ├── pager.cpython-312.pyc
│   │           │   │   │   │   ├── palette.cpython-312.pyc
│   │           │   │   │   │   ├── panel.cpython-312.pyc
│   │           │   │   │   │   ├── pretty.cpython-312.pyc
│   │           │   │   │   │   ├── progress_bar.cpython-312.pyc
│   │           │   │   │   │   ├── progress.cpython-312.pyc
│   │           │   │   │   │   ├── prompt.cpython-312.pyc
│   │           │   │   │   │   ├── protocol.cpython-312.pyc
│   │           │   │   │   │   ├── region.cpython-312.pyc
│   │           │   │   │   │   ├── repr.cpython-312.pyc
│   │           │   │   │   │   ├── rule.cpython-312.pyc
│   │           │   │   │   │   ├── scope.cpython-312.pyc
│   │           │   │   │   │   ├── screen.cpython-312.pyc
│   │           │   │   │   │   ├── segment.cpython-312.pyc
│   │           │   │   │   │   ├── spinner.cpython-312.pyc
│   │           │   │   │   │   ├── status.cpython-312.pyc
│   │           │   │   │   │   ├── style.cpython-312.pyc
│   │           │   │   │   │   ├── styled.cpython-312.pyc
│   │           │   │   │   │   ├── syntax.cpython-312.pyc
│   │           │   │   │   │   ├── table.cpython-312.pyc
│   │           │   │   │   │   ├── terminal_theme.cpython-312.pyc
│   │           │   │   │   │   ├── text.cpython-312.pyc
│   │           │   │   │   │   ├── theme.cpython-312.pyc
│   │           │   │   │   │   ├── themes.cpython-312.pyc
│   │           │   │   │   │   ├── traceback.cpython-312.pyc
│   │           │   │   │   │   └── tree.cpython-312.pyc
│   │           │   │   │   ├── _cell_widths.py
│   │           │   │   │   ├── _emoji_codes.py
│   │           │   │   │   ├── _emoji_replace.py
│   │           │   │   │   ├── _export_format.py
│   │           │   │   │   ├── _extension.py
│   │           │   │   │   ├── _fileno.py
│   │           │   │   │   ├── _inspect.py
│   │           │   │   │   ├── _log_render.py
│   │           │   │   │   ├── _loop.py
│   │           │   │   │   ├── _null_file.py
│   │           │   │   │   ├── _palettes.py
│   │           │   │   │   ├── _pick.py
│   │           │   │   │   ├── _ratio.py
│   │           │   │   │   ├── _spinners.py
│   │           │   │   │   ├── _stack.py
│   │           │   │   │   ├── _timer.py
│   │           │   │   │   ├── _win32_console.py
│   │           │   │   │   ├── _windows_renderer.py
│   │           │   │   │   ├── _windows.py
│   │           │   │   │   ├── _wrap.py
│   │           │   │   │   ├── abc.py
│   │           │   │   │   ├── align.py
│   │           │   │   │   ├── ansi.py
│   │           │   │   │   ├── bar.py
│   │           │   │   │   ├── box.py
│   │           │   │   │   ├── cells.py
│   │           │   │   │   ├── color_triplet.py
│   │           │   │   │   ├── color.py
│   │           │   │   │   ├── columns.py
│   │           │   │   │   ├── console.py
│   │           │   │   │   ├── constrain.py
│   │           │   │   │   ├── containers.py
│   │           │   │   │   ├── control.py
│   │           │   │   │   ├── default_styles.py
│   │           │   │   │   ├── diagnose.py
│   │           │   │   │   ├── emoji.py
│   │           │   │   │   ├── errors.py
│   │           │   │   │   ├── file_proxy.py
│   │           │   │   │   ├── filesize.py
│   │           │   │   │   ├── highlighter.py
│   │           │   │   │   ├── json.py
│   │           │   │   │   ├── jupyter.py
│   │           │   │   │   ├── layout.py
│   │           │   │   │   ├── live_render.py
│   │           │   │   │   ├── live.py
│   │           │   │   │   ├── logging.py
│   │           │   │   │   ├── markup.py
│   │           │   │   │   ├── measure.py
│   │           │   │   │   ├── padding.py
│   │           │   │   │   ├── pager.py
│   │           │   │   │   ├── palette.py
│   │           │   │   │   ├── panel.py
│   │           │   │   │   ├── pretty.py
│   │           │   │   │   ├── progress_bar.py
│   │           │   │   │   ├── progress.py
│   │           │   │   │   ├── prompt.py
│   │           │   │   │   ├── protocol.py
│   │           │   │   │   ├── py.typed
│   │           │   │   │   ├── region.py
│   │           │   │   │   ├── repr.py
│   │           │   │   │   ├── rule.py
│   │           │   │   │   ├── scope.py
│   │           │   │   │   ├── screen.py
│   │           │   │   │   ├── segment.py
│   │           │   │   │   ├── spinner.py
│   │           │   │   │   ├── status.py
│   │           │   │   │   ├── style.py
│   │           │   │   │   ├── styled.py
│   │           │   │   │   ├── syntax.py
│   │           │   │   │   ├── table.py
│   │           │   │   │   ├── terminal_theme.py
│   │           │   │   │   ├── text.py
│   │           │   │   │   ├── theme.py
│   │           │   │   │   ├── themes.py
│   │           │   │   │   ├── traceback.py
│   │           │   │   │   └── tree.py
│   │           │   │   ├── tomli
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _parser.cpython-312.pyc
│   │           │   │   │   │   ├── _re.cpython-312.pyc
│   │           │   │   │   │   └── _types.cpython-312.pyc
│   │           │   │   │   ├── _parser.py
│   │           │   │   │   ├── _re.py
│   │           │   │   │   ├── _types.py
│   │           │   │   │   └── py.typed
│   │           │   │   ├── truststore
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _api.cpython-312.pyc
│   │           │   │   │   │   ├── _macos.cpython-312.pyc
│   │           │   │   │   │   ├── _openssl.cpython-312.pyc
│   │           │   │   │   │   ├── _ssl_constants.cpython-312.pyc
│   │           │   │   │   │   └── _windows.cpython-312.pyc
│   │           │   │   │   ├── _api.py
│   │           │   │   │   ├── _macos.py
│   │           │   │   │   ├── _openssl.py
│   │           │   │   │   ├── _ssl_constants.py
│   │           │   │   │   ├── _windows.py
│   │           │   │   │   └── py.typed
│   │           │   │   ├── typing_extensions.py
│   │           │   │   ├── urllib3
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── _collections.cpython-312.pyc
│   │           │   │   │   │   ├── _version.cpython-312.pyc
│   │           │   │   │   │   ├── connection.cpython-312.pyc
│   │           │   │   │   │   ├── connectionpool.cpython-312.pyc
│   │           │   │   │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   │   │   ├── fields.cpython-312.pyc
│   │           │   │   │   │   ├── filepost.cpython-312.pyc
│   │           │   │   │   │   ├── poolmanager.cpython-312.pyc
│   │           │   │   │   │   ├── request.cpython-312.pyc
│   │           │   │   │   │   └── response.cpython-312.pyc
│   │           │   │   │   ├── _collections.py
│   │           │   │   │   ├── _version.py
│   │           │   │   │   ├── connection.py
│   │           │   │   │   ├── connectionpool.py
│   │           │   │   │   ├── contrib
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   ├── _appengine_environ.cpython-312.pyc
│   │           │   │   │   │   │   ├── appengine.cpython-312.pyc
│   │           │   │   │   │   │   ├── ntlmpool.cpython-312.pyc
│   │           │   │   │   │   │   ├── pyopenssl.cpython-312.pyc
│   │           │   │   │   │   │   ├── securetransport.cpython-312.pyc
│   │           │   │   │   │   │   └── socks.cpython-312.pyc
│   │           │   │   │   │   ├── _appengine_environ.py
│   │           │   │   │   │   ├── _securetransport
│   │           │   │   │   │   │   ├── __init__.py
│   │           │   │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   │   ├── bindings.cpython-312.pyc
│   │           │   │   │   │   │   │   └── low_level.cpython-312.pyc
│   │           │   │   │   │   │   ├── bindings.py
│   │           │   │   │   │   │   └── low_level.py
│   │           │   │   │   │   ├── appengine.py
│   │           │   │   │   │   ├── ntlmpool.py
│   │           │   │   │   │   ├── pyopenssl.py
│   │           │   │   │   │   ├── securetransport.py
│   │           │   │   │   │   └── socks.py
│   │           │   │   │   ├── exceptions.py
│   │           │   │   │   ├── fields.py
│   │           │   │   │   ├── filepost.py
│   │           │   │   │   ├── packages
│   │           │   │   │   │   ├── __init__.py
│   │           │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   └── six.cpython-312.pyc
│   │           │   │   │   │   ├── backports
│   │           │   │   │   │   │   ├── __init__.py
│   │           │   │   │   │   │   ├── __pycache__
│   │           │   │   │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   │   │   ├── makefile.cpython-312.pyc
│   │           │   │   │   │   │   │   └── weakref_finalize.cpython-312.pyc
│   │           │   │   │   │   │   ├── makefile.py
│   │           │   │   │   │   │   └── weakref_finalize.py
│   │           │   │   │   │   └── six.py
│   │           │   │   │   ├── poolmanager.py
│   │           │   │   │   ├── request.py
│   │           │   │   │   ├── response.py
│   │           │   │   │   └── util
│   │           │   │   │       ├── __init__.py
│   │           │   │   │       ├── __pycache__
│   │           │   │   │       │   ├── __init__.cpython-312.pyc
│   │           │   │   │       │   ├── connection.cpython-312.pyc
│   │           │   │   │       │   ├── proxy.cpython-312.pyc
│   │           │   │   │       │   ├── queue.cpython-312.pyc
│   │           │   │   │       │   ├── request.cpython-312.pyc
│   │           │   │   │       │   ├── response.cpython-312.pyc
│   │           │   │   │       │   ├── retry.cpython-312.pyc
│   │           │   │   │       │   ├── ssl_.cpython-312.pyc
│   │           │   │   │       │   ├── ssl_match_hostname.cpython-312.pyc
│   │           │   │   │       │   ├── ssltransport.cpython-312.pyc
│   │           │   │   │       │   ├── timeout.cpython-312.pyc
│   │           │   │   │       │   ├── url.cpython-312.pyc
│   │           │   │   │       │   └── wait.cpython-312.pyc
│   │           │   │   │       ├── connection.py
│   │           │   │   │       ├── proxy.py
│   │           │   │   │       ├── queue.py
│   │           │   │   │       ├── request.py
│   │           │   │   │       ├── response.py
│   │           │   │   │       ├── retry.py
│   │           │   │   │       ├── ssl_.py
│   │           │   │   │       ├── ssl_match_hostname.py
│   │           │   │   │       ├── ssltransport.py
│   │           │   │   │       ├── timeout.py
│   │           │   │   │       ├── url.py
│   │           │   │   │       └── wait.py
│   │           │   │   └── vendor.txt
│   │           │   └── py.typed
│   │           ├── pip-24.2.dist-info
│   │           │   ├── AUTHORS.txt
│   │           │   ├── entry_points.txt
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── requests
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __version__.cpython-312.pyc
│   │           │   │   ├── _internal_utils.cpython-312.pyc
│   │           │   │   ├── adapters.cpython-312.pyc
│   │           │   │   ├── api.cpython-312.pyc
│   │           │   │   ├── auth.cpython-312.pyc
│   │           │   │   ├── certs.cpython-312.pyc
│   │           │   │   ├── compat.cpython-312.pyc
│   │           │   │   ├── cookies.cpython-312.pyc
│   │           │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   ├── help.cpython-312.pyc
│   │           │   │   ├── hooks.cpython-312.pyc
│   │           │   │   ├── models.cpython-312.pyc
│   │           │   │   ├── packages.cpython-312.pyc
│   │           │   │   ├── sessions.cpython-312.pyc
│   │           │   │   ├── status_codes.cpython-312.pyc
│   │           │   │   ├── structures.cpython-312.pyc
│   │           │   │   └── utils.cpython-312.pyc
│   │           │   ├── __version__.py
│   │           │   ├── _internal_utils.py
│   │           │   ├── adapters.py
│   │           │   ├── api.py
│   │           │   ├── auth.py
│   │           │   ├── certs.py
│   │           │   ├── compat.py
│   │           │   ├── cookies.py
│   │           │   ├── exceptions.py
│   │           │   ├── help.py
│   │           │   ├── hooks.py
│   │           │   ├── models.py
│   │           │   ├── packages.py
│   │           │   ├── sessions.py
│   │           │   ├── status_codes.py
│   │           │   ├── structures.py
│   │           │   └── utils.py
│   │           ├── requests-2.32.3.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── soupsieve
│   │           │   ├── __init__.py
│   │           │   ├── __meta__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── __meta__.cpython-312.pyc
│   │           │   │   ├── css_match.cpython-312.pyc
│   │           │   │   ├── css_parser.cpython-312.pyc
│   │           │   │   ├── css_types.cpython-312.pyc
│   │           │   │   ├── pretty.cpython-312.pyc
│   │           │   │   └── util.cpython-312.pyc
│   │           │   ├── css_match.py
│   │           │   ├── css_parser.py
│   │           │   ├── css_types.py
│   │           │   ├── pretty.py
│   │           │   ├── py.typed
│   │           │   └── util.py
│   │           ├── soupsieve-2.6.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── licenses
│   │           │   │   └── LICENSE.md
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── urllib3
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _base_connection.cpython-312.pyc
│   │           │   │   ├── _collections.cpython-312.pyc
│   │           │   │   ├── _request_methods.cpython-312.pyc
│   │           │   │   ├── _version.cpython-312.pyc
│   │           │   │   ├── connection.cpython-312.pyc
│   │           │   │   ├── connectionpool.cpython-312.pyc
│   │           │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   ├── fields.cpython-312.pyc
│   │           │   │   ├── filepost.cpython-312.pyc
│   │           │   │   ├── poolmanager.cpython-312.pyc
│   │           │   │   └── response.cpython-312.pyc
│   │           │   ├── _base_connection.py
│   │           │   ├── _collections.py
│   │           │   ├── _request_methods.py
│   │           │   ├── _version.py
│   │           │   ├── connection.py
│   │           │   ├── connectionpool.py
│   │           │   ├── contrib
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── pyopenssl.cpython-312.pyc
│   │           │   │   │   └── socks.cpython-312.pyc
│   │           │   │   ├── emscripten
│   │           │   │   │   ├── __init__.py
│   │           │   │   │   ├── __pycache__
│   │           │   │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   │   ├── connection.cpython-312.pyc
│   │           │   │   │   │   ├── fetch.cpython-312.pyc
│   │           │   │   │   │   ├── request.cpython-312.pyc
│   │           │   │   │   │   └── response.cpython-312.pyc
│   │           │   │   │   ├── connection.py
│   │           │   │   │   ├── emscripten_fetch_worker.js
│   │           │   │   │   ├── fetch.py
│   │           │   │   │   ├── request.py
│   │           │   │   │   └── response.py
│   │           │   │   ├── pyopenssl.py
│   │           │   │   └── socks.py
│   │           │   ├── exceptions.py
│   │           │   ├── fields.py
│   │           │   ├── filepost.py
│   │           │   ├── http2
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── connection.cpython-312.pyc
│   │           │   │   │   └── probe.cpython-312.pyc
│   │           │   │   ├── connection.py
│   │           │   │   └── probe.py
│   │           │   ├── poolmanager.py
│   │           │   ├── py.typed
│   │           │   ├── response.py
│   │           │   └── util
│   │           │       ├── __init__.py
│   │           │       ├── __pycache__
│   │           │       │   ├── __init__.cpython-312.pyc
│   │           │       │   ├── connection.cpython-312.pyc
│   │           │       │   ├── proxy.cpython-312.pyc
│   │           │       │   ├── request.cpython-312.pyc
│   │           │       │   ├── response.cpython-312.pyc
│   │           │       │   ├── retry.cpython-312.pyc
│   │           │       │   ├── ssl_.cpython-312.pyc
│   │           │       │   ├── ssl_match_hostname.cpython-312.pyc
│   │           │       │   ├── ssltransport.cpython-312.pyc
│   │           │       │   ├── timeout.cpython-312.pyc
│   │           │       │   ├── url.cpython-312.pyc
│   │           │       │   ├── util.cpython-312.pyc
│   │           │       │   └── wait.cpython-312.pyc
│   │           │       ├── connection.py
│   │           │       ├── proxy.py
│   │           │       ├── request.py
│   │           │       ├── response.py
│   │           │       ├── retry.py
│   │           │       ├── ssl_.py
│   │           │       ├── ssl_match_hostname.py
│   │           │       ├── ssltransport.py
│   │           │       ├── timeout.py
│   │           │       ├── url.py
│   │           │       ├── util.py
│   │           │       └── wait.py
│   │           ├── urllib3-2.2.3.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── licenses
│   │           │   │   └── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   └── WHEEL
│   │           ├── useragent
│   │           │   ├── __init__.py
│   │           │   ├── __init__.pyc
│   │           │   ├── __pycache__
│   │           │   │   └── __init__.cpython-312.pyc
│   │           │   ├── resources
│   │           │   │   └── user_agent_data.json
│   │           │   └── test
│   │           │       ├── __init__.py
│   │           │       ├── __pycache__
│   │           │       │   └── __init__.cpython-312.pyc
│   │           │       ├── test_additional_os.json
│   │           │       ├── test_browser.json
│   │           │       ├── test_device.json
│   │           │       ├── test_firefox.json
│   │           │       ├── test_os.json
│   │           │       └── test_pgts_browser.json
│   │           ├── useragent-0.1.1.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── LICENSE.txt
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── REQUESTED
│   │           │   ├── top_level.txt
│   │           │   └── WHEEL
│   │           ├── werkzeug
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   ├── __init__.cpython-312.pyc
│   │           │   │   ├── _internal.cpython-312.pyc
│   │           │   │   ├── _reloader.cpython-312.pyc
│   │           │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   ├── formparser.cpython-312.pyc
│   │           │   │   ├── http.cpython-312.pyc
│   │           │   │   ├── local.cpython-312.pyc
│   │           │   │   ├── security.cpython-312.pyc
│   │           │   │   ├── serving.cpython-312.pyc
│   │           │   │   ├── test.cpython-312.pyc
│   │           │   │   ├── testapp.cpython-312.pyc
│   │           │   │   ├── urls.cpython-312.pyc
│   │           │   │   ├── user_agent.cpython-312.pyc
│   │           │   │   ├── utils.cpython-312.pyc
│   │           │   │   └── wsgi.cpython-312.pyc
│   │           │   ├── _internal.py
│   │           │   ├── _reloader.py
│   │           │   ├── datastructures
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── accept.cpython-312.pyc
│   │           │   │   │   ├── auth.cpython-312.pyc
│   │           │   │   │   ├── cache_control.cpython-312.pyc
│   │           │   │   │   ├── csp.cpython-312.pyc
│   │           │   │   │   ├── etag.cpython-312.pyc
│   │           │   │   │   ├── file_storage.cpython-312.pyc
│   │           │   │   │   ├── headers.cpython-312.pyc
│   │           │   │   │   ├── mixins.cpython-312.pyc
│   │           │   │   │   ├── range.cpython-312.pyc
│   │           │   │   │   └── structures.cpython-312.pyc
│   │           │   │   ├── accept.py
│   │           │   │   ├── accept.pyi
│   │           │   │   ├── auth.py
│   │           │   │   ├── cache_control.py
│   │           │   │   ├── cache_control.pyi
│   │           │   │   ├── csp.py
│   │           │   │   ├── csp.pyi
│   │           │   │   ├── etag.py
│   │           │   │   ├── etag.pyi
│   │           │   │   ├── file_storage.py
│   │           │   │   ├── file_storage.pyi
│   │           │   │   ├── headers.py
│   │           │   │   ├── headers.pyi
│   │           │   │   ├── mixins.py
│   │           │   │   ├── mixins.pyi
│   │           │   │   ├── range.py
│   │           │   │   ├── range.pyi
│   │           │   │   ├── structures.py
│   │           │   │   └── structures.pyi
│   │           │   ├── debug
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── console.cpython-312.pyc
│   │           │   │   │   ├── repr.cpython-312.pyc
│   │           │   │   │   └── tbtools.cpython-312.pyc
│   │           │   │   ├── console.py
│   │           │   │   ├── repr.py
│   │           │   │   ├── shared
│   │           │   │   │   ├── console.png
│   │           │   │   │   ├── debugger.js
│   │           │   │   │   ├── ICON_LICENSE.md
│   │           │   │   │   ├── less.png
│   │           │   │   │   ├── more.png
│   │           │   │   │   └── style.css
│   │           │   │   └── tbtools.py
│   │           │   ├── exceptions.py
│   │           │   ├── formparser.py
│   │           │   ├── http.py
│   │           │   ├── local.py
│   │           │   ├── middleware
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── dispatcher.cpython-312.pyc
│   │           │   │   │   ├── http_proxy.cpython-312.pyc
│   │           │   │   │   ├── lint.cpython-312.pyc
│   │           │   │   │   ├── profiler.cpython-312.pyc
│   │           │   │   │   ├── proxy_fix.cpython-312.pyc
│   │           │   │   │   └── shared_data.cpython-312.pyc
│   │           │   │   ├── dispatcher.py
│   │           │   │   ├── http_proxy.py
│   │           │   │   ├── lint.py
│   │           │   │   ├── profiler.py
│   │           │   │   ├── proxy_fix.py
│   │           │   │   └── shared_data.py
│   │           │   ├── py.typed
│   │           │   ├── routing
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── converters.cpython-312.pyc
│   │           │   │   │   ├── exceptions.cpython-312.pyc
│   │           │   │   │   ├── map.cpython-312.pyc
│   │           │   │   │   ├── matcher.cpython-312.pyc
│   │           │   │   │   └── rules.cpython-312.pyc
│   │           │   │   ├── converters.py
│   │           │   │   ├── exceptions.py
│   │           │   │   ├── map.py
│   │           │   │   ├── matcher.py
│   │           │   │   └── rules.py
│   │           │   ├── sansio
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── http.cpython-312.pyc
│   │           │   │   │   ├── multipart.cpython-312.pyc
│   │           │   │   │   ├── request.cpython-312.pyc
│   │           │   │   │   ├── response.cpython-312.pyc
│   │           │   │   │   └── utils.cpython-312.pyc
│   │           │   │   ├── http.py
│   │           │   │   ├── multipart.py
│   │           │   │   ├── request.py
│   │           │   │   ├── response.py
│   │           │   │   └── utils.py
│   │           │   ├── security.py
│   │           │   ├── serving.py
│   │           │   ├── test.py
│   │           │   ├── testapp.py
│   │           │   ├── urls.py
│   │           │   ├── user_agent.py
│   │           │   ├── utils.py
│   │           │   ├── wrappers
│   │           │   │   ├── __init__.py
│   │           │   │   ├── __pycache__
│   │           │   │   │   ├── __init__.cpython-312.pyc
│   │           │   │   │   ├── request.cpython-312.pyc
│   │           │   │   │   └── response.cpython-312.pyc
│   │           │   │   ├── request.py
│   │           │   │   └── response.py
│   │           │   └── wsgi.py
│   │           └── werkzeug-3.0.4.dist-info
│   │               ├── INSTALLER
│   │               ├── LICENSE.txt
│   │               ├── METADATA
│   │               ├── RECORD
│   │               └── WHEEL
│   ├── pyvenv.cfg
│   ├── static
│   │   └── styles.css
│   ├── templates
│   │   └── index.html
│   └── test.py
├── cline_config.json
├── mcp_server.py
├── README.md
├── search_results.json
├── settings.json
└── test_files
    ├── text1.txt
    └── text2.txt
```

# Files

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_internal/req/req_file.py:
--------------------------------------------------------------------------------

```python
  1 | """
  2 | Requirements file parsing
  3 | """
  4 | 
  5 | import logging
  6 | import optparse
  7 | import os
  8 | import re
  9 | import shlex
 10 | import urllib.parse
 11 | from optparse import Values
 12 | from typing import (
 13 |     TYPE_CHECKING,
 14 |     Any,
 15 |     Callable,
 16 |     Dict,
 17 |     Generator,
 18 |     Iterable,
 19 |     List,
 20 |     NoReturn,
 21 |     Optional,
 22 |     Tuple,
 23 | )
 24 | 
 25 | from pip._internal.cli import cmdoptions
 26 | from pip._internal.exceptions import InstallationError, RequirementsFileParseError
 27 | from pip._internal.models.search_scope import SearchScope
 28 | from pip._internal.utils.encoding import auto_decode
 29 | 
 30 | if TYPE_CHECKING:
 31 |     from pip._internal.index.package_finder import PackageFinder
 32 |     from pip._internal.network.session import PipSession
 33 | 
 34 | __all__ = ["parse_requirements"]
 35 | 
 36 | ReqFileLines = Iterable[Tuple[int, str]]
 37 | 
 38 | LineParser = Callable[[str], Tuple[str, Values]]
 39 | 
 40 | SCHEME_RE = re.compile(r"^(http|https|file):", re.I)
 41 | COMMENT_RE = re.compile(r"(^|\s+)#.*$")
 42 | 
 43 | # Matches environment variable-style values in '${MY_VARIABLE_1}' with the
 44 | # variable name consisting of only uppercase letters, digits or the '_'
 45 | # (underscore). This follows the POSIX standard defined in IEEE Std 1003.1,
 46 | # 2013 Edition.
 47 | ENV_VAR_RE = re.compile(r"(?P<var>\$\{(?P<name>[A-Z0-9_]+)\})")
 48 | 
 49 | SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [
 50 |     cmdoptions.index_url,
 51 |     cmdoptions.extra_index_url,
 52 |     cmdoptions.no_index,
 53 |     cmdoptions.constraints,
 54 |     cmdoptions.requirements,
 55 |     cmdoptions.editable,
 56 |     cmdoptions.find_links,
 57 |     cmdoptions.no_binary,
 58 |     cmdoptions.only_binary,
 59 |     cmdoptions.prefer_binary,
 60 |     cmdoptions.require_hashes,
 61 |     cmdoptions.pre,
 62 |     cmdoptions.trusted_host,
 63 |     cmdoptions.use_new_feature,
 64 | ]
 65 | 
 66 | # options to be passed to requirements
 67 | SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [
 68 |     cmdoptions.global_options,
 69 |     cmdoptions.hash,
 70 |     cmdoptions.config_settings,
 71 | ]
 72 | 
 73 | SUPPORTED_OPTIONS_EDITABLE_REQ: List[Callable[..., optparse.Option]] = [
 74 |     cmdoptions.config_settings,
 75 | ]
 76 | 
 77 | 
 78 | # the 'dest' string values
 79 | SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ]
 80 | SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [
 81 |     str(o().dest) for o in SUPPORTED_OPTIONS_EDITABLE_REQ
 82 | ]
 83 | 
 84 | logger = logging.getLogger(__name__)
 85 | 
 86 | 
 87 | class ParsedRequirement:
 88 |     def __init__(
 89 |         self,
 90 |         requirement: str,
 91 |         is_editable: bool,
 92 |         comes_from: str,
 93 |         constraint: bool,
 94 |         options: Optional[Dict[str, Any]] = None,
 95 |         line_source: Optional[str] = None,
 96 |     ) -> None:
 97 |         self.requirement = requirement
 98 |         self.is_editable = is_editable
 99 |         self.comes_from = comes_from
100 |         self.options = options
101 |         self.constraint = constraint
102 |         self.line_source = line_source
103 | 
104 | 
105 | class ParsedLine:
106 |     def __init__(
107 |         self,
108 |         filename: str,
109 |         lineno: int,
110 |         args: str,
111 |         opts: Values,
112 |         constraint: bool,
113 |     ) -> None:
114 |         self.filename = filename
115 |         self.lineno = lineno
116 |         self.opts = opts
117 |         self.constraint = constraint
118 | 
119 |         if args:
120 |             self.is_requirement = True
121 |             self.is_editable = False
122 |             self.requirement = args
123 |         elif opts.editables:
124 |             self.is_requirement = True
125 |             self.is_editable = True
126 |             # We don't support multiple -e on one line
127 |             self.requirement = opts.editables[0]
128 |         else:
129 |             self.is_requirement = False
130 | 
131 | 
132 | def parse_requirements(
133 |     filename: str,
134 |     session: "PipSession",
135 |     finder: Optional["PackageFinder"] = None,
136 |     options: Optional[optparse.Values] = None,
137 |     constraint: bool = False,
138 | ) -> Generator[ParsedRequirement, None, None]:
139 |     """Parse a requirements file and yield ParsedRequirement instances.
140 | 
141 |     :param filename:    Path or url of requirements file.
142 |     :param session:     PipSession instance.
143 |     :param finder:      Instance of pip.index.PackageFinder.
144 |     :param options:     cli options.
145 |     :param constraint:  If true, parsing a constraint file rather than
146 |         requirements file.
147 |     """
148 |     line_parser = get_line_parser(finder)
149 |     parser = RequirementsFileParser(session, line_parser)
150 | 
151 |     for parsed_line in parser.parse(filename, constraint):
152 |         parsed_req = handle_line(
153 |             parsed_line, options=options, finder=finder, session=session
154 |         )
155 |         if parsed_req is not None:
156 |             yield parsed_req
157 | 
158 | 
159 | def preprocess(content: str) -> ReqFileLines:
160 |     """Split, filter, and join lines, and return a line iterator
161 | 
162 |     :param content: the content of the requirements file
163 |     """
164 |     lines_enum: ReqFileLines = enumerate(content.splitlines(), start=1)
165 |     lines_enum = join_lines(lines_enum)
166 |     lines_enum = ignore_comments(lines_enum)
167 |     lines_enum = expand_env_variables(lines_enum)
168 |     return lines_enum
169 | 
170 | 
171 | def handle_requirement_line(
172 |     line: ParsedLine,
173 |     options: Optional[optparse.Values] = None,
174 | ) -> ParsedRequirement:
175 |     # preserve for the nested code path
176 |     line_comes_from = "{} {} (line {})".format(
177 |         "-c" if line.constraint else "-r",
178 |         line.filename,
179 |         line.lineno,
180 |     )
181 | 
182 |     assert line.is_requirement
183 | 
184 |     # get the options that apply to requirements
185 |     if line.is_editable:
186 |         supported_dest = SUPPORTED_OPTIONS_EDITABLE_REQ_DEST
187 |     else:
188 |         supported_dest = SUPPORTED_OPTIONS_REQ_DEST
189 |     req_options = {}
190 |     for dest in supported_dest:
191 |         if dest in line.opts.__dict__ and line.opts.__dict__[dest]:
192 |             req_options[dest] = line.opts.__dict__[dest]
193 | 
194 |     line_source = f"line {line.lineno} of {line.filename}"
195 |     return ParsedRequirement(
196 |         requirement=line.requirement,
197 |         is_editable=line.is_editable,
198 |         comes_from=line_comes_from,
199 |         constraint=line.constraint,
200 |         options=req_options,
201 |         line_source=line_source,
202 |     )
203 | 
204 | 
205 | def handle_option_line(
206 |     opts: Values,
207 |     filename: str,
208 |     lineno: int,
209 |     finder: Optional["PackageFinder"] = None,
210 |     options: Optional[optparse.Values] = None,
211 |     session: Optional["PipSession"] = None,
212 | ) -> None:
213 |     if opts.hashes:
214 |         logger.warning(
215 |             "%s line %s has --hash but no requirement, and will be ignored.",
216 |             filename,
217 |             lineno,
218 |         )
219 | 
220 |     if options:
221 |         # percolate options upward
222 |         if opts.require_hashes:
223 |             options.require_hashes = opts.require_hashes
224 |         if opts.features_enabled:
225 |             options.features_enabled.extend(
226 |                 f for f in opts.features_enabled if f not in options.features_enabled
227 |             )
228 | 
229 |     # set finder options
230 |     if finder:
231 |         find_links = finder.find_links
232 |         index_urls = finder.index_urls
233 |         no_index = finder.search_scope.no_index
234 |         if opts.no_index is True:
235 |             no_index = True
236 |             index_urls = []
237 |         if opts.index_url and not no_index:
238 |             index_urls = [opts.index_url]
239 |         if opts.extra_index_urls and not no_index:
240 |             index_urls.extend(opts.extra_index_urls)
241 |         if opts.find_links:
242 |             # FIXME: it would be nice to keep track of the source
243 |             # of the find_links: support a find-links local path
244 |             # relative to a requirements file.
245 |             value = opts.find_links[0]
246 |             req_dir = os.path.dirname(os.path.abspath(filename))
247 |             relative_to_reqs_file = os.path.join(req_dir, value)
248 |             if os.path.exists(relative_to_reqs_file):
249 |                 value = relative_to_reqs_file
250 |             find_links.append(value)
251 | 
252 |         if session:
253 |             # We need to update the auth urls in session
254 |             session.update_index_urls(index_urls)
255 | 
256 |         search_scope = SearchScope(
257 |             find_links=find_links,
258 |             index_urls=index_urls,
259 |             no_index=no_index,
260 |         )
261 |         finder.search_scope = search_scope
262 | 
263 |         if opts.pre:
264 |             finder.set_allow_all_prereleases()
265 | 
266 |         if opts.prefer_binary:
267 |             finder.set_prefer_binary()
268 | 
269 |         if session:
270 |             for host in opts.trusted_hosts or []:
271 |                 source = f"line {lineno} of {filename}"
272 |                 session.add_trusted_host(host, source=source)
273 | 
274 | 
275 | def handle_line(
276 |     line: ParsedLine,
277 |     options: Optional[optparse.Values] = None,
278 |     finder: Optional["PackageFinder"] = None,
279 |     session: Optional["PipSession"] = None,
280 | ) -> Optional[ParsedRequirement]:
281 |     """Handle a single parsed requirements line; This can result in
282 |     creating/yielding requirements, or updating the finder.
283 | 
284 |     :param line:        The parsed line to be processed.
285 |     :param options:     CLI options.
286 |     :param finder:      The finder - updated by non-requirement lines.
287 |     :param session:     The session - updated by non-requirement lines.
288 | 
289 |     Returns a ParsedRequirement object if the line is a requirement line,
290 |     otherwise returns None.
291 | 
292 |     For lines that contain requirements, the only options that have an effect
293 |     are from SUPPORTED_OPTIONS_REQ, and they are scoped to the
294 |     requirement. Other options from SUPPORTED_OPTIONS may be present, but are
295 |     ignored.
296 | 
297 |     For lines that do not contain requirements, the only options that have an
298 |     effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may
299 |     be present, but are ignored. These lines may contain multiple options
300 |     (although our docs imply only one is supported), and all our parsed and
301 |     affect the finder.
302 |     """
303 | 
304 |     if line.is_requirement:
305 |         parsed_req = handle_requirement_line(line, options)
306 |         return parsed_req
307 |     else:
308 |         handle_option_line(
309 |             line.opts,
310 |             line.filename,
311 |             line.lineno,
312 |             finder,
313 |             options,
314 |             session,
315 |         )
316 |         return None
317 | 
318 | 
319 | class RequirementsFileParser:
320 |     def __init__(
321 |         self,
322 |         session: "PipSession",
323 |         line_parser: LineParser,
324 |     ) -> None:
325 |         self._session = session
326 |         self._line_parser = line_parser
327 | 
328 |     def parse(
329 |         self, filename: str, constraint: bool
330 |     ) -> Generator[ParsedLine, None, None]:
331 |         """Parse a given file, yielding parsed lines."""
332 |         yield from self._parse_and_recurse(filename, constraint)
333 | 
334 |     def _parse_and_recurse(
335 |         self, filename: str, constraint: bool
336 |     ) -> Generator[ParsedLine, None, None]:
337 |         for line in self._parse_file(filename, constraint):
338 |             if not line.is_requirement and (
339 |                 line.opts.requirements or line.opts.constraints
340 |             ):
341 |                 # parse a nested requirements file
342 |                 if line.opts.requirements:
343 |                     req_path = line.opts.requirements[0]
344 |                     nested_constraint = False
345 |                 else:
346 |                     req_path = line.opts.constraints[0]
347 |                     nested_constraint = True
348 | 
349 |                 # original file is over http
350 |                 if SCHEME_RE.search(filename):
351 |                     # do a url join so relative paths work
352 |                     req_path = urllib.parse.urljoin(filename, req_path)
353 |                 # original file and nested file are paths
354 |                 elif not SCHEME_RE.search(req_path):
355 |                     # do a join so relative paths work
356 |                     req_path = os.path.join(
357 |                         os.path.dirname(filename),
358 |                         req_path,
359 |                     )
360 | 
361 |                 yield from self._parse_and_recurse(req_path, nested_constraint)
362 |             else:
363 |                 yield line
364 | 
365 |     def _parse_file(
366 |         self, filename: str, constraint: bool
367 |     ) -> Generator[ParsedLine, None, None]:
368 |         _, content = get_file_content(filename, self._session)
369 | 
370 |         lines_enum = preprocess(content)
371 | 
372 |         for line_number, line in lines_enum:
373 |             try:
374 |                 args_str, opts = self._line_parser(line)
375 |             except OptionParsingError as e:
376 |                 # add offending line
377 |                 msg = f"Invalid requirement: {line}\n{e.msg}"
378 |                 raise RequirementsFileParseError(msg)
379 | 
380 |             yield ParsedLine(
381 |                 filename,
382 |                 line_number,
383 |                 args_str,
384 |                 opts,
385 |                 constraint,
386 |             )
387 | 
388 | 
389 | def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser:
390 |     def parse_line(line: str) -> Tuple[str, Values]:
391 |         # Build new parser for each line since it accumulates appendable
392 |         # options.
393 |         parser = build_parser()
394 |         defaults = parser.get_default_values()
395 |         defaults.index_url = None
396 |         if finder:
397 |             defaults.format_control = finder.format_control
398 | 
399 |         args_str, options_str = break_args_options(line)
400 | 
401 |         try:
402 |             options = shlex.split(options_str)
403 |         except ValueError as e:
404 |             raise OptionParsingError(f"Could not split options: {options_str}") from e
405 | 
406 |         opts, _ = parser.parse_args(options, defaults)
407 | 
408 |         return args_str, opts
409 | 
410 |     return parse_line
411 | 
412 | 
413 | def break_args_options(line: str) -> Tuple[str, str]:
414 |     """Break up the line into an args and options string.  We only want to shlex
415 |     (and then optparse) the options, not the args.  args can contain markers
416 |     which are corrupted by shlex.
417 |     """
418 |     tokens = line.split(" ")
419 |     args = []
420 |     options = tokens[:]
421 |     for token in tokens:
422 |         if token.startswith("-") or token.startswith("--"):
423 |             break
424 |         else:
425 |             args.append(token)
426 |             options.pop(0)
427 |     return " ".join(args), " ".join(options)
428 | 
429 | 
430 | class OptionParsingError(Exception):
431 |     def __init__(self, msg: str) -> None:
432 |         self.msg = msg
433 | 
434 | 
435 | def build_parser() -> optparse.OptionParser:
436 |     """
437 |     Return a parser for parsing requirement lines
438 |     """
439 |     parser = optparse.OptionParser(add_help_option=False)
440 | 
441 |     option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ
442 |     for option_factory in option_factories:
443 |         option = option_factory()
444 |         parser.add_option(option)
445 | 
446 |     # By default optparse sys.exits on parsing errors. We want to wrap
447 |     # that in our own exception.
448 |     def parser_exit(self: Any, msg: str) -> "NoReturn":
449 |         raise OptionParsingError(msg)
450 | 
451 |     # NOTE: mypy disallows assigning to a method
452 |     #       https://github.com/python/mypy/issues/2427
453 |     parser.exit = parser_exit  # type: ignore
454 | 
455 |     return parser
456 | 
457 | 
458 | def join_lines(lines_enum: ReqFileLines) -> ReqFileLines:
459 |     """Joins a line ending in '\' with the previous line (except when following
460 |     comments).  The joined line takes on the index of the first line.
461 |     """
462 |     primary_line_number = None
463 |     new_line: List[str] = []
464 |     for line_number, line in lines_enum:
465 |         if not line.endswith("\\") or COMMENT_RE.match(line):
466 |             if COMMENT_RE.match(line):
467 |                 # this ensures comments are always matched later
468 |                 line = " " + line
469 |             if new_line:
470 |                 new_line.append(line)
471 |                 assert primary_line_number is not None
472 |                 yield primary_line_number, "".join(new_line)
473 |                 new_line = []
474 |             else:
475 |                 yield line_number, line
476 |         else:
477 |             if not new_line:
478 |                 primary_line_number = line_number
479 |             new_line.append(line.strip("\\"))
480 | 
481 |     # last line contains \
482 |     if new_line:
483 |         assert primary_line_number is not None
484 |         yield primary_line_number, "".join(new_line)
485 | 
486 |     # TODO: handle space after '\'.
487 | 
488 | 
489 | def ignore_comments(lines_enum: ReqFileLines) -> ReqFileLines:
490 |     """
491 |     Strips comments and filter empty lines.
492 |     """
493 |     for line_number, line in lines_enum:
494 |         line = COMMENT_RE.sub("", line)
495 |         line = line.strip()
496 |         if line:
497 |             yield line_number, line
498 | 
499 | 
500 | def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines:
501 |     """Replace all environment variables that can be retrieved via `os.getenv`.
502 | 
503 |     The only allowed format for environment variables defined in the
504 |     requirement file is `${MY_VARIABLE_1}` to ensure two things:
505 | 
506 |     1. Strings that contain a `$` aren't accidentally (partially) expanded.
507 |     2. Ensure consistency across platforms for requirement files.
508 | 
509 |     These points are the result of a discussion on the `github pull
510 |     request #3514 <https://github.com/pypa/pip/pull/3514>`_.
511 | 
512 |     Valid characters in variable names follow the `POSIX standard
513 |     <http://pubs.opengroup.org/onlinepubs/9699919799/>`_ and are limited
514 |     to uppercase letter, digits and the `_` (underscore).
515 |     """
516 |     for line_number, line in lines_enum:
517 |         for env_var, var_name in ENV_VAR_RE.findall(line):
518 |             value = os.getenv(var_name)
519 |             if not value:
520 |                 continue
521 | 
522 |             line = line.replace(env_var, value)
523 | 
524 |         yield line_number, line
525 | 
526 | 
527 | def get_file_content(url: str, session: "PipSession") -> Tuple[str, str]:
528 |     """Gets the content of a file; it may be a filename, file: URL, or
529 |     http: URL.  Returns (location, content).  Content is unicode.
530 |     Respects # -*- coding: declarations on the retrieved files.
531 | 
532 |     :param url:         File path or url.
533 |     :param session:     PipSession instance.
534 |     """
535 |     scheme = urllib.parse.urlsplit(url).scheme
536 |     # Pip has special support for file:// URLs (LocalFSAdapter).
537 |     if scheme in ["http", "https", "file"]:
538 |         # Delay importing heavy network modules until absolutely necessary.
539 |         from pip._internal.network.utils import raise_for_status
540 | 
541 |         resp = session.get(url)
542 |         raise_for_status(resp)
543 |         return resp.url, resp.text
544 | 
545 |     # Assume this is a bare path.
546 |     try:
547 |         with open(url, "rb") as f:
548 |             content = auto_decode(f.read())
549 |     except OSError as exc:
550 |         raise InstallationError(f"Could not open requirements file: {exc}")
551 |     return url, content
552 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/lxml/doctestcompare.py:
--------------------------------------------------------------------------------

```python
  1 | """
  2 | lxml-based doctest output comparison.
  3 | 
  4 | Note: normally, you should just import the `lxml.usedoctest` and
  5 | `lxml.html.usedoctest` modules from within a doctest, instead of this
  6 | one::
  7 | 
  8 |     >>> import lxml.usedoctest # for XML output
  9 | 
 10 |     >>> import lxml.html.usedoctest # for HTML output
 11 | 
 12 | To use this module directly, you must call ``lxmldoctest.install()``,
 13 | which will cause doctest to use this in all subsequent calls.
 14 | 
 15 | This changes the way output is checked and comparisons are made for
 16 | XML or HTML-like content.
 17 | 
 18 | XML or HTML content is noticed because the example starts with ``<``
 19 | (it's HTML if it starts with ``<html``).  You can also use the
 20 | ``PARSE_HTML`` and ``PARSE_XML`` flags to force parsing.
 21 | 
 22 | Some rough wildcard-like things are allowed.  Whitespace is generally
 23 | ignored (except in attributes).  In text (attributes and text in the
 24 | body) you can use ``...`` as a wildcard.  In an example it also
 25 | matches any trailing tags in the element, though it does not match
 26 | leading tags.  You may create a tag ``<any>`` or include an ``any``
 27 | attribute in the tag.  An ``any`` tag matches any tag, while the
 28 | attribute matches any and all attributes.
 29 | 
 30 | When a match fails, the reformatted example and gotten text is
 31 | displayed (indented), and a rough diff-like output is given.  Anything
 32 | marked with ``+`` is in the output but wasn't supposed to be, and
 33 | similarly ``-`` means its in the example but wasn't in the output.
 34 | 
 35 | You can disable parsing on one line with ``# doctest:+NOPARSE_MARKUP``
 36 | """
 37 | 
 38 | from lxml import etree
 39 | import sys
 40 | import re
 41 | import doctest
 42 | try:
 43 |     from html import escape as html_escape
 44 | except ImportError:
 45 |     from cgi import escape as html_escape
 46 | 
 47 | __all__ = ['PARSE_HTML', 'PARSE_XML', 'NOPARSE_MARKUP', 'LXMLOutputChecker',
 48 |            'LHTMLOutputChecker', 'install', 'temp_install']
 49 | 
 50 | PARSE_HTML = doctest.register_optionflag('PARSE_HTML')
 51 | PARSE_XML = doctest.register_optionflag('PARSE_XML')
 52 | NOPARSE_MARKUP = doctest.register_optionflag('NOPARSE_MARKUP')
 53 | 
 54 | OutputChecker = doctest.OutputChecker
 55 | 
 56 | def strip(v):
 57 |     if v is None:
 58 |         return None
 59 |     else:
 60 |         return v.strip()
 61 | 
 62 | def norm_whitespace(v):
 63 |     return _norm_whitespace_re.sub(' ', v)
 64 | 
 65 | _html_parser = etree.HTMLParser(recover=False, remove_blank_text=True)
 66 | 
 67 | def html_fromstring(html):
 68 |     return etree.fromstring(html, _html_parser)
 69 | 
 70 | # We use this to distinguish repr()s from elements:
 71 | _repr_re = re.compile(r'^<[^>]+ (at|object) ')
 72 | _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
 73 | 
 74 | class LXMLOutputChecker(OutputChecker):
 75 | 
 76 |     empty_tags = (
 77 |         'param', 'img', 'area', 'br', 'basefont', 'input',
 78 |         'base', 'meta', 'link', 'col')
 79 | 
 80 |     def get_default_parser(self):
 81 |         return etree.XML
 82 | 
 83 |     def check_output(self, want, got, optionflags):
 84 |         alt_self = getattr(self, '_temp_override_self', None)
 85 |         if alt_self is not None:
 86 |             super_method = self._temp_call_super_check_output
 87 |             self = alt_self
 88 |         else:
 89 |             super_method = OutputChecker.check_output
 90 |         parser = self.get_parser(want, got, optionflags)
 91 |         if not parser:
 92 |             return super_method(
 93 |                 self, want, got, optionflags)
 94 |         try:
 95 |             want_doc = parser(want)
 96 |         except etree.XMLSyntaxError:
 97 |             return False
 98 |         try:
 99 |             got_doc = parser(got)
100 |         except etree.XMLSyntaxError:
101 |             return False
102 |         return self.compare_docs(want_doc, got_doc)
103 | 
104 |     def get_parser(self, want, got, optionflags):
105 |         parser = None
106 |         if NOPARSE_MARKUP & optionflags:
107 |             return None
108 |         if PARSE_HTML & optionflags:
109 |             parser = html_fromstring
110 |         elif PARSE_XML & optionflags:
111 |             parser = etree.XML
112 |         elif (want.strip().lower().startswith('<html')
113 |               and got.strip().startswith('<html')):
114 |             parser = html_fromstring
115 |         elif (self._looks_like_markup(want)
116 |               and self._looks_like_markup(got)):
117 |             parser = self.get_default_parser()
118 |         return parser
119 | 
120 |     def _looks_like_markup(self, s):
121 |         s = s.strip()
122 |         return (s.startswith('<')
123 |                 and not _repr_re.search(s))
124 | 
125 |     def compare_docs(self, want, got):
126 |         if not self.tag_compare(want.tag, got.tag):
127 |             return False
128 |         if not self.text_compare(want.text, got.text, True):
129 |             return False
130 |         if not self.text_compare(want.tail, got.tail, True):
131 |             return False
132 |         if 'any' not in want.attrib:
133 |             want_keys = sorted(want.attrib.keys())
134 |             got_keys = sorted(got.attrib.keys())
135 |             if want_keys != got_keys:
136 |                 return False
137 |             for key in want_keys:
138 |                 if not self.text_compare(want.attrib[key], got.attrib[key], False):
139 |                     return False
140 |         if want.text != '...' or len(want):
141 |             want_children = list(want)
142 |             got_children = list(got)
143 |             while want_children or got_children:
144 |                 if not want_children or not got_children:
145 |                     return False
146 |                 want_first = want_children.pop(0)
147 |                 got_first = got_children.pop(0)
148 |                 if not self.compare_docs(want_first, got_first):
149 |                     return False
150 |                 if not got_children and want_first.tail == '...':
151 |                     break
152 |         return True
153 | 
154 |     def text_compare(self, want, got, strip):
155 |         want = want or ''
156 |         got = got or ''
157 |         if strip:
158 |             want = norm_whitespace(want).strip()
159 |             got = norm_whitespace(got).strip()
160 |         want = '^%s$' % re.escape(want)
161 |         want = want.replace(r'\.\.\.', '.*')
162 |         if re.search(want, got):
163 |             return True
164 |         else:
165 |             return False
166 | 
167 |     def tag_compare(self, want, got):
168 |         if want == 'any':
169 |             return True
170 |         if (not isinstance(want, (str, bytes))
171 |                 or not isinstance(got, (str, bytes))):
172 |             return want == got
173 |         want = want or ''
174 |         got = got or ''
175 |         if want.startswith('{...}'):
176 |             # Ellipsis on the namespace
177 |             return want.split('}')[-1] == got.split('}')[-1]
178 |         else:
179 |             return want == got
180 | 
181 |     def output_difference(self, example, got, optionflags):
182 |         want = example.want
183 |         parser = self.get_parser(want, got, optionflags)
184 |         errors = []
185 |         if parser is not None:
186 |             try:
187 |                 want_doc = parser(want)
188 |             except etree.XMLSyntaxError:
189 |                 e = sys.exc_info()[1]
190 |                 errors.append('In example: %s' % e)
191 |             try:
192 |                 got_doc = parser(got)
193 |             except etree.XMLSyntaxError:
194 |                 e = sys.exc_info()[1]
195 |                 errors.append('In actual output: %s' % e)
196 |         if parser is None or errors:
197 |             value = OutputChecker.output_difference(
198 |                 self, example, got, optionflags)
199 |             if errors:
200 |                 errors.append(value)
201 |                 return '\n'.join(errors)
202 |             else:
203 |                 return value
204 |         html = parser is html_fromstring
205 |         diff_parts = ['Expected:',
206 |                       self.format_doc(want_doc, html, 2),
207 |                       'Got:',
208 |                       self.format_doc(got_doc, html, 2),
209 |                       'Diff:',
210 |                       self.collect_diff(want_doc, got_doc, html, 2)]
211 |         return '\n'.join(diff_parts)
212 | 
213 |     def html_empty_tag(self, el, html=True):
214 |         if not html:
215 |             return False
216 |         if el.tag not in self.empty_tags:
217 |             return False
218 |         if el.text or len(el):
219 |             # This shouldn't happen (contents in an empty tag)
220 |             return False
221 |         return True
222 | 
223 |     def format_doc(self, doc, html, indent, prefix=''):
224 |         parts = []
225 |         if not len(doc):
226 |             # No children...
227 |             parts.append(' '*indent)
228 |             parts.append(prefix)
229 |             parts.append(self.format_tag(doc))
230 |             if not self.html_empty_tag(doc, html):
231 |                 if strip(doc.text):
232 |                     parts.append(self.format_text(doc.text))
233 |                 parts.append(self.format_end_tag(doc))
234 |             if strip(doc.tail):
235 |                 parts.append(self.format_text(doc.tail))
236 |             parts.append('\n')
237 |             return ''.join(parts)
238 |         parts.append(' '*indent)
239 |         parts.append(prefix)
240 |         parts.append(self.format_tag(doc))
241 |         if not self.html_empty_tag(doc, html):
242 |             parts.append('\n')
243 |             if strip(doc.text):
244 |                 parts.append(' '*indent)
245 |                 parts.append(self.format_text(doc.text))
246 |                 parts.append('\n')
247 |             for el in doc:
248 |                 parts.append(self.format_doc(el, html, indent+2))
249 |             parts.append(' '*indent)
250 |             parts.append(self.format_end_tag(doc))
251 |             parts.append('\n')
252 |         if strip(doc.tail):
253 |             parts.append(' '*indent)
254 |             parts.append(self.format_text(doc.tail))
255 |             parts.append('\n')
256 |         return ''.join(parts)
257 | 
258 |     def format_text(self, text, strip=True):
259 |         if text is None:
260 |             return ''
261 |         if strip:
262 |             text = text.strip()
263 |         return html_escape(text, 1)
264 | 
265 |     def format_tag(self, el):
266 |         attrs = []
267 |         if isinstance(el, etree.CommentBase):
268 |             # FIXME: probably PIs should be handled specially too?
269 |             return '<!--'
270 |         for name, value in sorted(el.attrib.items()):
271 |             attrs.append('%s="%s"' % (name, self.format_text(value, False)))
272 |         if not attrs:
273 |             return '<%s>' % el.tag
274 |         return '<%s %s>' % (el.tag, ' '.join(attrs))
275 |     
276 |     def format_end_tag(self, el):
277 |         if isinstance(el, etree.CommentBase):
278 |             # FIXME: probably PIs should be handled specially too?
279 |             return '-->'
280 |         return '</%s>' % el.tag
281 | 
282 |     def collect_diff(self, want, got, html, indent):
283 |         parts = []
284 |         if not len(want) and not len(got):
285 |             parts.append(' '*indent)
286 |             parts.append(self.collect_diff_tag(want, got))
287 |             if not self.html_empty_tag(got, html):
288 |                 parts.append(self.collect_diff_text(want.text, got.text))
289 |                 parts.append(self.collect_diff_end_tag(want, got))
290 |             parts.append(self.collect_diff_text(want.tail, got.tail))
291 |             parts.append('\n')
292 |             return ''.join(parts)
293 |         parts.append(' '*indent)
294 |         parts.append(self.collect_diff_tag(want, got))
295 |         parts.append('\n')
296 |         if strip(want.text) or strip(got.text):
297 |             parts.append(' '*indent)
298 |             parts.append(self.collect_diff_text(want.text, got.text))
299 |             parts.append('\n')
300 |         want_children = list(want)
301 |         got_children = list(got)
302 |         while want_children or got_children:
303 |             if not want_children:
304 |                 parts.append(self.format_doc(got_children.pop(0), html, indent+2, '+'))
305 |                 continue
306 |             if not got_children:
307 |                 parts.append(self.format_doc(want_children.pop(0), html, indent+2, '-'))
308 |                 continue
309 |             parts.append(self.collect_diff(
310 |                 want_children.pop(0), got_children.pop(0), html, indent+2))
311 |         parts.append(' '*indent)
312 |         parts.append(self.collect_diff_end_tag(want, got))
313 |         parts.append('\n')
314 |         if strip(want.tail) or strip(got.tail):
315 |             parts.append(' '*indent)
316 |             parts.append(self.collect_diff_text(want.tail, got.tail))
317 |             parts.append('\n')
318 |         return ''.join(parts)
319 | 
320 |     def collect_diff_tag(self, want, got):
321 |         if not self.tag_compare(want.tag, got.tag):
322 |             tag = '%s (got: %s)' % (want.tag, got.tag)
323 |         else:
324 |             tag = got.tag
325 |         attrs = []
326 |         any = want.tag == 'any' or 'any' in want.attrib
327 |         for name, value in sorted(got.attrib.items()):
328 |             if name not in want.attrib and not any:
329 |                 attrs.append('+%s="%s"' % (name, self.format_text(value, False)))
330 |             else:
331 |                 if name in want.attrib:
332 |                     text = self.collect_diff_text(want.attrib[name], value, False)
333 |                 else:
334 |                     text = self.format_text(value, False)
335 |                 attrs.append('%s="%s"' % (name, text))
336 |         if not any:
337 |             for name, value in sorted(want.attrib.items()):
338 |                 if name in got.attrib:
339 |                     continue
340 |                 attrs.append('-%s="%s"' % (name, self.format_text(value, False)))
341 |         if attrs:
342 |             tag = '<%s %s>' % (tag, ' '.join(attrs))
343 |         else:
344 |             tag = '<%s>' % tag
345 |         return tag
346 | 
347 |     def collect_diff_end_tag(self, want, got):
348 |         if want.tag != got.tag:
349 |             tag = '%s (got: %s)' % (want.tag, got.tag)
350 |         else:
351 |             tag = got.tag
352 |         return '</%s>' % tag
353 | 
354 |     def collect_diff_text(self, want, got, strip=True):
355 |         if self.text_compare(want, got, strip):
356 |             if not got:
357 |                 return ''
358 |             return self.format_text(got, strip)
359 |         text = '%s (got: %s)' % (want, got)
360 |         return self.format_text(text, strip)
361 | 
362 | class LHTMLOutputChecker(LXMLOutputChecker):
363 |     def get_default_parser(self):
364 |         return html_fromstring
365 |     
366 | def install(html=False):
367 |     """
368 |     Install doctestcompare for all future doctests.
369 | 
370 |     If html is true, then by default the HTML parser will be used;
371 |     otherwise the XML parser is used.
372 |     """
373 |     if html:
374 |         doctest.OutputChecker = LHTMLOutputChecker
375 |     else:
376 |         doctest.OutputChecker = LXMLOutputChecker
377 | 
378 | def temp_install(html=False, del_module=None):
379 |     """
380 |     Use this *inside* a doctest to enable this checker for this
381 |     doctest only.
382 | 
383 |     If html is true, then by default the HTML parser will be used;
384 |     otherwise the XML parser is used.
385 |     """
386 |     if html:
387 |         Checker = LHTMLOutputChecker
388 |     else:
389 |         Checker = LXMLOutputChecker
390 |     frame = _find_doctest_frame()
391 |     dt_self = frame.f_locals['self']
392 |     checker = Checker()
393 |     old_checker = dt_self._checker
394 |     dt_self._checker = checker
395 |     # The unfortunate thing is that there is a local variable 'check'
396 |     # in the function that runs the doctests, that is a bound method
397 |     # into the output checker.  We have to update that.  We can't
398 |     # modify the frame, so we have to modify the object in place.  The
399 |     # only way to do this is to actually change the func_code
400 |     # attribute of the method.  We change it, and then wait for
401 |     # __record_outcome to be run, which signals the end of the __run
402 |     # method, at which point we restore the previous check_output
403 |     # implementation.
404 |     check_func = frame.f_locals['check'].__func__
405 |     checker_check_func = checker.check_output.__func__
406 |     # Because we can't patch up func_globals, this is the only global
407 |     # in check_output that we care about:
408 |     doctest.etree = etree
409 |     _RestoreChecker(dt_self, old_checker, checker,
410 |                     check_func, checker_check_func,
411 |                     del_module)
412 | 
413 | class _RestoreChecker:
414 |     def __init__(self, dt_self, old_checker, new_checker, check_func, clone_func,
415 |                  del_module):
416 |         self.dt_self = dt_self
417 |         self.checker = old_checker
418 |         self.checker._temp_call_super_check_output = self.call_super
419 |         self.checker._temp_override_self = new_checker
420 |         self.check_func = check_func
421 |         self.clone_func = clone_func
422 |         self.del_module = del_module
423 |         self.install_clone()
424 |         self.install_dt_self()
425 |     def install_clone(self):
426 |         self.func_code = self.check_func.__code__
427 |         self.func_globals = self.check_func.__globals__
428 |         self.check_func.__code__ = self.clone_func.__code__
429 |     def uninstall_clone(self):
430 |         self.check_func.__code__ = self.func_code
431 |     def install_dt_self(self):
432 |         self.prev_func = self.dt_self._DocTestRunner__record_outcome
433 |         self.dt_self._DocTestRunner__record_outcome = self
434 |     def uninstall_dt_self(self):
435 |         self.dt_self._DocTestRunner__record_outcome = self.prev_func
436 |     def uninstall_module(self):
437 |         if self.del_module:
438 |             import sys
439 |             del sys.modules[self.del_module]
440 |             if '.' in self.del_module:
441 |                 package, module = self.del_module.rsplit('.', 1)
442 |                 package_mod = sys.modules[package]
443 |                 delattr(package_mod, module)
444 |     def __call__(self, *args, **kw):
445 |         self.uninstall_clone()
446 |         self.uninstall_dt_self()
447 |         del self.checker._temp_override_self
448 |         del self.checker._temp_call_super_check_output
449 |         result = self.prev_func(*args, **kw)
450 |         self.uninstall_module()
451 |         return result
452 |     def call_super(self, *args, **kw):
453 |         self.uninstall_clone()
454 |         try:
455 |             return self.check_func(*args, **kw)
456 |         finally:
457 |             self.install_clone()
458 |             
459 | def _find_doctest_frame():
460 |     import sys
461 |     frame = sys._getframe(1)
462 |     while frame:
463 |         l = frame.f_locals
464 |         if 'BOOM' in l:
465 |             # Sign of doctest
466 |             return frame
467 |         frame = frame.f_back
468 |     raise LookupError(
469 |         "Could not find doctest (only use this function *inside* a doctest)")
470 |     
471 | __test__ = {
472 |     'basic': '''
473 |     >>> temp_install()
474 |     >>> print """<xml a="1" b="2">stuff</xml>"""
475 |     <xml b="2" a="1">...</xml>
476 |     >>> print """<xml xmlns="http://example.com"><tag   attr="bar"   /></xml>"""
477 |     <xml xmlns="...">
478 |       <tag attr="..." />
479 |     </xml>
480 |     >>> print """<xml>blahblahblah<foo /></xml>""" # doctest: +NOPARSE_MARKUP, +ELLIPSIS
481 |     <xml>...foo /></xml>
482 |     '''}
483 | 
484 | if __name__ == '__main__':
485 |     import doctest
486 |     doctest.testmod()
487 |     
488 |     
489 | 
```

--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py:
--------------------------------------------------------------------------------

```python
  1 | import contextlib
  2 | import ssl
  3 | import typing
  4 | from ctypes import WinDLL  # type: ignore
  5 | from ctypes import WinError  # type: ignore
  6 | from ctypes import (
  7 |     POINTER,
  8 |     Structure,
  9 |     c_char_p,
 10 |     c_ulong,
 11 |     c_void_p,
 12 |     c_wchar_p,
 13 |     cast,
 14 |     create_unicode_buffer,
 15 |     pointer,
 16 |     sizeof,
 17 | )
 18 | from ctypes.wintypes import (
 19 |     BOOL,
 20 |     DWORD,
 21 |     HANDLE,
 22 |     LONG,
 23 |     LPCSTR,
 24 |     LPCVOID,
 25 |     LPCWSTR,
 26 |     LPFILETIME,
 27 |     LPSTR,
 28 |     LPWSTR,
 29 | )
 30 | from typing import TYPE_CHECKING, Any
 31 | 
 32 | from ._ssl_constants import _set_ssl_context_verify_mode
 33 | 
 34 | HCERTCHAINENGINE = HANDLE
 35 | HCERTSTORE = HANDLE
 36 | HCRYPTPROV_LEGACY = HANDLE
 37 | 
 38 | 
 39 | class CERT_CONTEXT(Structure):
 40 |     _fields_ = (
 41 |         ("dwCertEncodingType", DWORD),
 42 |         ("pbCertEncoded", c_void_p),
 43 |         ("cbCertEncoded", DWORD),
 44 |         ("pCertInfo", c_void_p),
 45 |         ("hCertStore", HCERTSTORE),
 46 |     )
 47 | 
 48 | 
 49 | PCERT_CONTEXT = POINTER(CERT_CONTEXT)
 50 | PCCERT_CONTEXT = POINTER(PCERT_CONTEXT)
 51 | 
 52 | 
 53 | class CERT_ENHKEY_USAGE(Structure):
 54 |     _fields_ = (
 55 |         ("cUsageIdentifier", DWORD),
 56 |         ("rgpszUsageIdentifier", POINTER(LPSTR)),
 57 |     )
 58 | 
 59 | 
 60 | PCERT_ENHKEY_USAGE = POINTER(CERT_ENHKEY_USAGE)
 61 | 
 62 | 
 63 | class CERT_USAGE_MATCH(Structure):
 64 |     _fields_ = (
 65 |         ("dwType", DWORD),
 66 |         ("Usage", CERT_ENHKEY_USAGE),
 67 |     )
 68 | 
 69 | 
 70 | class CERT_CHAIN_PARA(Structure):
 71 |     _fields_ = (
 72 |         ("cbSize", DWORD),
 73 |         ("RequestedUsage", CERT_USAGE_MATCH),
 74 |         ("RequestedIssuancePolicy", CERT_USAGE_MATCH),
 75 |         ("dwUrlRetrievalTimeout", DWORD),
 76 |         ("fCheckRevocationFreshnessTime", BOOL),
 77 |         ("dwRevocationFreshnessTime", DWORD),
 78 |         ("pftCacheResync", LPFILETIME),
 79 |         ("pStrongSignPara", c_void_p),
 80 |         ("dwStrongSignFlags", DWORD),
 81 |     )
 82 | 
 83 | 
 84 | if TYPE_CHECKING:
 85 |     PCERT_CHAIN_PARA = pointer[CERT_CHAIN_PARA]  # type: ignore[misc]
 86 | else:
 87 |     PCERT_CHAIN_PARA = POINTER(CERT_CHAIN_PARA)
 88 | 
 89 | 
 90 | class CERT_TRUST_STATUS(Structure):
 91 |     _fields_ = (
 92 |         ("dwErrorStatus", DWORD),
 93 |         ("dwInfoStatus", DWORD),
 94 |     )
 95 | 
 96 | 
 97 | class CERT_CHAIN_ELEMENT(Structure):
 98 |     _fields_ = (
 99 |         ("cbSize", DWORD),
100 |         ("pCertContext", PCERT_CONTEXT),
101 |         ("TrustStatus", CERT_TRUST_STATUS),
102 |         ("pRevocationInfo", c_void_p),
103 |         ("pIssuanceUsage", PCERT_ENHKEY_USAGE),
104 |         ("pApplicationUsage", PCERT_ENHKEY_USAGE),
105 |         ("pwszExtendedErrorInfo", LPCWSTR),
106 |     )
107 | 
108 | 
109 | PCERT_CHAIN_ELEMENT = POINTER(CERT_CHAIN_ELEMENT)
110 | 
111 | 
112 | class CERT_SIMPLE_CHAIN(Structure):
113 |     _fields_ = (
114 |         ("cbSize", DWORD),
115 |         ("TrustStatus", CERT_TRUST_STATUS),
116 |         ("cElement", DWORD),
117 |         ("rgpElement", POINTER(PCERT_CHAIN_ELEMENT)),
118 |         ("pTrustListInfo", c_void_p),
119 |         ("fHasRevocationFreshnessTime", BOOL),
120 |         ("dwRevocationFreshnessTime", DWORD),
121 |     )
122 | 
123 | 
124 | PCERT_SIMPLE_CHAIN = POINTER(CERT_SIMPLE_CHAIN)
125 | 
126 | 
127 | class CERT_CHAIN_CONTEXT(Structure):
128 |     _fields_ = (
129 |         ("cbSize", DWORD),
130 |         ("TrustStatus", CERT_TRUST_STATUS),
131 |         ("cChain", DWORD),
132 |         ("rgpChain", POINTER(PCERT_SIMPLE_CHAIN)),
133 |         ("cLowerQualityChainContext", DWORD),
134 |         ("rgpLowerQualityChainContext", c_void_p),
135 |         ("fHasRevocationFreshnessTime", BOOL),
136 |         ("dwRevocationFreshnessTime", DWORD),
137 |     )
138 | 
139 | 
140 | PCERT_CHAIN_CONTEXT = POINTER(CERT_CHAIN_CONTEXT)
141 | PCCERT_CHAIN_CONTEXT = POINTER(PCERT_CHAIN_CONTEXT)
142 | 
143 | 
144 | class SSL_EXTRA_CERT_CHAIN_POLICY_PARA(Structure):
145 |     _fields_ = (
146 |         ("cbSize", DWORD),
147 |         ("dwAuthType", DWORD),
148 |         ("fdwChecks", DWORD),
149 |         ("pwszServerName", LPCWSTR),
150 |     )
151 | 
152 | 
153 | class CERT_CHAIN_POLICY_PARA(Structure):
154 |     _fields_ = (
155 |         ("cbSize", DWORD),
156 |         ("dwFlags", DWORD),
157 |         ("pvExtraPolicyPara", c_void_p),
158 |     )
159 | 
160 | 
161 | PCERT_CHAIN_POLICY_PARA = POINTER(CERT_CHAIN_POLICY_PARA)
162 | 
163 | 
164 | class CERT_CHAIN_POLICY_STATUS(Structure):
165 |     _fields_ = (
166 |         ("cbSize", DWORD),
167 |         ("dwError", DWORD),
168 |         ("lChainIndex", LONG),
169 |         ("lElementIndex", LONG),
170 |         ("pvExtraPolicyStatus", c_void_p),
171 |     )
172 | 
173 | 
174 | PCERT_CHAIN_POLICY_STATUS = POINTER(CERT_CHAIN_POLICY_STATUS)
175 | 
176 | 
177 | class CERT_CHAIN_ENGINE_CONFIG(Structure):
178 |     _fields_ = (
179 |         ("cbSize", DWORD),
180 |         ("hRestrictedRoot", HCERTSTORE),
181 |         ("hRestrictedTrust", HCERTSTORE),
182 |         ("hRestrictedOther", HCERTSTORE),
183 |         ("cAdditionalStore", DWORD),
184 |         ("rghAdditionalStore", c_void_p),
185 |         ("dwFlags", DWORD),
186 |         ("dwUrlRetrievalTimeout", DWORD),
187 |         ("MaximumCachedCertificates", DWORD),
188 |         ("CycleDetectionModulus", DWORD),
189 |         ("hExclusiveRoot", HCERTSTORE),
190 |         ("hExclusiveTrustedPeople", HCERTSTORE),
191 |         ("dwExclusiveFlags", DWORD),
192 |     )
193 | 
194 | 
195 | PCERT_CHAIN_ENGINE_CONFIG = POINTER(CERT_CHAIN_ENGINE_CONFIG)
196 | PHCERTCHAINENGINE = POINTER(HCERTCHAINENGINE)
197 | 
198 | X509_ASN_ENCODING = 0x00000001
199 | PKCS_7_ASN_ENCODING = 0x00010000
200 | CERT_STORE_PROV_MEMORY = b"Memory"
201 | CERT_STORE_ADD_USE_EXISTING = 2
202 | USAGE_MATCH_TYPE_OR = 1
203 | OID_PKIX_KP_SERVER_AUTH = c_char_p(b"1.3.6.1.5.5.7.3.1")
204 | CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000
205 | CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000
206 | CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS = 0x00000007
207 | CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008
208 | CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010
209 | CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040
210 | CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020
211 | CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080
212 | CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = 0x00000F00
213 | CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG = 0x00008000
214 | CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG = 0x00004000
215 | AUTHTYPE_SERVER = 2
216 | CERT_CHAIN_POLICY_SSL = 4
217 | FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
218 | FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
219 | 
220 | # Flags to set for SSLContext.verify_mode=CERT_NONE
221 | CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS = (
222 |     CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS
223 |     | CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG
224 |     | CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG
225 |     | CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG
226 |     | CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG
227 |     | CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG
228 |     | CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS
229 |     | CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG
230 |     | CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG
231 | )
232 | 
233 | wincrypt = WinDLL("crypt32.dll")
234 | kernel32 = WinDLL("kernel32.dll")
235 | 
236 | 
237 | def _handle_win_error(result: bool, _: Any, args: Any) -> Any:
238 |     if not result:
239 |         # Note, actually raises OSError after calling GetLastError and FormatMessage
240 |         raise WinError()
241 |     return args
242 | 
243 | 
244 | CertCreateCertificateChainEngine = wincrypt.CertCreateCertificateChainEngine
245 | CertCreateCertificateChainEngine.argtypes = (
246 |     PCERT_CHAIN_ENGINE_CONFIG,
247 |     PHCERTCHAINENGINE,
248 | )
249 | CertCreateCertificateChainEngine.errcheck = _handle_win_error
250 | 
251 | CertOpenStore = wincrypt.CertOpenStore
252 | CertOpenStore.argtypes = (LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, c_void_p)
253 | CertOpenStore.restype = HCERTSTORE
254 | CertOpenStore.errcheck = _handle_win_error
255 | 
256 | CertAddEncodedCertificateToStore = wincrypt.CertAddEncodedCertificateToStore
257 | CertAddEncodedCertificateToStore.argtypes = (
258 |     HCERTSTORE,
259 |     DWORD,
260 |     c_char_p,
261 |     DWORD,
262 |     DWORD,
263 |     PCCERT_CONTEXT,
264 | )
265 | CertAddEncodedCertificateToStore.restype = BOOL
266 | 
267 | CertCreateCertificateContext = wincrypt.CertCreateCertificateContext
268 | CertCreateCertificateContext.argtypes = (DWORD, c_char_p, DWORD)
269 | CertCreateCertificateContext.restype = PCERT_CONTEXT
270 | CertCreateCertificateContext.errcheck = _handle_win_error
271 | 
272 | CertGetCertificateChain = wincrypt.CertGetCertificateChain
273 | CertGetCertificateChain.argtypes = (
274 |     HCERTCHAINENGINE,
275 |     PCERT_CONTEXT,
276 |     LPFILETIME,
277 |     HCERTSTORE,
278 |     PCERT_CHAIN_PARA,
279 |     DWORD,
280 |     c_void_p,
281 |     PCCERT_CHAIN_CONTEXT,
282 | )
283 | CertGetCertificateChain.restype = BOOL
284 | CertGetCertificateChain.errcheck = _handle_win_error
285 | 
286 | CertVerifyCertificateChainPolicy = wincrypt.CertVerifyCertificateChainPolicy
287 | CertVerifyCertificateChainPolicy.argtypes = (
288 |     c_ulong,
289 |     PCERT_CHAIN_CONTEXT,
290 |     PCERT_CHAIN_POLICY_PARA,
291 |     PCERT_CHAIN_POLICY_STATUS,
292 | )
293 | CertVerifyCertificateChainPolicy.restype = BOOL
294 | 
295 | CertCloseStore = wincrypt.CertCloseStore
296 | CertCloseStore.argtypes = (HCERTSTORE, DWORD)
297 | CertCloseStore.restype = BOOL
298 | CertCloseStore.errcheck = _handle_win_error
299 | 
300 | CertFreeCertificateChain = wincrypt.CertFreeCertificateChain
301 | CertFreeCertificateChain.argtypes = (PCERT_CHAIN_CONTEXT,)
302 | 
303 | CertFreeCertificateContext = wincrypt.CertFreeCertificateContext
304 | CertFreeCertificateContext.argtypes = (PCERT_CONTEXT,)
305 | 
306 | CertFreeCertificateChainEngine = wincrypt.CertFreeCertificateChainEngine
307 | CertFreeCertificateChainEngine.argtypes = (HCERTCHAINENGINE,)
308 | 
309 | FormatMessageW = kernel32.FormatMessageW
310 | FormatMessageW.argtypes = (
311 |     DWORD,
312 |     LPCVOID,
313 |     DWORD,
314 |     DWORD,
315 |     LPWSTR,
316 |     DWORD,
317 |     c_void_p,
318 | )
319 | FormatMessageW.restype = DWORD
320 | 
321 | 
322 | def _verify_peercerts_impl(
323 |     ssl_context: ssl.SSLContext,
324 |     cert_chain: list[bytes],
325 |     server_hostname: str | None = None,
326 | ) -> None:
327 |     """Verify the cert_chain from the server using Windows APIs."""
328 | 
329 |     # If the peer didn't send any certificates then
330 |     # we can't do verification. Raise an error.
331 |     if not cert_chain:
332 |         raise ssl.SSLCertVerificationError("Peer sent no certificates to verify")
333 | 
334 |     pCertContext = None
335 |     hIntermediateCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None)
336 |     try:
337 |         # Add intermediate certs to an in-memory cert store
338 |         for cert_bytes in cert_chain[1:]:
339 |             CertAddEncodedCertificateToStore(
340 |                 hIntermediateCertStore,
341 |                 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
342 |                 cert_bytes,
343 |                 len(cert_bytes),
344 |                 CERT_STORE_ADD_USE_EXISTING,
345 |                 None,
346 |             )
347 | 
348 |         # Cert context for leaf cert
349 |         leaf_cert = cert_chain[0]
350 |         pCertContext = CertCreateCertificateContext(
351 |             X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, leaf_cert, len(leaf_cert)
352 |         )
353 | 
354 |         # Chain params to match certs for serverAuth extended usage
355 |         cert_enhkey_usage = CERT_ENHKEY_USAGE()
356 |         cert_enhkey_usage.cUsageIdentifier = 1
357 |         cert_enhkey_usage.rgpszUsageIdentifier = (c_char_p * 1)(OID_PKIX_KP_SERVER_AUTH)
358 |         cert_usage_match = CERT_USAGE_MATCH()
359 |         cert_usage_match.Usage = cert_enhkey_usage
360 |         chain_params = CERT_CHAIN_PARA()
361 |         chain_params.RequestedUsage = cert_usage_match
362 |         chain_params.cbSize = sizeof(chain_params)
363 |         pChainPara = pointer(chain_params)
364 | 
365 |         if ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_CHAIN:
366 |             chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN
367 |         elif ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_LEAF:
368 |             chain_flags = CERT_CHAIN_REVOCATION_CHECK_END_CERT
369 |         else:
370 |             chain_flags = 0
371 | 
372 |         try:
373 |             # First attempt to verify using the default Windows system trust roots
374 |             # (default chain engine).
375 |             _get_and_verify_cert_chain(
376 |                 ssl_context,
377 |                 None,
378 |                 hIntermediateCertStore,
379 |                 pCertContext,
380 |                 pChainPara,
381 |                 server_hostname,
382 |                 chain_flags=chain_flags,
383 |             )
384 |         except ssl.SSLCertVerificationError as e:
385 |             # If that fails but custom CA certs have been added
386 |             # to the SSLContext using load_verify_locations,
387 |             # try verifying using a custom chain engine
388 |             # that trusts the custom CA certs.
389 |             custom_ca_certs: list[bytes] | None = ssl_context.get_ca_certs(
390 |                 binary_form=True
391 |             )
392 |             if custom_ca_certs:
393 |                 try:
394 |                     _verify_using_custom_ca_certs(
395 |                         ssl_context,
396 |                         custom_ca_certs,
397 |                         hIntermediateCertStore,
398 |                         pCertContext,
399 |                         pChainPara,
400 |                         server_hostname,
401 |                         chain_flags=chain_flags,
402 |                     )
403 |                 # Raise the original error, not the new error.
404 |                 except ssl.SSLCertVerificationError:
405 |                     raise e from None
406 |             else:
407 |                 raise
408 |     finally:
409 |         CertCloseStore(hIntermediateCertStore, 0)
410 |         if pCertContext:
411 |             CertFreeCertificateContext(pCertContext)
412 | 
413 | 
414 | def _get_and_verify_cert_chain(
415 |     ssl_context: ssl.SSLContext,
416 |     hChainEngine: HCERTCHAINENGINE | None,
417 |     hIntermediateCertStore: HCERTSTORE,
418 |     pPeerCertContext: c_void_p,
419 |     pChainPara: PCERT_CHAIN_PARA,  # type: ignore[valid-type]
420 |     server_hostname: str | None,
421 |     chain_flags: int,
422 | ) -> None:
423 |     ppChainContext = None
424 |     try:
425 |         # Get cert chain
426 |         ppChainContext = pointer(PCERT_CHAIN_CONTEXT())
427 |         CertGetCertificateChain(
428 |             hChainEngine,  # chain engine
429 |             pPeerCertContext,  # leaf cert context
430 |             None,  # current system time
431 |             hIntermediateCertStore,  # additional in-memory cert store
432 |             pChainPara,  # chain-building parameters
433 |             chain_flags,
434 |             None,  # reserved
435 |             ppChainContext,  # the resulting chain context
436 |         )
437 |         pChainContext = ppChainContext.contents
438 | 
439 |         # Verify cert chain
440 |         ssl_extra_cert_chain_policy_para = SSL_EXTRA_CERT_CHAIN_POLICY_PARA()
441 |         ssl_extra_cert_chain_policy_para.cbSize = sizeof(
442 |             ssl_extra_cert_chain_policy_para
443 |         )
444 |         ssl_extra_cert_chain_policy_para.dwAuthType = AUTHTYPE_SERVER
445 |         ssl_extra_cert_chain_policy_para.fdwChecks = 0
446 |         if server_hostname:
447 |             ssl_extra_cert_chain_policy_para.pwszServerName = c_wchar_p(server_hostname)
448 | 
449 |         chain_policy = CERT_CHAIN_POLICY_PARA()
450 |         chain_policy.pvExtraPolicyPara = cast(
451 |             pointer(ssl_extra_cert_chain_policy_para), c_void_p
452 |         )
453 |         if ssl_context.verify_mode == ssl.CERT_NONE:
454 |             chain_policy.dwFlags |= CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS
455 |         if not ssl_context.check_hostname:
456 |             chain_policy.dwFlags |= CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG
457 |         chain_policy.cbSize = sizeof(chain_policy)
458 | 
459 |         pPolicyPara = pointer(chain_policy)
460 |         policy_status = CERT_CHAIN_POLICY_STATUS()
461 |         policy_status.cbSize = sizeof(policy_status)
462 |         pPolicyStatus = pointer(policy_status)
463 |         CertVerifyCertificateChainPolicy(
464 |             CERT_CHAIN_POLICY_SSL,
465 |             pChainContext,
466 |             pPolicyPara,
467 |             pPolicyStatus,
468 |         )
469 | 
470 |         # Check status
471 |         error_code = policy_status.dwError
472 |         if error_code:
473 |             # Try getting a human readable message for an error code.
474 |             error_message_buf = create_unicode_buffer(1024)
475 |             error_message_chars = FormatMessageW(
476 |                 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
477 |                 None,
478 |                 error_code,
479 |                 0,
480 |                 error_message_buf,
481 |                 sizeof(error_message_buf),
482 |                 None,
483 |             )
484 | 
485 |             # See if we received a message for the error,
486 |             # otherwise we use a generic error with the
487 |             # error code and hope that it's search-able.
488 |             if error_message_chars <= 0:
489 |                 error_message = f"Certificate chain policy error {error_code:#x} [{policy_status.lElementIndex}]"
490 |             else:
491 |                 error_message = error_message_buf.value.strip()
492 | 
493 |             err = ssl.SSLCertVerificationError(error_message)
494 |             err.verify_message = error_message
495 |             err.verify_code = error_code
496 |             raise err from None
497 |     finally:
498 |         if ppChainContext:
499 |             CertFreeCertificateChain(ppChainContext.contents)
500 | 
501 | 
502 | def _verify_using_custom_ca_certs(
503 |     ssl_context: ssl.SSLContext,
504 |     custom_ca_certs: list[bytes],
505 |     hIntermediateCertStore: HCERTSTORE,
506 |     pPeerCertContext: c_void_p,
507 |     pChainPara: PCERT_CHAIN_PARA,  # type: ignore[valid-type]
508 |     server_hostname: str | None,
509 |     chain_flags: int,
510 | ) -> None:
511 |     hChainEngine = None
512 |     hRootCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None)
513 |     try:
514 |         # Add custom CA certs to an in-memory cert store
515 |         for cert_bytes in custom_ca_certs:
516 |             CertAddEncodedCertificateToStore(
517 |                 hRootCertStore,
518 |                 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
519 |                 cert_bytes,
520 |                 len(cert_bytes),
521 |                 CERT_STORE_ADD_USE_EXISTING,
522 |                 None,
523 |             )
524 | 
525 |         # Create a custom cert chain engine which exclusively trusts
526 |         # certs from our hRootCertStore
527 |         cert_chain_engine_config = CERT_CHAIN_ENGINE_CONFIG()
528 |         cert_chain_engine_config.cbSize = sizeof(cert_chain_engine_config)
529 |         cert_chain_engine_config.hExclusiveRoot = hRootCertStore
530 |         pConfig = pointer(cert_chain_engine_config)
531 |         phChainEngine = pointer(HCERTCHAINENGINE())
532 |         CertCreateCertificateChainEngine(
533 |             pConfig,
534 |             phChainEngine,
535 |         )
536 |         hChainEngine = phChainEngine.contents
537 | 
538 |         # Get and verify a cert chain using the custom chain engine
539 |         _get_and_verify_cert_chain(
540 |             ssl_context,
541 |             hChainEngine,
542 |             hIntermediateCertStore,
543 |             pPeerCertContext,
544 |             pChainPara,
545 |             server_hostname,
546 |             chain_flags,
547 |         )
548 |     finally:
549 |         if hChainEngine:
550 |             CertFreeCertificateChainEngine(hChainEngine)
551 |         CertCloseStore(hRootCertStore, 0)
552 | 
553 | 
554 | @contextlib.contextmanager
555 | def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]:
556 |     check_hostname = ctx.check_hostname
557 |     verify_mode = ctx.verify_mode
558 |     ctx.check_hostname = False
559 |     _set_ssl_context_verify_mode(ctx, ssl.CERT_NONE)
560 |     try:
561 |         yield
562 |     finally:
563 |         ctx.check_hostname = check_hostname
564 |         _set_ssl_context_verify_mode(ctx, verify_mode)
565 | 
```
Page 60/168FirstPrevNextLast