This is page 50 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/jinja2/bccache.py:
--------------------------------------------------------------------------------
```python
1 | """The optional bytecode cache system. This is useful if you have very
2 | complex template situations and the compilation of all those templates
3 | slows down your application too much.
4 |
5 | Situations where this is useful are often forking web applications that
6 | are initialized on the first request.
7 | """
8 |
9 | import errno
10 | import fnmatch
11 | import marshal
12 | import os
13 | import pickle
14 | import stat
15 | import sys
16 | import tempfile
17 | import typing as t
18 | from hashlib import sha1
19 | from io import BytesIO
20 | from types import CodeType
21 |
22 | if t.TYPE_CHECKING:
23 | import typing_extensions as te
24 |
25 | from .environment import Environment
26 |
27 | class _MemcachedClient(te.Protocol):
28 | def get(self, key: str) -> bytes: ...
29 |
30 | def set(
31 | self, key: str, value: bytes, timeout: t.Optional[int] = None
32 | ) -> None: ...
33 |
34 |
35 | bc_version = 5
36 | # Magic bytes to identify Jinja bytecode cache files. Contains the
37 | # Python major and minor version to avoid loading incompatible bytecode
38 | # if a project upgrades its Python version.
39 | bc_magic = (
40 | b"j2"
41 | + pickle.dumps(bc_version, 2)
42 | + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2)
43 | )
44 |
45 |
46 | class Bucket:
47 | """Buckets are used to store the bytecode for one template. It's created
48 | and initialized by the bytecode cache and passed to the loading functions.
49 |
50 | The buckets get an internal checksum from the cache assigned and use this
51 | to automatically reject outdated cache material. Individual bytecode
52 | cache subclasses don't have to care about cache invalidation.
53 | """
54 |
55 | def __init__(self, environment: "Environment", key: str, checksum: str) -> None:
56 | self.environment = environment
57 | self.key = key
58 | self.checksum = checksum
59 | self.reset()
60 |
61 | def reset(self) -> None:
62 | """Resets the bucket (unloads the bytecode)."""
63 | self.code: t.Optional[CodeType] = None
64 |
65 | def load_bytecode(self, f: t.BinaryIO) -> None:
66 | """Loads bytecode from a file or file like object."""
67 | # make sure the magic header is correct
68 | magic = f.read(len(bc_magic))
69 | if magic != bc_magic:
70 | self.reset()
71 | return
72 | # the source code of the file changed, we need to reload
73 | checksum = pickle.load(f)
74 | if self.checksum != checksum:
75 | self.reset()
76 | return
77 | # if marshal_load fails then we need to reload
78 | try:
79 | self.code = marshal.load(f)
80 | except (EOFError, ValueError, TypeError):
81 | self.reset()
82 | return
83 |
84 | def write_bytecode(self, f: t.IO[bytes]) -> None:
85 | """Dump the bytecode into the file or file like object passed."""
86 | if self.code is None:
87 | raise TypeError("can't write empty bucket")
88 | f.write(bc_magic)
89 | pickle.dump(self.checksum, f, 2)
90 | marshal.dump(self.code, f)
91 |
92 | def bytecode_from_string(self, string: bytes) -> None:
93 | """Load bytecode from bytes."""
94 | self.load_bytecode(BytesIO(string))
95 |
96 | def bytecode_to_string(self) -> bytes:
97 | """Return the bytecode as bytes."""
98 | out = BytesIO()
99 | self.write_bytecode(out)
100 | return out.getvalue()
101 |
102 |
103 | class BytecodeCache:
104 | """To implement your own bytecode cache you have to subclass this class
105 | and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of
106 | these methods are passed a :class:`~jinja2.bccache.Bucket`.
107 |
108 | A very basic bytecode cache that saves the bytecode on the file system::
109 |
110 | from os import path
111 |
112 | class MyCache(BytecodeCache):
113 |
114 | def __init__(self, directory):
115 | self.directory = directory
116 |
117 | def load_bytecode(self, bucket):
118 | filename = path.join(self.directory, bucket.key)
119 | if path.exists(filename):
120 | with open(filename, 'rb') as f:
121 | bucket.load_bytecode(f)
122 |
123 | def dump_bytecode(self, bucket):
124 | filename = path.join(self.directory, bucket.key)
125 | with open(filename, 'wb') as f:
126 | bucket.write_bytecode(f)
127 |
128 | A more advanced version of a filesystem based bytecode cache is part of
129 | Jinja.
130 | """
131 |
132 | def load_bytecode(self, bucket: Bucket) -> None:
133 | """Subclasses have to override this method to load bytecode into a
134 | bucket. If they are not able to find code in the cache for the
135 | bucket, it must not do anything.
136 | """
137 | raise NotImplementedError()
138 |
139 | def dump_bytecode(self, bucket: Bucket) -> None:
140 | """Subclasses have to override this method to write the bytecode
141 | from a bucket back to the cache. If it unable to do so it must not
142 | fail silently but raise an exception.
143 | """
144 | raise NotImplementedError()
145 |
146 | def clear(self) -> None:
147 | """Clears the cache. This method is not used by Jinja but should be
148 | implemented to allow applications to clear the bytecode cache used
149 | by a particular environment.
150 | """
151 |
152 | def get_cache_key(
153 | self, name: str, filename: t.Optional[t.Union[str]] = None
154 | ) -> str:
155 | """Returns the unique hash key for this template name."""
156 | hash = sha1(name.encode("utf-8"))
157 |
158 | if filename is not None:
159 | hash.update(f"|{filename}".encode())
160 |
161 | return hash.hexdigest()
162 |
163 | def get_source_checksum(self, source: str) -> str:
164 | """Returns a checksum for the source."""
165 | return sha1(source.encode("utf-8")).hexdigest()
166 |
167 | def get_bucket(
168 | self,
169 | environment: "Environment",
170 | name: str,
171 | filename: t.Optional[str],
172 | source: str,
173 | ) -> Bucket:
174 | """Return a cache bucket for the given template. All arguments are
175 | mandatory but filename may be `None`.
176 | """
177 | key = self.get_cache_key(name, filename)
178 | checksum = self.get_source_checksum(source)
179 | bucket = Bucket(environment, key, checksum)
180 | self.load_bytecode(bucket)
181 | return bucket
182 |
183 | def set_bucket(self, bucket: Bucket) -> None:
184 | """Put the bucket into the cache."""
185 | self.dump_bytecode(bucket)
186 |
187 |
188 | class FileSystemBytecodeCache(BytecodeCache):
189 | """A bytecode cache that stores bytecode on the filesystem. It accepts
190 | two arguments: The directory where the cache items are stored and a
191 | pattern string that is used to build the filename.
192 |
193 | If no directory is specified a default cache directory is selected. On
194 | Windows the user's temp directory is used, on UNIX systems a directory
195 | is created for the user in the system temp directory.
196 |
197 | The pattern can be used to have multiple separate caches operate on the
198 | same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s``
199 | is replaced with the cache key.
200 |
201 | >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')
202 |
203 | This bytecode cache supports clearing of the cache using the clear method.
204 | """
205 |
206 | def __init__(
207 | self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache"
208 | ) -> None:
209 | if directory is None:
210 | directory = self._get_default_cache_dir()
211 | self.directory = directory
212 | self.pattern = pattern
213 |
214 | def _get_default_cache_dir(self) -> str:
215 | def _unsafe_dir() -> "te.NoReturn":
216 | raise RuntimeError(
217 | "Cannot determine safe temp directory. You "
218 | "need to explicitly provide one."
219 | )
220 |
221 | tmpdir = tempfile.gettempdir()
222 |
223 | # On windows the temporary directory is used specific unless
224 | # explicitly forced otherwise. We can just use that.
225 | if os.name == "nt":
226 | return tmpdir
227 | if not hasattr(os, "getuid"):
228 | _unsafe_dir()
229 |
230 | dirname = f"_jinja2-cache-{os.getuid()}"
231 | actual_dir = os.path.join(tmpdir, dirname)
232 |
233 | try:
234 | os.mkdir(actual_dir, stat.S_IRWXU)
235 | except OSError as e:
236 | if e.errno != errno.EEXIST:
237 | raise
238 | try:
239 | os.chmod(actual_dir, stat.S_IRWXU)
240 | actual_dir_stat = os.lstat(actual_dir)
241 | if (
242 | actual_dir_stat.st_uid != os.getuid()
243 | or not stat.S_ISDIR(actual_dir_stat.st_mode)
244 | or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU
245 | ):
246 | _unsafe_dir()
247 | except OSError as e:
248 | if e.errno != errno.EEXIST:
249 | raise
250 |
251 | actual_dir_stat = os.lstat(actual_dir)
252 | if (
253 | actual_dir_stat.st_uid != os.getuid()
254 | or not stat.S_ISDIR(actual_dir_stat.st_mode)
255 | or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU
256 | ):
257 | _unsafe_dir()
258 |
259 | return actual_dir
260 |
261 | def _get_cache_filename(self, bucket: Bucket) -> str:
262 | return os.path.join(self.directory, self.pattern % (bucket.key,))
263 |
264 | def load_bytecode(self, bucket: Bucket) -> None:
265 | filename = self._get_cache_filename(bucket)
266 |
267 | # Don't test for existence before opening the file, since the
268 | # file could disappear after the test before the open.
269 | try:
270 | f = open(filename, "rb")
271 | except (FileNotFoundError, IsADirectoryError, PermissionError):
272 | # PermissionError can occur on Windows when an operation is
273 | # in progress, such as calling clear().
274 | return
275 |
276 | with f:
277 | bucket.load_bytecode(f)
278 |
279 | def dump_bytecode(self, bucket: Bucket) -> None:
280 | # Write to a temporary file, then rename to the real name after
281 | # writing. This avoids another process reading the file before
282 | # it is fully written.
283 | name = self._get_cache_filename(bucket)
284 | f = tempfile.NamedTemporaryFile(
285 | mode="wb",
286 | dir=os.path.dirname(name),
287 | prefix=os.path.basename(name),
288 | suffix=".tmp",
289 | delete=False,
290 | )
291 |
292 | def remove_silent() -> None:
293 | try:
294 | os.remove(f.name)
295 | except OSError:
296 | # Another process may have called clear(). On Windows,
297 | # another program may be holding the file open.
298 | pass
299 |
300 | try:
301 | with f:
302 | bucket.write_bytecode(f)
303 | except BaseException:
304 | remove_silent()
305 | raise
306 |
307 | try:
308 | os.replace(f.name, name)
309 | except OSError:
310 | # Another process may have called clear(). On Windows,
311 | # another program may be holding the file open.
312 | remove_silent()
313 | except BaseException:
314 | remove_silent()
315 | raise
316 |
317 | def clear(self) -> None:
318 | # imported lazily here because google app-engine doesn't support
319 | # write access on the file system and the function does not exist
320 | # normally.
321 | from os import remove
322 |
323 | files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",))
324 | for filename in files:
325 | try:
326 | remove(os.path.join(self.directory, filename))
327 | except OSError:
328 | pass
329 |
330 |
331 | class MemcachedBytecodeCache(BytecodeCache):
332 | """This class implements a bytecode cache that uses a memcache cache for
333 | storing the information. It does not enforce a specific memcache library
334 | (tummy's memcache or cmemcache) but will accept any class that provides
335 | the minimal interface required.
336 |
337 | Libraries compatible with this class:
338 |
339 | - `cachelib <https://github.com/pallets/cachelib>`_
340 | - `python-memcached <https://pypi.org/project/python-memcached/>`_
341 |
342 | (Unfortunately the django cache interface is not compatible because it
343 | does not support storing binary data, only text. You can however pass
344 | the underlying cache client to the bytecode cache which is available
345 | as `django.core.cache.cache._client`.)
346 |
347 | The minimal interface for the client passed to the constructor is this:
348 |
349 | .. class:: MinimalClientInterface
350 |
351 | .. method:: set(key, value[, timeout])
352 |
353 | Stores the bytecode in the cache. `value` is a string and
354 | `timeout` the timeout of the key. If timeout is not provided
355 | a default timeout or no timeout should be assumed, if it's
356 | provided it's an integer with the number of seconds the cache
357 | item should exist.
358 |
359 | .. method:: get(key)
360 |
361 | Returns the value for the cache key. If the item does not
362 | exist in the cache the return value must be `None`.
363 |
364 | The other arguments to the constructor are the prefix for all keys that
365 | is added before the actual cache key and the timeout for the bytecode in
366 | the cache system. We recommend a high (or no) timeout.
367 |
368 | This bytecode cache does not support clearing of used items in the cache.
369 | The clear method is a no-operation function.
370 |
371 | .. versionadded:: 2.7
372 | Added support for ignoring memcache errors through the
373 | `ignore_memcache_errors` parameter.
374 | """
375 |
376 | def __init__(
377 | self,
378 | client: "_MemcachedClient",
379 | prefix: str = "jinja2/bytecode/",
380 | timeout: t.Optional[int] = None,
381 | ignore_memcache_errors: bool = True,
382 | ):
383 | self.client = client
384 | self.prefix = prefix
385 | self.timeout = timeout
386 | self.ignore_memcache_errors = ignore_memcache_errors
387 |
388 | def load_bytecode(self, bucket: Bucket) -> None:
389 | try:
390 | code = self.client.get(self.prefix + bucket.key)
391 | except Exception:
392 | if not self.ignore_memcache_errors:
393 | raise
394 | else:
395 | bucket.bytecode_from_string(code)
396 |
397 | def dump_bytecode(self, bucket: Bucket) -> None:
398 | key = self.prefix + bucket.key
399 | value = bucket.bytecode_to_string()
400 |
401 | try:
402 | if self.timeout is not None:
403 | self.client.set(key, value, self.timeout)
404 | else:
405 | self.client.set(key, value)
406 | except Exception:
407 | if not self.ignore_memcache_errors:
408 | raise
409 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/fetch.py:
--------------------------------------------------------------------------------
```python
1 | """
2 | Support for streaming http requests in emscripten.
3 |
4 | A few caveats -
5 |
6 | Firstly, you can't do streaming http in the main UI thread, because atomics.wait isn't allowed.
7 | Streaming only works if you're running pyodide in a web worker.
8 |
9 | Secondly, this uses an extra web worker and SharedArrayBuffer to do the asynchronous fetch
10 | operation, so it requires that you have crossOriginIsolation enabled, by serving over https
11 | (or from localhost) with the two headers below set:
12 |
13 | Cross-Origin-Opener-Policy: same-origin
14 | Cross-Origin-Embedder-Policy: require-corp
15 |
16 | You can tell if cross origin isolation is successfully enabled by looking at the global crossOriginIsolated variable in
17 | javascript console. If it isn't, streaming requests will fallback to XMLHttpRequest, i.e. getting the whole
18 | request into a buffer and then returning it. it shows a warning in the javascript console in this case.
19 |
20 | Finally, the webworker which does the streaming fetch is created on initial import, but will only be started once
21 | control is returned to javascript. Call `await wait_for_streaming_ready()` to wait for streaming fetch.
22 |
23 | NB: in this code, there are a lot of javascript objects. They are named js_*
24 | to make it clear what type of object they are.
25 | """
26 | from __future__ import annotations
27 |
28 | import io
29 | import json
30 | from email.parser import Parser
31 | from importlib.resources import files
32 | from typing import TYPE_CHECKING, Any
33 |
34 | import js # type: ignore[import-not-found]
35 | from pyodide.ffi import ( # type: ignore[import-not-found]
36 | JsArray,
37 | JsException,
38 | JsProxy,
39 | to_js,
40 | )
41 |
42 | if TYPE_CHECKING:
43 | from typing_extensions import Buffer
44 |
45 | from .request import EmscriptenRequest
46 | from .response import EmscriptenResponse
47 |
48 | """
49 | There are some headers that trigger unintended CORS preflight requests.
50 | See also https://github.com/koenvo/pyodide-http/issues/22
51 | """
52 | HEADERS_TO_IGNORE = ("user-agent",)
53 |
54 | SUCCESS_HEADER = -1
55 | SUCCESS_EOF = -2
56 | ERROR_TIMEOUT = -3
57 | ERROR_EXCEPTION = -4
58 |
59 | _STREAMING_WORKER_CODE = (
60 | files(__package__)
61 | .joinpath("emscripten_fetch_worker.js")
62 | .read_text(encoding="utf-8")
63 | )
64 |
65 |
66 | class _RequestError(Exception):
67 | def __init__(
68 | self,
69 | message: str | None = None,
70 | *,
71 | request: EmscriptenRequest | None = None,
72 | response: EmscriptenResponse | None = None,
73 | ):
74 | self.request = request
75 | self.response = response
76 | self.message = message
77 | super().__init__(self.message)
78 |
79 |
80 | class _StreamingError(_RequestError):
81 | pass
82 |
83 |
84 | class _TimeoutError(_RequestError):
85 | pass
86 |
87 |
88 | def _obj_from_dict(dict_val: dict[str, Any]) -> JsProxy:
89 | return to_js(dict_val, dict_converter=js.Object.fromEntries)
90 |
91 |
92 | class _ReadStream(io.RawIOBase):
93 | def __init__(
94 | self,
95 | int_buffer: JsArray,
96 | byte_buffer: JsArray,
97 | timeout: float,
98 | worker: JsProxy,
99 | connection_id: int,
100 | request: EmscriptenRequest,
101 | ):
102 | self.int_buffer = int_buffer
103 | self.byte_buffer = byte_buffer
104 | self.read_pos = 0
105 | self.read_len = 0
106 | self.connection_id = connection_id
107 | self.worker = worker
108 | self.timeout = int(1000 * timeout) if timeout > 0 else None
109 | self.is_live = True
110 | self._is_closed = False
111 | self.request: EmscriptenRequest | None = request
112 |
113 | def __del__(self) -> None:
114 | self.close()
115 |
116 | # this is compatible with _base_connection
117 | def is_closed(self) -> bool:
118 | return self._is_closed
119 |
120 | # for compatibility with RawIOBase
121 | @property
122 | def closed(self) -> bool:
123 | return self.is_closed()
124 |
125 | def close(self) -> None:
126 | if not self.is_closed():
127 | self.read_len = 0
128 | self.read_pos = 0
129 | self.int_buffer = None
130 | self.byte_buffer = None
131 | self._is_closed = True
132 | self.request = None
133 | if self.is_live:
134 | self.worker.postMessage(_obj_from_dict({"close": self.connection_id}))
135 | self.is_live = False
136 | super().close()
137 |
138 | def readable(self) -> bool:
139 | return True
140 |
141 | def writable(self) -> bool:
142 | return False
143 |
144 | def seekable(self) -> bool:
145 | return False
146 |
147 | def readinto(self, byte_obj: Buffer) -> int:
148 | if not self.int_buffer:
149 | raise _StreamingError(
150 | "No buffer for stream in _ReadStream.readinto",
151 | request=self.request,
152 | response=None,
153 | )
154 | if self.read_len == 0:
155 | # wait for the worker to send something
156 | js.Atomics.store(self.int_buffer, 0, ERROR_TIMEOUT)
157 | self.worker.postMessage(_obj_from_dict({"getMore": self.connection_id}))
158 | if (
159 | js.Atomics.wait(self.int_buffer, 0, ERROR_TIMEOUT, self.timeout)
160 | == "timed-out"
161 | ):
162 | raise _TimeoutError
163 | data_len = self.int_buffer[0]
164 | if data_len > 0:
165 | self.read_len = data_len
166 | self.read_pos = 0
167 | elif data_len == ERROR_EXCEPTION:
168 | string_len = self.int_buffer[1]
169 | # decode the error string
170 | js_decoder = js.TextDecoder.new()
171 | json_str = js_decoder.decode(self.byte_buffer.slice(0, string_len))
172 | raise _StreamingError(
173 | f"Exception thrown in fetch: {json_str}",
174 | request=self.request,
175 | response=None,
176 | )
177 | else:
178 | # EOF, free the buffers and return zero
179 | # and free the request
180 | self.is_live = False
181 | self.close()
182 | return 0
183 | # copy from int32array to python bytes
184 | ret_length = min(self.read_len, len(memoryview(byte_obj)))
185 | subarray = self.byte_buffer.subarray(
186 | self.read_pos, self.read_pos + ret_length
187 | ).to_py()
188 | memoryview(byte_obj)[0:ret_length] = subarray
189 | self.read_len -= ret_length
190 | self.read_pos += ret_length
191 | return ret_length
192 |
193 |
194 | class _StreamingFetcher:
195 | def __init__(self) -> None:
196 | # make web-worker and data buffer on startup
197 | self.streaming_ready = False
198 |
199 | js_data_blob = js.Blob.new(
200 | [_STREAMING_WORKER_CODE], _obj_from_dict({"type": "application/javascript"})
201 | )
202 |
203 | def promise_resolver(js_resolve_fn: JsProxy, js_reject_fn: JsProxy) -> None:
204 | def onMsg(e: JsProxy) -> None:
205 | self.streaming_ready = True
206 | js_resolve_fn(e)
207 |
208 | def onErr(e: JsProxy) -> None:
209 | js_reject_fn(e) # Defensive: never happens in ci
210 |
211 | self.js_worker.onmessage = onMsg
212 | self.js_worker.onerror = onErr
213 |
214 | js_data_url = js.URL.createObjectURL(js_data_blob)
215 | self.js_worker = js.globalThis.Worker.new(js_data_url)
216 | self.js_worker_ready_promise = js.globalThis.Promise.new(promise_resolver)
217 |
218 | def send(self, request: EmscriptenRequest) -> EmscriptenResponse:
219 | headers = {
220 | k: v for k, v in request.headers.items() if k not in HEADERS_TO_IGNORE
221 | }
222 |
223 | body = request.body
224 | fetch_data = {"headers": headers, "body": to_js(body), "method": request.method}
225 | # start the request off in the worker
226 | timeout = int(1000 * request.timeout) if request.timeout > 0 else None
227 | js_shared_buffer = js.SharedArrayBuffer.new(1048576)
228 | js_int_buffer = js.Int32Array.new(js_shared_buffer)
229 | js_byte_buffer = js.Uint8Array.new(js_shared_buffer, 8)
230 |
231 | js.Atomics.store(js_int_buffer, 0, ERROR_TIMEOUT)
232 | js.Atomics.notify(js_int_buffer, 0)
233 | js_absolute_url = js.URL.new(request.url, js.location).href
234 | self.js_worker.postMessage(
235 | _obj_from_dict(
236 | {
237 | "buffer": js_shared_buffer,
238 | "url": js_absolute_url,
239 | "fetchParams": fetch_data,
240 | }
241 | )
242 | )
243 | # wait for the worker to send something
244 | js.Atomics.wait(js_int_buffer, 0, ERROR_TIMEOUT, timeout)
245 | if js_int_buffer[0] == ERROR_TIMEOUT:
246 | raise _TimeoutError(
247 | "Timeout connecting to streaming request",
248 | request=request,
249 | response=None,
250 | )
251 | elif js_int_buffer[0] == SUCCESS_HEADER:
252 | # got response
253 | # header length is in second int of intBuffer
254 | string_len = js_int_buffer[1]
255 | # decode the rest to a JSON string
256 | js_decoder = js.TextDecoder.new()
257 | # this does a copy (the slice) because decode can't work on shared array
258 | # for some silly reason
259 | json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len))
260 | # get it as an object
261 | response_obj = json.loads(json_str)
262 | return EmscriptenResponse(
263 | request=request,
264 | status_code=response_obj["status"],
265 | headers=response_obj["headers"],
266 | body=_ReadStream(
267 | js_int_buffer,
268 | js_byte_buffer,
269 | request.timeout,
270 | self.js_worker,
271 | response_obj["connectionID"],
272 | request,
273 | ),
274 | )
275 | elif js_int_buffer[0] == ERROR_EXCEPTION:
276 | string_len = js_int_buffer[1]
277 | # decode the error string
278 | js_decoder = js.TextDecoder.new()
279 | json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len))
280 | raise _StreamingError(
281 | f"Exception thrown in fetch: {json_str}", request=request, response=None
282 | )
283 | else:
284 | raise _StreamingError(
285 | f"Unknown status from worker in fetch: {js_int_buffer[0]}",
286 | request=request,
287 | response=None,
288 | )
289 |
290 |
291 | # check if we are in a worker or not
292 | def is_in_browser_main_thread() -> bool:
293 | return hasattr(js, "window") and hasattr(js, "self") and js.self == js.window
294 |
295 |
296 | def is_cross_origin_isolated() -> bool:
297 | return hasattr(js, "crossOriginIsolated") and js.crossOriginIsolated
298 |
299 |
300 | def is_in_node() -> bool:
301 | return (
302 | hasattr(js, "process")
303 | and hasattr(js.process, "release")
304 | and hasattr(js.process.release, "name")
305 | and js.process.release.name == "node"
306 | )
307 |
308 |
309 | def is_worker_available() -> bool:
310 | return hasattr(js, "Worker") and hasattr(js, "Blob")
311 |
312 |
313 | _fetcher: _StreamingFetcher | None = None
314 |
315 | if is_worker_available() and (
316 | (is_cross_origin_isolated() and not is_in_browser_main_thread())
317 | and (not is_in_node())
318 | ):
319 | _fetcher = _StreamingFetcher()
320 | else:
321 | _fetcher = None
322 |
323 |
324 | def send_streaming_request(request: EmscriptenRequest) -> EmscriptenResponse | None:
325 | if _fetcher and streaming_ready():
326 | return _fetcher.send(request)
327 | else:
328 | _show_streaming_warning()
329 | return None
330 |
331 |
332 | _SHOWN_TIMEOUT_WARNING = False
333 |
334 |
335 | def _show_timeout_warning() -> None:
336 | global _SHOWN_TIMEOUT_WARNING
337 | if not _SHOWN_TIMEOUT_WARNING:
338 | _SHOWN_TIMEOUT_WARNING = True
339 | message = "Warning: Timeout is not available on main browser thread"
340 | js.console.warn(message)
341 |
342 |
343 | _SHOWN_STREAMING_WARNING = False
344 |
345 |
346 | def _show_streaming_warning() -> None:
347 | global _SHOWN_STREAMING_WARNING
348 | if not _SHOWN_STREAMING_WARNING:
349 | _SHOWN_STREAMING_WARNING = True
350 | message = "Can't stream HTTP requests because: \n"
351 | if not is_cross_origin_isolated():
352 | message += " Page is not cross-origin isolated\n"
353 | if is_in_browser_main_thread():
354 | message += " Python is running in main browser thread\n"
355 | if not is_worker_available():
356 | message += " Worker or Blob classes are not available in this environment." # Defensive: this is always False in browsers that we test in
357 | if streaming_ready() is False:
358 | message += """ Streaming fetch worker isn't ready. If you want to be sure that streaming fetch
359 | is working, you need to call: 'await urllib3.contrib.emscripten.fetch.wait_for_streaming_ready()`"""
360 | from js import console
361 |
362 | console.warn(message)
363 |
364 |
365 | def send_request(request: EmscriptenRequest) -> EmscriptenResponse:
366 | try:
367 | js_xhr = js.XMLHttpRequest.new()
368 |
369 | if not is_in_browser_main_thread():
370 | js_xhr.responseType = "arraybuffer"
371 | if request.timeout:
372 | js_xhr.timeout = int(request.timeout * 1000)
373 | else:
374 | js_xhr.overrideMimeType("text/plain; charset=ISO-8859-15")
375 | if request.timeout:
376 | # timeout isn't available on the main thread - show a warning in console
377 | # if it is set
378 | _show_timeout_warning()
379 |
380 | js_xhr.open(request.method, request.url, False)
381 | for name, value in request.headers.items():
382 | if name.lower() not in HEADERS_TO_IGNORE:
383 | js_xhr.setRequestHeader(name, value)
384 |
385 | js_xhr.send(to_js(request.body))
386 |
387 | headers = dict(Parser().parsestr(js_xhr.getAllResponseHeaders()))
388 |
389 | if not is_in_browser_main_thread():
390 | body = js_xhr.response.to_py().tobytes()
391 | else:
392 | body = js_xhr.response.encode("ISO-8859-15")
393 | return EmscriptenResponse(
394 | status_code=js_xhr.status, headers=headers, body=body, request=request
395 | )
396 | except JsException as err:
397 | if err.name == "TimeoutError":
398 | raise _TimeoutError(err.message, request=request)
399 | elif err.name == "NetworkError":
400 | raise _RequestError(err.message, request=request)
401 | else:
402 | # general http error
403 | raise _RequestError(err.message, request=request)
404 |
405 |
406 | def streaming_ready() -> bool | None:
407 | if _fetcher:
408 | return _fetcher.streaming_ready
409 | else:
410 | return None # no fetcher, return None to signify that
411 |
412 |
413 | async def wait_for_streaming_ready() -> bool:
414 | if _fetcher:
415 | await _fetcher.js_worker_ready_promise
416 | return True
417 | else:
418 | return False
419 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py:
--------------------------------------------------------------------------------
```python
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright (C) 2012-2023 Python Software Foundation.
4 | # See LICENSE.txt and CONTRIBUTORS.txt.
5 | #
6 | """
7 | Class representing the list of files in a distribution.
8 |
9 | Equivalent to distutils.filelist, but fixes some problems.
10 | """
11 | import fnmatch
12 | import logging
13 | import os
14 | import re
15 | import sys
16 |
17 | from . import DistlibException
18 | from .compat import fsdecode
19 | from .util import convert_path
20 |
21 |
22 | __all__ = ['Manifest']
23 |
24 | logger = logging.getLogger(__name__)
25 |
26 | # a \ followed by some spaces + EOL
27 | _COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M)
28 | _COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S)
29 |
30 | #
31 | # Due to the different results returned by fnmatch.translate, we need
32 | # to do slightly different processing for Python 2.7 and 3.2 ... this needed
33 | # to be brought in for Python 3.6 onwards.
34 | #
35 | _PYTHON_VERSION = sys.version_info[:2]
36 |
37 |
38 | class Manifest(object):
39 | """
40 | A list of files built by exploring the filesystem and filtered by applying various
41 | patterns to what we find there.
42 | """
43 |
44 | def __init__(self, base=None):
45 | """
46 | Initialise an instance.
47 |
48 | :param base: The base directory to explore under.
49 | """
50 | self.base = os.path.abspath(os.path.normpath(base or os.getcwd()))
51 | self.prefix = self.base + os.sep
52 | self.allfiles = None
53 | self.files = set()
54 |
55 | #
56 | # Public API
57 | #
58 |
59 | def findall(self):
60 | """Find all files under the base and set ``allfiles`` to the absolute
61 | pathnames of files found.
62 | """
63 | from stat import S_ISREG, S_ISDIR, S_ISLNK
64 |
65 | self.allfiles = allfiles = []
66 | root = self.base
67 | stack = [root]
68 | pop = stack.pop
69 | push = stack.append
70 |
71 | while stack:
72 | root = pop()
73 | names = os.listdir(root)
74 |
75 | for name in names:
76 | fullname = os.path.join(root, name)
77 |
78 | # Avoid excess stat calls -- just one will do, thank you!
79 | stat = os.stat(fullname)
80 | mode = stat.st_mode
81 | if S_ISREG(mode):
82 | allfiles.append(fsdecode(fullname))
83 | elif S_ISDIR(mode) and not S_ISLNK(mode):
84 | push(fullname)
85 |
86 | def add(self, item):
87 | """
88 | Add a file to the manifest.
89 |
90 | :param item: The pathname to add. This can be relative to the base.
91 | """
92 | if not item.startswith(self.prefix):
93 | item = os.path.join(self.base, item)
94 | self.files.add(os.path.normpath(item))
95 |
96 | def add_many(self, items):
97 | """
98 | Add a list of files to the manifest.
99 |
100 | :param items: The pathnames to add. These can be relative to the base.
101 | """
102 | for item in items:
103 | self.add(item)
104 |
105 | def sorted(self, wantdirs=False):
106 | """
107 | Return sorted files in directory order
108 | """
109 |
110 | def add_dir(dirs, d):
111 | dirs.add(d)
112 | logger.debug('add_dir added %s', d)
113 | if d != self.base:
114 | parent, _ = os.path.split(d)
115 | assert parent not in ('', '/')
116 | add_dir(dirs, parent)
117 |
118 | result = set(self.files) # make a copy!
119 | if wantdirs:
120 | dirs = set()
121 | for f in result:
122 | add_dir(dirs, os.path.dirname(f))
123 | result |= dirs
124 | return [os.path.join(*path_tuple) for path_tuple in
125 | sorted(os.path.split(path) for path in result)]
126 |
127 | def clear(self):
128 | """Clear all collected files."""
129 | self.files = set()
130 | self.allfiles = []
131 |
132 | def process_directive(self, directive):
133 | """
134 | Process a directive which either adds some files from ``allfiles`` to
135 | ``files``, or removes some files from ``files``.
136 |
137 | :param directive: The directive to process. This should be in a format
138 | compatible with distutils ``MANIFEST.in`` files:
139 |
140 | http://docs.python.org/distutils/sourcedist.html#commands
141 | """
142 | # Parse the line: split it up, make sure the right number of words
143 | # is there, and return the relevant words. 'action' is always
144 | # defined: it's the first word of the line. Which of the other
145 | # three are defined depends on the action; it'll be either
146 | # patterns, (dir and patterns), or (dirpattern).
147 | action, patterns, thedir, dirpattern = self._parse_directive(directive)
148 |
149 | # OK, now we know that the action is valid and we have the
150 | # right number of words on the line for that action -- so we
151 | # can proceed with minimal error-checking.
152 | if action == 'include':
153 | for pattern in patterns:
154 | if not self._include_pattern(pattern, anchor=True):
155 | logger.warning('no files found matching %r', pattern)
156 |
157 | elif action == 'exclude':
158 | for pattern in patterns:
159 | self._exclude_pattern(pattern, anchor=True)
160 |
161 | elif action == 'global-include':
162 | for pattern in patterns:
163 | if not self._include_pattern(pattern, anchor=False):
164 | logger.warning('no files found matching %r '
165 | 'anywhere in distribution', pattern)
166 |
167 | elif action == 'global-exclude':
168 | for pattern in patterns:
169 | self._exclude_pattern(pattern, anchor=False)
170 |
171 | elif action == 'recursive-include':
172 | for pattern in patterns:
173 | if not self._include_pattern(pattern, prefix=thedir):
174 | logger.warning('no files found matching %r '
175 | 'under directory %r', pattern, thedir)
176 |
177 | elif action == 'recursive-exclude':
178 | for pattern in patterns:
179 | self._exclude_pattern(pattern, prefix=thedir)
180 |
181 | elif action == 'graft':
182 | if not self._include_pattern(None, prefix=dirpattern):
183 | logger.warning('no directories found matching %r',
184 | dirpattern)
185 |
186 | elif action == 'prune':
187 | if not self._exclude_pattern(None, prefix=dirpattern):
188 | logger.warning('no previously-included directories found '
189 | 'matching %r', dirpattern)
190 | else: # pragma: no cover
191 | # This should never happen, as it should be caught in
192 | # _parse_template_line
193 | raise DistlibException(
194 | 'invalid action %r' % action)
195 |
196 | #
197 | # Private API
198 | #
199 |
200 | def _parse_directive(self, directive):
201 | """
202 | Validate a directive.
203 | :param directive: The directive to validate.
204 | :return: A tuple of action, patterns, thedir, dir_patterns
205 | """
206 | words = directive.split()
207 | if len(words) == 1 and words[0] not in ('include', 'exclude',
208 | 'global-include',
209 | 'global-exclude',
210 | 'recursive-include',
211 | 'recursive-exclude',
212 | 'graft', 'prune'):
213 | # no action given, let's use the default 'include'
214 | words.insert(0, 'include')
215 |
216 | action = words[0]
217 | patterns = thedir = dir_pattern = None
218 |
219 | if action in ('include', 'exclude',
220 | 'global-include', 'global-exclude'):
221 | if len(words) < 2:
222 | raise DistlibException(
223 | '%r expects <pattern1> <pattern2> ...' % action)
224 |
225 | patterns = [convert_path(word) for word in words[1:]]
226 |
227 | elif action in ('recursive-include', 'recursive-exclude'):
228 | if len(words) < 3:
229 | raise DistlibException(
230 | '%r expects <dir> <pattern1> <pattern2> ...' % action)
231 |
232 | thedir = convert_path(words[1])
233 | patterns = [convert_path(word) for word in words[2:]]
234 |
235 | elif action in ('graft', 'prune'):
236 | if len(words) != 2:
237 | raise DistlibException(
238 | '%r expects a single <dir_pattern>' % action)
239 |
240 | dir_pattern = convert_path(words[1])
241 |
242 | else:
243 | raise DistlibException('unknown action %r' % action)
244 |
245 | return action, patterns, thedir, dir_pattern
246 |
247 | def _include_pattern(self, pattern, anchor=True, prefix=None,
248 | is_regex=False):
249 | """Select strings (presumably filenames) from 'self.files' that
250 | match 'pattern', a Unix-style wildcard (glob) pattern.
251 |
252 | Patterns are not quite the same as implemented by the 'fnmatch'
253 | module: '*' and '?' match non-special characters, where "special"
254 | is platform-dependent: slash on Unix; colon, slash, and backslash on
255 | DOS/Windows; and colon on Mac OS.
256 |
257 | If 'anchor' is true (the default), then the pattern match is more
258 | stringent: "*.py" will match "foo.py" but not "foo/bar.py". If
259 | 'anchor' is false, both of these will match.
260 |
261 | If 'prefix' is supplied, then only filenames starting with 'prefix'
262 | (itself a pattern) and ending with 'pattern', with anything in between
263 | them, will match. 'anchor' is ignored in this case.
264 |
265 | If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
266 | 'pattern' is assumed to be either a string containing a regex or a
267 | regex object -- no translation is done, the regex is just compiled
268 | and used as-is.
269 |
270 | Selected strings will be added to self.files.
271 |
272 | Return True if files are found.
273 | """
274 | # XXX docstring lying about what the special chars are?
275 | found = False
276 | pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex)
277 |
278 | # delayed loading of allfiles list
279 | if self.allfiles is None:
280 | self.findall()
281 |
282 | for name in self.allfiles:
283 | if pattern_re.search(name):
284 | self.files.add(name)
285 | found = True
286 | return found
287 |
288 | def _exclude_pattern(self, pattern, anchor=True, prefix=None,
289 | is_regex=False):
290 | """Remove strings (presumably filenames) from 'files' that match
291 | 'pattern'.
292 |
293 | Other parameters are the same as for 'include_pattern()', above.
294 | The list 'self.files' is modified in place. Return True if files are
295 | found.
296 |
297 | This API is public to allow e.g. exclusion of SCM subdirs, e.g. when
298 | packaging source distributions
299 | """
300 | found = False
301 | pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex)
302 | for f in list(self.files):
303 | if pattern_re.search(f):
304 | self.files.remove(f)
305 | found = True
306 | return found
307 |
308 | def _translate_pattern(self, pattern, anchor=True, prefix=None,
309 | is_regex=False):
310 | """Translate a shell-like wildcard pattern to a compiled regular
311 | expression.
312 |
313 | Return the compiled regex. If 'is_regex' true,
314 | then 'pattern' is directly compiled to a regex (if it's a string)
315 | or just returned as-is (assumes it's a regex object).
316 | """
317 | if is_regex:
318 | if isinstance(pattern, str):
319 | return re.compile(pattern)
320 | else:
321 | return pattern
322 |
323 | if _PYTHON_VERSION > (3, 2):
324 | # ditch start and end characters
325 | start, _, end = self._glob_to_re('_').partition('_')
326 |
327 | if pattern:
328 | pattern_re = self._glob_to_re(pattern)
329 | if _PYTHON_VERSION > (3, 2):
330 | assert pattern_re.startswith(start) and pattern_re.endswith(end)
331 | else:
332 | pattern_re = ''
333 |
334 | base = re.escape(os.path.join(self.base, ''))
335 | if prefix is not None:
336 | # ditch end of pattern character
337 | if _PYTHON_VERSION <= (3, 2):
338 | empty_pattern = self._glob_to_re('')
339 | prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)]
340 | else:
341 | prefix_re = self._glob_to_re(prefix)
342 | assert prefix_re.startswith(start) and prefix_re.endswith(end)
343 | prefix_re = prefix_re[len(start): len(prefix_re) - len(end)]
344 | sep = os.sep
345 | if os.sep == '\\':
346 | sep = r'\\'
347 | if _PYTHON_VERSION <= (3, 2):
348 | pattern_re = '^' + base + sep.join((prefix_re,
349 | '.*' + pattern_re))
350 | else:
351 | pattern_re = pattern_re[len(start): len(pattern_re) - len(end)]
352 | pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep,
353 | pattern_re, end)
354 | else: # no prefix -- respect anchor flag
355 | if anchor:
356 | if _PYTHON_VERSION <= (3, 2):
357 | pattern_re = '^' + base + pattern_re
358 | else:
359 | pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):])
360 |
361 | return re.compile(pattern_re)
362 |
363 | def _glob_to_re(self, pattern):
364 | """Translate a shell-like glob pattern to a regular expression.
365 |
366 | Return a string containing the regex. Differs from
367 | 'fnmatch.translate()' in that '*' does not match "special characters"
368 | (which are platform-specific).
369 | """
370 | pattern_re = fnmatch.translate(pattern)
371 |
372 | # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
373 | # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
374 | # and by extension they shouldn't match such "special characters" under
375 | # any OS. So change all non-escaped dots in the RE to match any
376 | # character except the special characters (currently: just os.sep).
377 | sep = os.sep
378 | if os.sep == '\\':
379 | # we're using a regex to manipulate a regex, so we need
380 | # to escape the backslash twice
381 | sep = r'\\\\'
382 | escaped = r'\1[^%s]' % sep
383 | pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re)
384 | return pattern_re
385 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/lxml/includes/etree_defs.h:
--------------------------------------------------------------------------------
```
1 | #ifndef HAS_ETREE_DEFS_H
2 | #define HAS_ETREE_DEFS_H
3 |
4 | /* quick check for Python/libxml2/libxslt devel setup */
5 | #include "Python.h"
6 | #ifndef PY_VERSION_HEX
7 | # error the development package of Python (header files etc.) is not installed correctly
8 | #elif PY_VERSION_HEX < 0x03060000
9 | # error this version of lxml requires Python 3.6 or later
10 | #endif
11 |
12 | #include "libxml/xmlversion.h"
13 | #ifndef LIBXML_VERSION
14 | # error the development package of libxml2 (header files etc.) is not installed correctly
15 | #elif LIBXML_VERSION < 20700
16 | # error minimum required version of libxml2 is 2.7.0
17 | #endif
18 |
19 | #include "libxslt/xsltconfig.h"
20 | #ifndef LIBXSLT_VERSION
21 | # error the development package of libxslt (header files etc.) is not installed correctly
22 | #elif LIBXSLT_VERSION < 10123
23 | # error minimum required version of libxslt is 1.1.23
24 | #endif
25 |
26 |
27 | /* v_arg functions */
28 | #define va_int(ap) va_arg(ap, int)
29 | #define va_charptr(ap) va_arg(ap, char *)
30 |
31 | #ifdef PYPY_VERSION
32 | # define IS_PYPY 1
33 | #else
34 | # define IS_PYPY 0
35 | #endif
36 |
37 | /* unused */
38 | #define IS_PYTHON2 0
39 | #define IS_PYTHON3 1
40 | #undef LXML_UNICODE_STRINGS
41 | #define LXML_UNICODE_STRINGS 1
42 |
43 | #if !IS_PYPY
44 | # define PyWeakref_LockObject(obj) (NULL)
45 | #endif
46 |
47 | /* Threading is not currently supported by PyPy */
48 | #if IS_PYPY
49 | # ifndef WITHOUT_THREADING
50 | # define WITHOUT_THREADING
51 | # endif
52 | #endif
53 |
54 | #if IS_PYPY
55 | # ifndef PyUnicode_FromFormat
56 | # define PyUnicode_FromFormat PyString_FromFormat
57 | # endif
58 | # if !defined(PyBytes_FromFormat)
59 | # ifdef PyString_FromFormat
60 | # define PyBytes_FromFormat PyString_FromFormat
61 | # else
62 | #include <stdarg.h>
63 | static PyObject* PyBytes_FromFormat(const char* format, ...) {
64 | PyObject *string;
65 | va_list vargs;
66 | #ifdef HAVE_STDARG_PROTOTYPES
67 | va_start(vargs, format);
68 | #else
69 | va_start(vargs);
70 | #endif
71 | string = PyUnicode_FromFormatV(format, vargs);
72 | va_end(vargs);
73 | if (string && PyUnicode_Check(string)) {
74 | PyObject *bstring = PyUnicode_AsUTF8String(string);
75 | Py_DECREF(string);
76 | string = bstring;
77 | }
78 | if (string && !PyBytes_CheckExact(string)) {
79 | Py_DECREF(string);
80 | string = NULL;
81 | PyErr_SetString(PyExc_TypeError, "String formatting and encoding failed to return bytes object");
82 | }
83 | return string;
84 | }
85 | # endif
86 | # endif
87 | #endif
88 |
89 | #if PY_VERSION_HEX >= 0x030B00A1
90 | /* Python 3.12 doesn't have wstr Unicode strings any more. */
91 | #undef PyUnicode_GET_DATA_SIZE
92 | #define PyUnicode_GET_DATA_SIZE(ustr) (0)
93 | #undef PyUnicode_AS_DATA
94 | #define PyUnicode_AS_DATA(ustr) (NULL)
95 | #undef PyUnicode_IS_READY
96 | #define PyUnicode_IS_READY(ustr) (1)
97 | #endif
98 |
99 | #ifdef WITHOUT_THREADING
100 | # undef PyEval_SaveThread
101 | # define PyEval_SaveThread() (NULL)
102 | # undef PyEval_RestoreThread
103 | # define PyEval_RestoreThread(state) if (state); else {}
104 | # undef PyGILState_Ensure
105 | # define PyGILState_Ensure() (PyGILState_UNLOCKED)
106 | # undef PyGILState_Release
107 | # define PyGILState_Release(state) if (state); else {}
108 | # undef Py_UNBLOCK_THREADS
109 | # define Py_UNBLOCK_THREADS _save = NULL;
110 | # undef Py_BLOCK_THREADS
111 | # define Py_BLOCK_THREADS if (_save); else {}
112 | #endif
113 |
114 | #ifdef WITHOUT_THREADING
115 | # define ENABLE_THREADING 0
116 | #else
117 | # define ENABLE_THREADING 1
118 | #endif
119 |
120 | #if LIBXML_VERSION < 20704
121 | /* FIXME: hack to make new error reporting compile in old libxml2 versions */
122 | # define xmlStructuredErrorContext NULL
123 | # define xmlXIncludeProcessTreeFlagsData(n,o,d) xmlXIncludeProcessTreeFlags(n,o)
124 | #endif
125 |
126 | /* schematron was added in libxml2 2.6.21 */
127 | #ifdef LIBXML_SCHEMATRON_ENABLED
128 | # define ENABLE_SCHEMATRON 1
129 | #else
130 | # define ENABLE_SCHEMATRON 0
131 | # define XML_SCHEMATRON_OUT_QUIET 0
132 | # define XML_SCHEMATRON_OUT_XML 0
133 | # define XML_SCHEMATRON_OUT_ERROR 0
134 | typedef void xmlSchematron;
135 | typedef void xmlSchematronParserCtxt;
136 | typedef void xmlSchematronValidCtxt;
137 | # define xmlSchematronNewDocParserCtxt(doc) NULL
138 | # define xmlSchematronNewParserCtxt(file) NULL
139 | # define xmlSchematronParse(ctxt) NULL
140 | # define xmlSchematronFreeParserCtxt(ctxt)
141 | # define xmlSchematronFree(schema)
142 | # define xmlSchematronNewValidCtxt(schema, options) NULL
143 | # define xmlSchematronValidateDoc(ctxt, doc) 0
144 | # define xmlSchematronFreeValidCtxt(ctxt)
145 | # define xmlSchematronSetValidStructuredErrors(ctxt, errorfunc, data)
146 | #endif
147 |
148 | #if LIBXML_VERSION < 20708
149 | # define HTML_PARSE_NODEFDTD 4
150 | #endif
151 | #if LIBXML_VERSION < 20900
152 | # define XML_PARSE_BIG_LINES 4194304
153 | #endif
154 |
155 | #include "libxml/tree.h"
156 | #ifndef LIBXML2_NEW_BUFFER
157 | typedef xmlBuffer xmlBuf;
158 | # define xmlBufContent(buf) xmlBufferContent(buf)
159 | # define xmlBufUse(buf) xmlBufferLength(buf)
160 | #endif
161 |
162 | /* libexslt 1.1.25+ support EXSLT functions in XPath */
163 | #if LIBXSLT_VERSION < 10125
164 | #define exsltDateXpathCtxtRegister(ctxt, prefix)
165 | #define exsltSetsXpathCtxtRegister(ctxt, prefix)
166 | #define exsltMathXpathCtxtRegister(ctxt, prefix)
167 | #define exsltStrXpathCtxtRegister(ctxt, prefix)
168 | #endif
169 |
170 | #define LXML_GET_XSLT_ENCODING(result_var, style) XSLT_GET_IMPORT_PTR(result_var, style, encoding)
171 |
172 | /* work around MSDEV 6.0 */
173 | #if (_MSC_VER == 1200) && (WINVER < 0x0500)
174 | long _ftol( double ); //defined by VC6 C libs
175 | long _ftol2( double dblSource ) { return _ftol( dblSource ); }
176 | #endif
177 |
178 | #ifdef __GNUC__
179 | /* Test for GCC > 2.95 */
180 | #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
181 | #define unlikely_condition(x) __builtin_expect((x), 0)
182 | #else /* __GNUC__ > 2 ... */
183 | #define unlikely_condition(x) (x)
184 | #endif /* __GNUC__ > 2 ... */
185 | #else /* __GNUC__ */
186 | #define unlikely_condition(x) (x)
187 | #endif /* __GNUC__ */
188 |
189 | #ifndef Py_TYPE
190 | #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
191 | #endif
192 |
193 | #define PY_NEW(T) \
194 | (((PyTypeObject*)(T))->tp_new( \
195 | (PyTypeObject*)(T), __pyx_empty_tuple, NULL))
196 |
197 | #define _fqtypename(o) ((Py_TYPE(o))->tp_name)
198 |
199 | #define lxml_malloc(count, item_size) \
200 | (unlikely_condition((size_t)(count) > (size_t) (PY_SSIZE_T_MAX / item_size)) ? NULL : \
201 | (PyMem_Malloc((count) * item_size)))
202 |
203 | #define lxml_realloc(mem, count, item_size) \
204 | (unlikely_condition((size_t)(count) > (size_t) (PY_SSIZE_T_MAX / item_size)) ? NULL : \
205 | (PyMem_Realloc(mem, (count) * item_size)))
206 |
207 | #define lxml_free(mem) PyMem_Free(mem)
208 |
209 | #define _isString(obj) (PyUnicode_Check(obj) || PyBytes_Check(obj))
210 |
211 | #define _isElement(c_node) \
212 | (((c_node)->type == XML_ELEMENT_NODE) || \
213 | ((c_node)->type == XML_COMMENT_NODE) || \
214 | ((c_node)->type == XML_ENTITY_REF_NODE) || \
215 | ((c_node)->type == XML_PI_NODE))
216 |
217 | #define _isElementOrXInclude(c_node) \
218 | (_isElement(c_node) || \
219 | ((c_node)->type == XML_XINCLUDE_START) || \
220 | ((c_node)->type == XML_XINCLUDE_END))
221 |
222 | #define _getNs(c_node) \
223 | (((c_node)->ns == 0) ? 0 : ((c_node)->ns->href))
224 |
225 |
226 | #include "string.h"
227 | static void* lxml_unpack_xmldoc_capsule(PyObject* capsule, int* is_owned) {
228 | xmlDoc *c_doc;
229 | void *context;
230 | *is_owned = 0;
231 | if (unlikely_condition(!PyCapsule_IsValid(capsule, (const char*)"libxml2:xmlDoc"))) {
232 | PyErr_SetString(
233 | PyExc_TypeError,
234 | "Not a valid capsule. The capsule argument must be a capsule object with name libxml2:xmlDoc");
235 | return NULL;
236 | }
237 | c_doc = (xmlDoc*) PyCapsule_GetPointer(capsule, (const char*)"libxml2:xmlDoc");
238 | if (unlikely_condition(!c_doc)) return NULL;
239 |
240 | if (unlikely_condition(c_doc->type != XML_DOCUMENT_NODE && c_doc->type != XML_HTML_DOCUMENT_NODE)) {
241 | PyErr_Format(
242 | PyExc_ValueError,
243 | "Illegal document provided: expected XML or HTML, found %d", (int)c_doc->type);
244 | return NULL;
245 | }
246 |
247 | context = PyCapsule_GetContext(capsule);
248 | if (unlikely_condition(!context && PyErr_Occurred())) return NULL;
249 | if (context && strcmp((const char*) context, "destructor:xmlFreeDoc") == 0) {
250 | /* take ownership by setting destructor to NULL */
251 | if (PyCapsule_SetDestructor(capsule, NULL) == 0) {
252 | /* ownership transferred => invalidate capsule by clearing its name */
253 | if (unlikely_condition(PyCapsule_SetName(capsule, NULL))) {
254 | /* this should never happen since everything above succeeded */
255 | xmlFreeDoc(c_doc);
256 | return NULL;
257 | }
258 | *is_owned = 1;
259 | }
260 | }
261 | return c_doc;
262 | }
263 |
264 | /* Macro pair implementation of a depth first tree walker
265 | *
266 | * Calls the code block between the BEGIN and END macros for all elements
267 | * below c_tree_top (exclusively), starting at c_node (inclusively iff
268 | * 'inclusive' is 1). The _ELEMENT_ variants will only stop on nodes
269 | * that match _isElement(), the normal variant will stop on every node
270 | * except text nodes.
271 | *
272 | * To traverse the node and all of its children and siblings in Pyrex, call
273 | * cdef xmlNode* some_node
274 | * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 1)
275 | * # do something with some_node
276 | * END_FOR_EACH_ELEMENT_FROM(some_node)
277 | *
278 | * To traverse only the children and siblings of a node, call
279 | * cdef xmlNode* some_node
280 | * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 0)
281 | * # do something with some_node
282 | * END_FOR_EACH_ELEMENT_FROM(some_node)
283 | *
284 | * To traverse only the children, do:
285 | * cdef xmlNode* some_node
286 | * some_node = parent_node.children
287 | * BEGIN_FOR_EACH_ELEMENT_FROM(parent_node, some_node, 1)
288 | * # do something with some_node
289 | * END_FOR_EACH_ELEMENT_FROM(some_node)
290 | *
291 | * NOTE: 'some_node' MUST be a plain 'xmlNode*' !
292 | *
293 | * NOTE: parent modification during the walk can divert the iterator, but
294 | * should not segfault !
295 | */
296 |
297 | #define _LX__ELEMENT_MATCH(c_node, only_elements) \
298 | ((only_elements) ? (_isElement(c_node)) : 1)
299 |
300 | #define _LX__ADVANCE_TO_NEXT(c_node, only_elements) \
301 | while ((c_node != 0) && (!_LX__ELEMENT_MATCH(c_node, only_elements))) \
302 | c_node = c_node->next;
303 |
304 | #define _LX__TRAVERSE_TO_NEXT(c_stop_node, c_node, only_elements) \
305 | { \
306 | /* walk through children first */ \
307 | xmlNode* _lx__next = c_node->children; \
308 | if (_lx__next != 0) { \
309 | if (c_node->type == XML_ENTITY_REF_NODE || c_node->type == XML_DTD_NODE) { \
310 | _lx__next = 0; \
311 | } else { \
312 | _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \
313 | } \
314 | } \
315 | if ((_lx__next == 0) && (c_node != c_stop_node)) { \
316 | /* try siblings */ \
317 | _lx__next = c_node->next; \
318 | _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \
319 | /* back off through parents */ \
320 | while (_lx__next == 0) { \
321 | c_node = c_node->parent; \
322 | if (c_node == 0) \
323 | break; \
324 | if (c_node == c_stop_node) \
325 | break; \
326 | if ((only_elements) && !_isElement(c_node)) \
327 | break; \
328 | /* we already traversed the parents -> siblings */ \
329 | _lx__next = c_node->next; \
330 | _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \
331 | } \
332 | } \
333 | c_node = _lx__next; \
334 | }
335 |
336 | #define _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, only_elements) \
337 | { \
338 | if (c_node != 0) { \
339 | const xmlNode* _lx__tree_top = (c_tree_top); \
340 | const int _lx__only_elements = (only_elements); \
341 | /* make sure we start at an element */ \
342 | if (!_LX__ELEMENT_MATCH(c_node, _lx__only_elements)) { \
343 | /* we skip the node, so 'inclusive' is irrelevant */ \
344 | if (c_node == _lx__tree_top) \
345 | c_node = 0; /* nothing to traverse */ \
346 | else { \
347 | c_node = c_node->next; \
348 | _LX__ADVANCE_TO_NEXT(c_node, _lx__only_elements) \
349 | } \
350 | } else if (! (inclusive)) { \
351 | /* skip the first node */ \
352 | _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \
353 | } \
354 | \
355 | /* now run the user code on the elements we find */ \
356 | while (c_node != 0) { \
357 | /* here goes the code to be run for each element */
358 |
359 | #define _LX__END_FOR_EACH_FROM(c_node) \
360 | _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \
361 | } \
362 | } \
363 | }
364 |
365 |
366 | #define BEGIN_FOR_EACH_ELEMENT_FROM(c_tree_top, c_node, inclusive) \
367 | _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 1)
368 |
369 | #define END_FOR_EACH_ELEMENT_FROM(c_node) \
370 | _LX__END_FOR_EACH_FROM(c_node)
371 |
372 | #define BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive) \
373 | _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 0)
374 |
375 | #define END_FOR_EACH_FROM(c_node) \
376 | _LX__END_FOR_EACH_FROM(c_node)
377 |
378 |
379 | #endif /* HAS_ETREE_DEFS_H */
380 |
```