This is page 153 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/environment.py:
--------------------------------------------------------------------------------
```python
1 | """Classes for managing templates and their runtime and compile time
2 | options.
3 | """
4 |
5 | import os
6 | import typing
7 | import typing as t
8 | import weakref
9 | from collections import ChainMap
10 | from functools import lru_cache
11 | from functools import partial
12 | from functools import reduce
13 | from types import CodeType
14 |
15 | from markupsafe import Markup
16 |
17 | from . import nodes
18 | from .compiler import CodeGenerator
19 | from .compiler import generate
20 | from .defaults import BLOCK_END_STRING
21 | from .defaults import BLOCK_START_STRING
22 | from .defaults import COMMENT_END_STRING
23 | from .defaults import COMMENT_START_STRING
24 | from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined]
25 | from .defaults import DEFAULT_NAMESPACE
26 | from .defaults import DEFAULT_POLICIES
27 | from .defaults import DEFAULT_TESTS # type: ignore[attr-defined]
28 | from .defaults import KEEP_TRAILING_NEWLINE
29 | from .defaults import LINE_COMMENT_PREFIX
30 | from .defaults import LINE_STATEMENT_PREFIX
31 | from .defaults import LSTRIP_BLOCKS
32 | from .defaults import NEWLINE_SEQUENCE
33 | from .defaults import TRIM_BLOCKS
34 | from .defaults import VARIABLE_END_STRING
35 | from .defaults import VARIABLE_START_STRING
36 | from .exceptions import TemplateNotFound
37 | from .exceptions import TemplateRuntimeError
38 | from .exceptions import TemplatesNotFound
39 | from .exceptions import TemplateSyntaxError
40 | from .exceptions import UndefinedError
41 | from .lexer import get_lexer
42 | from .lexer import Lexer
43 | from .lexer import TokenStream
44 | from .nodes import EvalContext
45 | from .parser import Parser
46 | from .runtime import Context
47 | from .runtime import new_context
48 | from .runtime import Undefined
49 | from .utils import _PassArg
50 | from .utils import concat
51 | from .utils import consume
52 | from .utils import import_string
53 | from .utils import internalcode
54 | from .utils import LRUCache
55 | from .utils import missing
56 |
57 | if t.TYPE_CHECKING:
58 | import typing_extensions as te
59 |
60 | from .bccache import BytecodeCache
61 | from .ext import Extension
62 | from .loaders import BaseLoader
63 |
64 | _env_bound = t.TypeVar("_env_bound", bound="Environment")
65 |
66 |
67 | # for direct template usage we have up to ten living environments
68 | @lru_cache(maxsize=10)
69 | def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound:
70 | """Return a new spontaneous environment. A spontaneous environment
71 | is used for templates created directly rather than through an
72 | existing environment.
73 |
74 | :param cls: Environment class to create.
75 | :param args: Positional arguments passed to environment.
76 | """
77 | env = cls(*args)
78 | env.shared = True
79 | return env
80 |
81 |
82 | def create_cache(
83 | size: int,
84 | ) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]:
85 | """Return the cache class for the given size."""
86 | if size == 0:
87 | return None
88 |
89 | if size < 0:
90 | return {}
91 |
92 | return LRUCache(size) # type: ignore
93 |
94 |
95 | def copy_cache(
96 | cache: t.Optional[t.MutableMapping[t.Any, t.Any]],
97 | ) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]:
98 | """Create an empty copy of the given cache."""
99 | if cache is None:
100 | return None
101 |
102 | if type(cache) is dict: # noqa E721
103 | return {}
104 |
105 | return LRUCache(cache.capacity) # type: ignore
106 |
107 |
108 | def load_extensions(
109 | environment: "Environment",
110 | extensions: t.Sequence[t.Union[str, t.Type["Extension"]]],
111 | ) -> t.Dict[str, "Extension"]:
112 | """Load the extensions from the list and bind it to the environment.
113 | Returns a dict of instantiated extensions.
114 | """
115 | result = {}
116 |
117 | for extension in extensions:
118 | if isinstance(extension, str):
119 | extension = t.cast(t.Type["Extension"], import_string(extension))
120 |
121 | result[extension.identifier] = extension(environment)
122 |
123 | return result
124 |
125 |
126 | def _environment_config_check(environment: "Environment") -> "Environment":
127 | """Perform a sanity check on the environment."""
128 | assert issubclass(
129 | environment.undefined, Undefined
130 | ), "'undefined' must be a subclass of 'jinja2.Undefined'."
131 | assert (
132 | environment.block_start_string
133 | != environment.variable_start_string
134 | != environment.comment_start_string
135 | ), "block, variable and comment start strings must be different."
136 | assert environment.newline_sequence in {
137 | "\r",
138 | "\r\n",
139 | "\n",
140 | }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'."
141 | return environment
142 |
143 |
144 | class Environment:
145 | r"""The core component of Jinja is the `Environment`. It contains
146 | important shared variables like configuration, filters, tests,
147 | globals and others. Instances of this class may be modified if
148 | they are not shared and if no template was loaded so far.
149 | Modifications on environments after the first template was loaded
150 | will lead to surprising effects and undefined behavior.
151 |
152 | Here are the possible initialization parameters:
153 |
154 | `block_start_string`
155 | The string marking the beginning of a block. Defaults to ``'{%'``.
156 |
157 | `block_end_string`
158 | The string marking the end of a block. Defaults to ``'%}'``.
159 |
160 | `variable_start_string`
161 | The string marking the beginning of a print statement.
162 | Defaults to ``'{{'``.
163 |
164 | `variable_end_string`
165 | The string marking the end of a print statement. Defaults to
166 | ``'}}'``.
167 |
168 | `comment_start_string`
169 | The string marking the beginning of a comment. Defaults to ``'{#'``.
170 |
171 | `comment_end_string`
172 | The string marking the end of a comment. Defaults to ``'#}'``.
173 |
174 | `line_statement_prefix`
175 | If given and a string, this will be used as prefix for line based
176 | statements. See also :ref:`line-statements`.
177 |
178 | `line_comment_prefix`
179 | If given and a string, this will be used as prefix for line based
180 | comments. See also :ref:`line-statements`.
181 |
182 | .. versionadded:: 2.2
183 |
184 | `trim_blocks`
185 | If this is set to ``True`` the first newline after a block is
186 | removed (block, not variable tag!). Defaults to `False`.
187 |
188 | `lstrip_blocks`
189 | If this is set to ``True`` leading spaces and tabs are stripped
190 | from the start of a line to a block. Defaults to `False`.
191 |
192 | `newline_sequence`
193 | The sequence that starts a newline. Must be one of ``'\r'``,
194 | ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a
195 | useful default for Linux and OS X systems as well as web
196 | applications.
197 |
198 | `keep_trailing_newline`
199 | Preserve the trailing newline when rendering templates.
200 | The default is ``False``, which causes a single newline,
201 | if present, to be stripped from the end of the template.
202 |
203 | .. versionadded:: 2.7
204 |
205 | `extensions`
206 | List of Jinja extensions to use. This can either be import paths
207 | as strings or extension classes. For more information have a
208 | look at :ref:`the extensions documentation <jinja-extensions>`.
209 |
210 | `optimized`
211 | should the optimizer be enabled? Default is ``True``.
212 |
213 | `undefined`
214 | :class:`Undefined` or a subclass of it that is used to represent
215 | undefined values in the template.
216 |
217 | `finalize`
218 | A callable that can be used to process the result of a variable
219 | expression before it is output. For example one can convert
220 | ``None`` implicitly into an empty string here.
221 |
222 | `autoescape`
223 | If set to ``True`` the XML/HTML autoescaping feature is enabled by
224 | default. For more details about autoescaping see
225 | :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also
226 | be a callable that is passed the template name and has to
227 | return ``True`` or ``False`` depending on autoescape should be
228 | enabled by default.
229 |
230 | .. versionchanged:: 2.4
231 | `autoescape` can now be a function
232 |
233 | `loader`
234 | The template loader for this environment.
235 |
236 | `cache_size`
237 | The size of the cache. Per default this is ``400`` which means
238 | that if more than 400 templates are loaded the loader will clean
239 | out the least recently used template. If the cache size is set to
240 | ``0`` templates are recompiled all the time, if the cache size is
241 | ``-1`` the cache will not be cleaned.
242 |
243 | .. versionchanged:: 2.8
244 | The cache size was increased to 400 from a low 50.
245 |
246 | `auto_reload`
247 | Some loaders load templates from locations where the template
248 | sources may change (ie: file system or database). If
249 | ``auto_reload`` is set to ``True`` (default) every time a template is
250 | requested the loader checks if the source changed and if yes, it
251 | will reload the template. For higher performance it's possible to
252 | disable that.
253 |
254 | `bytecode_cache`
255 | If set to a bytecode cache object, this object will provide a
256 | cache for the internal Jinja bytecode so that templates don't
257 | have to be parsed if they were not changed.
258 |
259 | See :ref:`bytecode-cache` for more information.
260 |
261 | `enable_async`
262 | If set to true this enables async template execution which
263 | allows using async functions and generators.
264 | """
265 |
266 | #: if this environment is sandboxed. Modifying this variable won't make
267 | #: the environment sandboxed though. For a real sandboxed environment
268 | #: have a look at jinja2.sandbox. This flag alone controls the code
269 | #: generation by the compiler.
270 | sandboxed = False
271 |
272 | #: True if the environment is just an overlay
273 | overlayed = False
274 |
275 | #: the environment this environment is linked to if it is an overlay
276 | linked_to: t.Optional["Environment"] = None
277 |
278 | #: shared environments have this set to `True`. A shared environment
279 | #: must not be modified
280 | shared = False
281 |
282 | #: the class that is used for code generation. See
283 | #: :class:`~jinja2.compiler.CodeGenerator` for more information.
284 | code_generator_class: t.Type["CodeGenerator"] = CodeGenerator
285 |
286 | concat = "".join
287 |
288 | #: the context class that is used for templates. See
289 | #: :class:`~jinja2.runtime.Context` for more information.
290 | context_class: t.Type[Context] = Context
291 |
292 | template_class: t.Type["Template"]
293 |
294 | def __init__(
295 | self,
296 | block_start_string: str = BLOCK_START_STRING,
297 | block_end_string: str = BLOCK_END_STRING,
298 | variable_start_string: str = VARIABLE_START_STRING,
299 | variable_end_string: str = VARIABLE_END_STRING,
300 | comment_start_string: str = COMMENT_START_STRING,
301 | comment_end_string: str = COMMENT_END_STRING,
302 | line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX,
303 | line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX,
304 | trim_blocks: bool = TRIM_BLOCKS,
305 | lstrip_blocks: bool = LSTRIP_BLOCKS,
306 | newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
307 | keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
308 | extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
309 | optimized: bool = True,
310 | undefined: t.Type[Undefined] = Undefined,
311 | finalize: t.Optional[t.Callable[..., t.Any]] = None,
312 | autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
313 | loader: t.Optional["BaseLoader"] = None,
314 | cache_size: int = 400,
315 | auto_reload: bool = True,
316 | bytecode_cache: t.Optional["BytecodeCache"] = None,
317 | enable_async: bool = False,
318 | ):
319 | # !!Important notice!!
320 | # The constructor accepts quite a few arguments that should be
321 | # passed by keyword rather than position. However it's important to
322 | # not change the order of arguments because it's used at least
323 | # internally in those cases:
324 | # - spontaneous environments (i18n extension and Template)
325 | # - unittests
326 | # If parameter changes are required only add parameters at the end
327 | # and don't change the arguments (or the defaults!) of the arguments
328 | # existing already.
329 |
330 | # lexer / parser information
331 | self.block_start_string = block_start_string
332 | self.block_end_string = block_end_string
333 | self.variable_start_string = variable_start_string
334 | self.variable_end_string = variable_end_string
335 | self.comment_start_string = comment_start_string
336 | self.comment_end_string = comment_end_string
337 | self.line_statement_prefix = line_statement_prefix
338 | self.line_comment_prefix = line_comment_prefix
339 | self.trim_blocks = trim_blocks
340 | self.lstrip_blocks = lstrip_blocks
341 | self.newline_sequence = newline_sequence
342 | self.keep_trailing_newline = keep_trailing_newline
343 |
344 | # runtime information
345 | self.undefined: t.Type[Undefined] = undefined
346 | self.optimized = optimized
347 | self.finalize = finalize
348 | self.autoescape = autoescape
349 |
350 | # defaults
351 | self.filters = DEFAULT_FILTERS.copy()
352 | self.tests = DEFAULT_TESTS.copy()
353 | self.globals = DEFAULT_NAMESPACE.copy()
354 |
355 | # set the loader provided
356 | self.loader = loader
357 | self.cache = create_cache(cache_size)
358 | self.bytecode_cache = bytecode_cache
359 | self.auto_reload = auto_reload
360 |
361 | # configurable policies
362 | self.policies = DEFAULT_POLICIES.copy()
363 |
364 | # load extensions
365 | self.extensions = load_extensions(self, extensions)
366 |
367 | self.is_async = enable_async
368 | _environment_config_check(self)
369 |
370 | def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None:
371 | """Adds an extension after the environment was created.
372 |
373 | .. versionadded:: 2.5
374 | """
375 | self.extensions.update(load_extensions(self, [extension]))
376 |
377 | def extend(self, **attributes: t.Any) -> None:
378 | """Add the items to the instance of the environment if they do not exist
379 | yet. This is used by :ref:`extensions <writing-extensions>` to register
380 | callbacks and configuration values without breaking inheritance.
381 | """
382 | for key, value in attributes.items():
383 | if not hasattr(self, key):
384 | setattr(self, key, value)
385 |
386 | def overlay(
387 | self,
388 | block_start_string: str = missing,
389 | block_end_string: str = missing,
390 | variable_start_string: str = missing,
391 | variable_end_string: str = missing,
392 | comment_start_string: str = missing,
393 | comment_end_string: str = missing,
394 | line_statement_prefix: t.Optional[str] = missing,
395 | line_comment_prefix: t.Optional[str] = missing,
396 | trim_blocks: bool = missing,
397 | lstrip_blocks: bool = missing,
398 | newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing,
399 | keep_trailing_newline: bool = missing,
400 | extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing,
401 | optimized: bool = missing,
402 | undefined: t.Type[Undefined] = missing,
403 | finalize: t.Optional[t.Callable[..., t.Any]] = missing,
404 | autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing,
405 | loader: t.Optional["BaseLoader"] = missing,
406 | cache_size: int = missing,
407 | auto_reload: bool = missing,
408 | bytecode_cache: t.Optional["BytecodeCache"] = missing,
409 | enable_async: bool = False,
410 | ) -> "Environment":
411 | """Create a new overlay environment that shares all the data with the
412 | current environment except for cache and the overridden attributes.
413 | Extensions cannot be removed for an overlayed environment. An overlayed
414 | environment automatically gets all the extensions of the environment it
415 | is linked to plus optional extra extensions.
416 |
417 | Creating overlays should happen after the initial environment was set
418 | up completely. Not all attributes are truly linked, some are just
419 | copied over so modifications on the original environment may not shine
420 | through.
421 |
422 | .. versionchanged:: 3.1.2
423 | Added the ``newline_sequence``,, ``keep_trailing_newline``,
424 | and ``enable_async`` parameters to match ``__init__``.
425 | """
426 | args = dict(locals())
427 | del args["self"], args["cache_size"], args["extensions"], args["enable_async"]
428 |
429 | rv = object.__new__(self.__class__)
430 | rv.__dict__.update(self.__dict__)
431 | rv.overlayed = True
432 | rv.linked_to = self
433 |
434 | for key, value in args.items():
435 | if value is not missing:
436 | setattr(rv, key, value)
437 |
438 | if cache_size is not missing:
439 | rv.cache = create_cache(cache_size)
440 | else:
441 | rv.cache = copy_cache(self.cache)
442 |
443 | rv.extensions = {}
444 | for key, value in self.extensions.items():
445 | rv.extensions[key] = value.bind(rv)
446 | if extensions is not missing:
447 | rv.extensions.update(load_extensions(rv, extensions))
448 |
449 | if enable_async is not missing:
450 | rv.is_async = enable_async
451 |
452 | return _environment_config_check(rv)
453 |
454 | @property
455 | def lexer(self) -> Lexer:
456 | """The lexer for this environment."""
457 | return get_lexer(self)
458 |
459 | def iter_extensions(self) -> t.Iterator["Extension"]:
460 | """Iterates over the extensions by priority."""
461 | return iter(sorted(self.extensions.values(), key=lambda x: x.priority))
462 |
463 | def getitem(
464 | self, obj: t.Any, argument: t.Union[str, t.Any]
465 | ) -> t.Union[t.Any, Undefined]:
466 | """Get an item or attribute of an object but prefer the item."""
467 | try:
468 | return obj[argument]
469 | except (AttributeError, TypeError, LookupError):
470 | if isinstance(argument, str):
471 | try:
472 | attr = str(argument)
473 | except Exception:
474 | pass
475 | else:
476 | try:
477 | return getattr(obj, attr)
478 | except AttributeError:
479 | pass
480 | return self.undefined(obj=obj, name=argument)
481 |
482 | def getattr(self, obj: t.Any, attribute: str) -> t.Any:
483 | """Get an item or attribute of an object but prefer the attribute.
484 | Unlike :meth:`getitem` the attribute *must* be a string.
485 | """
486 | try:
487 | return getattr(obj, attribute)
488 | except AttributeError:
489 | pass
490 | try:
491 | return obj[attribute]
492 | except (TypeError, LookupError, AttributeError):
493 | return self.undefined(obj=obj, name=attribute)
494 |
495 | def _filter_test_common(
496 | self,
497 | name: t.Union[str, Undefined],
498 | value: t.Any,
499 | args: t.Optional[t.Sequence[t.Any]],
500 | kwargs: t.Optional[t.Mapping[str, t.Any]],
501 | context: t.Optional[Context],
502 | eval_ctx: t.Optional[EvalContext],
503 | is_filter: bool,
504 | ) -> t.Any:
505 | if is_filter:
506 | env_map = self.filters
507 | type_name = "filter"
508 | else:
509 | env_map = self.tests
510 | type_name = "test"
511 |
512 | func = env_map.get(name) # type: ignore
513 |
514 | if func is None:
515 | msg = f"No {type_name} named {name!r}."
516 |
517 | if isinstance(name, Undefined):
518 | try:
519 | name._fail_with_undefined_error()
520 | except Exception as e:
521 | msg = f"{msg} ({e}; did you forget to quote the callable name?)"
522 |
523 | raise TemplateRuntimeError(msg)
524 |
525 | args = [value, *(args if args is not None else ())]
526 | kwargs = kwargs if kwargs is not None else {}
527 | pass_arg = _PassArg.from_obj(func)
528 |
529 | if pass_arg is _PassArg.context:
530 | if context is None:
531 | raise TemplateRuntimeError(
532 | f"Attempted to invoke a context {type_name} without context."
533 | )
534 |
535 | args.insert(0, context)
536 | elif pass_arg is _PassArg.eval_context:
537 | if eval_ctx is None:
538 | if context is not None:
539 | eval_ctx = context.eval_ctx
540 | else:
541 | eval_ctx = EvalContext(self)
542 |
543 | args.insert(0, eval_ctx)
544 | elif pass_arg is _PassArg.environment:
545 | args.insert(0, self)
546 |
547 | return func(*args, **kwargs)
548 |
549 | def call_filter(
550 | self,
551 | name: str,
552 | value: t.Any,
553 | args: t.Optional[t.Sequence[t.Any]] = None,
554 | kwargs: t.Optional[t.Mapping[str, t.Any]] = None,
555 | context: t.Optional[Context] = None,
556 | eval_ctx: t.Optional[EvalContext] = None,
557 | ) -> t.Any:
558 | """Invoke a filter on a value the same way the compiler does.
559 |
560 | This might return a coroutine if the filter is running from an
561 | environment in async mode and the filter supports async
562 | execution. It's your responsibility to await this if needed.
563 |
564 | .. versionadded:: 2.7
565 | """
566 | return self._filter_test_common(
567 | name, value, args, kwargs, context, eval_ctx, True
568 | )
569 |
570 | def call_test(
571 | self,
572 | name: str,
573 | value: t.Any,
574 | args: t.Optional[t.Sequence[t.Any]] = None,
575 | kwargs: t.Optional[t.Mapping[str, t.Any]] = None,
576 | context: t.Optional[Context] = None,
577 | eval_ctx: t.Optional[EvalContext] = None,
578 | ) -> t.Any:
579 | """Invoke a test on a value the same way the compiler does.
580 |
581 | This might return a coroutine if the test is running from an
582 | environment in async mode and the test supports async execution.
583 | It's your responsibility to await this if needed.
584 |
585 | .. versionchanged:: 3.0
586 | Tests support ``@pass_context``, etc. decorators. Added
587 | the ``context`` and ``eval_ctx`` parameters.
588 |
589 | .. versionadded:: 2.7
590 | """
591 | return self._filter_test_common(
592 | name, value, args, kwargs, context, eval_ctx, False
593 | )
594 |
595 | @internalcode
596 | def parse(
597 | self,
598 | source: str,
599 | name: t.Optional[str] = None,
600 | filename: t.Optional[str] = None,
601 | ) -> nodes.Template:
602 | """Parse the sourcecode and return the abstract syntax tree. This
603 | tree of nodes is used by the compiler to convert the template into
604 | executable source- or bytecode. This is useful for debugging or to
605 | extract information from templates.
606 |
607 | If you are :ref:`developing Jinja extensions <writing-extensions>`
608 | this gives you a good overview of the node tree generated.
609 | """
610 | try:
611 | return self._parse(source, name, filename)
612 | except TemplateSyntaxError:
613 | self.handle_exception(source=source)
614 |
615 | def _parse(
616 | self, source: str, name: t.Optional[str], filename: t.Optional[str]
617 | ) -> nodes.Template:
618 | """Internal parsing function used by `parse` and `compile`."""
619 | return Parser(self, source, name, filename).parse()
620 |
621 | def lex(
622 | self,
623 | source: str,
624 | name: t.Optional[str] = None,
625 | filename: t.Optional[str] = None,
626 | ) -> t.Iterator[t.Tuple[int, str, str]]:
627 | """Lex the given sourcecode and return a generator that yields
628 | tokens as tuples in the form ``(lineno, token_type, value)``.
629 | This can be useful for :ref:`extension development <writing-extensions>`
630 | and debugging templates.
631 |
632 | This does not perform preprocessing. If you want the preprocessing
633 | of the extensions to be applied you have to filter source through
634 | the :meth:`preprocess` method.
635 | """
636 | source = str(source)
637 | try:
638 | return self.lexer.tokeniter(source, name, filename)
639 | except TemplateSyntaxError:
640 | self.handle_exception(source=source)
641 |
642 | def preprocess(
643 | self,
644 | source: str,
645 | name: t.Optional[str] = None,
646 | filename: t.Optional[str] = None,
647 | ) -> str:
648 | """Preprocesses the source with all extensions. This is automatically
649 | called for all parsing and compiling methods but *not* for :meth:`lex`
650 | because there you usually only want the actual source tokenized.
651 | """
652 | return reduce(
653 | lambda s, e: e.preprocess(s, name, filename),
654 | self.iter_extensions(),
655 | str(source),
656 | )
657 |
658 | def _tokenize(
659 | self,
660 | source: str,
661 | name: t.Optional[str],
662 | filename: t.Optional[str] = None,
663 | state: t.Optional[str] = None,
664 | ) -> TokenStream:
665 | """Called by the parser to do the preprocessing and filtering
666 | for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`.
667 | """
668 | source = self.preprocess(source, name, filename)
669 | stream = self.lexer.tokenize(source, name, filename, state)
670 |
671 | for ext in self.iter_extensions():
672 | stream = ext.filter_stream(stream) # type: ignore
673 |
674 | if not isinstance(stream, TokenStream):
675 | stream = TokenStream(stream, name, filename)
676 |
677 | return stream
678 |
679 | def _generate(
680 | self,
681 | source: nodes.Template,
682 | name: t.Optional[str],
683 | filename: t.Optional[str],
684 | defer_init: bool = False,
685 | ) -> str:
686 | """Internal hook that can be overridden to hook a different generate
687 | method in.
688 |
689 | .. versionadded:: 2.5
690 | """
691 | return generate( # type: ignore
692 | source,
693 | self,
694 | name,
695 | filename,
696 | defer_init=defer_init,
697 | optimized=self.optimized,
698 | )
699 |
700 | def _compile(self, source: str, filename: str) -> CodeType:
701 | """Internal hook that can be overridden to hook a different compile
702 | method in.
703 |
704 | .. versionadded:: 2.5
705 | """
706 | return compile(source, filename, "exec")
707 |
708 | @typing.overload
709 | def compile( # type: ignore
710 | self,
711 | source: t.Union[str, nodes.Template],
712 | name: t.Optional[str] = None,
713 | filename: t.Optional[str] = None,
714 | raw: "te.Literal[False]" = False,
715 | defer_init: bool = False,
716 | ) -> CodeType: ...
717 |
718 | @typing.overload
719 | def compile(
720 | self,
721 | source: t.Union[str, nodes.Template],
722 | name: t.Optional[str] = None,
723 | filename: t.Optional[str] = None,
724 | raw: "te.Literal[True]" = ...,
725 | defer_init: bool = False,
726 | ) -> str: ...
727 |
728 | @internalcode
729 | def compile(
730 | self,
731 | source: t.Union[str, nodes.Template],
732 | name: t.Optional[str] = None,
733 | filename: t.Optional[str] = None,
734 | raw: bool = False,
735 | defer_init: bool = False,
736 | ) -> t.Union[str, CodeType]:
737 | """Compile a node or template source code. The `name` parameter is
738 | the load name of the template after it was joined using
739 | :meth:`join_path` if necessary, not the filename on the file system.
740 | the `filename` parameter is the estimated filename of the template on
741 | the file system. If the template came from a database or memory this
742 | can be omitted.
743 |
744 | The return value of this method is a python code object. If the `raw`
745 | parameter is `True` the return value will be a string with python
746 | code equivalent to the bytecode returned otherwise. This method is
747 | mainly used internally.
748 |
749 | `defer_init` is use internally to aid the module code generator. This
750 | causes the generated code to be able to import without the global
751 | environment variable to be set.
752 |
753 | .. versionadded:: 2.4
754 | `defer_init` parameter added.
755 | """
756 | source_hint = None
757 | try:
758 | if isinstance(source, str):
759 | source_hint = source
760 | source = self._parse(source, name, filename)
761 | source = self._generate(source, name, filename, defer_init=defer_init)
762 | if raw:
763 | return source
764 | if filename is None:
765 | filename = "<template>"
766 | return self._compile(source, filename)
767 | except TemplateSyntaxError:
768 | self.handle_exception(source=source_hint)
769 |
770 | def compile_expression(
771 | self, source: str, undefined_to_none: bool = True
772 | ) -> "TemplateExpression":
773 | """A handy helper method that returns a callable that accepts keyword
774 | arguments that appear as variables in the expression. If called it
775 | returns the result of the expression.
776 |
777 | This is useful if applications want to use the same rules as Jinja
778 | in template "configuration files" or similar situations.
779 |
780 | Example usage:
781 |
782 | >>> env = Environment()
783 | >>> expr = env.compile_expression('foo == 42')
784 | >>> expr(foo=23)
785 | False
786 | >>> expr(foo=42)
787 | True
788 |
789 | Per default the return value is converted to `None` if the
790 | expression returns an undefined value. This can be changed
791 | by setting `undefined_to_none` to `False`.
792 |
793 | >>> env.compile_expression('var')() is None
794 | True
795 | >>> env.compile_expression('var', undefined_to_none=False)()
796 | Undefined
797 |
798 | .. versionadded:: 2.1
799 | """
800 | parser = Parser(self, source, state="variable")
801 | try:
802 | expr = parser.parse_expression()
803 | if not parser.stream.eos:
804 | raise TemplateSyntaxError(
805 | "chunk after expression", parser.stream.current.lineno, None, None
806 | )
807 | expr.set_environment(self)
808 | except TemplateSyntaxError:
809 | self.handle_exception(source=source)
810 |
811 | body = [nodes.Assign(nodes.Name("result", "store"), expr, lineno=1)]
812 | template = self.from_string(nodes.Template(body, lineno=1))
813 | return TemplateExpression(template, undefined_to_none)
814 |
815 | def compile_templates(
816 | self,
817 | target: t.Union[str, "os.PathLike[str]"],
818 | extensions: t.Optional[t.Collection[str]] = None,
819 | filter_func: t.Optional[t.Callable[[str], bool]] = None,
820 | zip: t.Optional[str] = "deflated",
821 | log_function: t.Optional[t.Callable[[str], None]] = None,
822 | ignore_errors: bool = True,
823 | ) -> None:
824 | """Finds all the templates the loader can find, compiles them
825 | and stores them in `target`. If `zip` is `None`, instead of in a
826 | zipfile, the templates will be stored in a directory.
827 | By default a deflate zip algorithm is used. To switch to
828 | the stored algorithm, `zip` can be set to ``'stored'``.
829 |
830 | `extensions` and `filter_func` are passed to :meth:`list_templates`.
831 | Each template returned will be compiled to the target folder or
832 | zipfile.
833 |
834 | By default template compilation errors are ignored. In case a
835 | log function is provided, errors are logged. If you want template
836 | syntax errors to abort the compilation you can set `ignore_errors`
837 | to `False` and you will get an exception on syntax errors.
838 |
839 | .. versionadded:: 2.4
840 | """
841 | from .loaders import ModuleLoader
842 |
843 | if log_function is None:
844 |
845 | def log_function(x: str) -> None:
846 | pass
847 |
848 | assert log_function is not None
849 | assert self.loader is not None, "No loader configured."
850 |
851 | def write_file(filename: str, data: str) -> None:
852 | if zip:
853 | info = ZipInfo(filename)
854 | info.external_attr = 0o755 << 16
855 | zip_file.writestr(info, data)
856 | else:
857 | with open(os.path.join(target, filename), "wb") as f:
858 | f.write(data.encode("utf8"))
859 |
860 | if zip is not None:
861 | from zipfile import ZIP_DEFLATED
862 | from zipfile import ZIP_STORED
863 | from zipfile import ZipFile
864 | from zipfile import ZipInfo
865 |
866 | zip_file = ZipFile(
867 | target, "w", dict(deflated=ZIP_DEFLATED, stored=ZIP_STORED)[zip]
868 | )
869 | log_function(f"Compiling into Zip archive {target!r}")
870 | else:
871 | if not os.path.isdir(target):
872 | os.makedirs(target)
873 | log_function(f"Compiling into folder {target!r}")
874 |
875 | try:
876 | for name in self.list_templates(extensions, filter_func):
877 | source, filename, _ = self.loader.get_source(self, name)
878 | try:
879 | code = self.compile(source, name, filename, True, True)
880 | except TemplateSyntaxError as e:
881 | if not ignore_errors:
882 | raise
883 | log_function(f'Could not compile "{name}": {e}')
884 | continue
885 |
886 | filename = ModuleLoader.get_module_filename(name)
887 |
888 | write_file(filename, code)
889 | log_function(f'Compiled "{name}" as {filename}')
890 | finally:
891 | if zip:
892 | zip_file.close()
893 |
894 | log_function("Finished compiling templates")
895 |
896 | def list_templates(
897 | self,
898 | extensions: t.Optional[t.Collection[str]] = None,
899 | filter_func: t.Optional[t.Callable[[str], bool]] = None,
900 | ) -> t.List[str]:
901 | """Returns a list of templates for this environment. This requires
902 | that the loader supports the loader's
903 | :meth:`~BaseLoader.list_templates` method.
904 |
905 | If there are other files in the template folder besides the
906 | actual templates, the returned list can be filtered. There are two
907 | ways: either `extensions` is set to a list of file extensions for
908 | templates, or a `filter_func` can be provided which is a callable that
909 | is passed a template name and should return `True` if it should end up
910 | in the result list.
911 |
912 | If the loader does not support that, a :exc:`TypeError` is raised.
913 |
914 | .. versionadded:: 2.4
915 | """
916 | assert self.loader is not None, "No loader configured."
917 | names = self.loader.list_templates()
918 |
919 | if extensions is not None:
920 | if filter_func is not None:
921 | raise TypeError(
922 | "either extensions or filter_func can be passed, but not both"
923 | )
924 |
925 | def filter_func(x: str) -> bool:
926 | return "." in x and x.rsplit(".", 1)[1] in extensions
927 |
928 | if filter_func is not None:
929 | names = [name for name in names if filter_func(name)]
930 |
931 | return names
932 |
933 | def handle_exception(self, source: t.Optional[str] = None) -> "te.NoReturn":
934 | """Exception handling helper. This is used internally to either raise
935 | rewritten exceptions or return a rendered traceback for the template.
936 | """
937 | from .debug import rewrite_traceback_stack
938 |
939 | raise rewrite_traceback_stack(source=source)
940 |
941 | def join_path(self, template: str, parent: str) -> str:
942 | """Join a template with the parent. By default all the lookups are
943 | relative to the loader root so this method returns the `template`
944 | parameter unchanged, but if the paths should be relative to the
945 | parent template, this function can be used to calculate the real
946 | template name.
947 |
948 | Subclasses may override this method and implement template path
949 | joining here.
950 | """
951 | return template
952 |
953 | @internalcode
954 | def _load_template(
955 | self, name: str, globals: t.Optional[t.MutableMapping[str, t.Any]]
956 | ) -> "Template":
957 | if self.loader is None:
958 | raise TypeError("no loader for this environment specified")
959 | cache_key = (weakref.ref(self.loader), name)
960 | if self.cache is not None:
961 | template = self.cache.get(cache_key)
962 | if template is not None and (
963 | not self.auto_reload or template.is_up_to_date
964 | ):
965 | # template.globals is a ChainMap, modifying it will only
966 | # affect the template, not the environment globals.
967 | if globals:
968 | template.globals.update(globals)
969 |
970 | return template
971 |
972 | template = self.loader.load(self, name, self.make_globals(globals))
973 |
974 | if self.cache is not None:
975 | self.cache[cache_key] = template
976 | return template
977 |
978 | @internalcode
979 | def get_template(
980 | self,
981 | name: t.Union[str, "Template"],
982 | parent: t.Optional[str] = None,
983 | globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
984 | ) -> "Template":
985 | """Load a template by name with :attr:`loader` and return a
986 | :class:`Template`. If the template does not exist a
987 | :exc:`TemplateNotFound` exception is raised.
988 |
989 | :param name: Name of the template to load. When loading
990 | templates from the filesystem, "/" is used as the path
991 | separator, even on Windows.
992 | :param parent: The name of the parent template importing this
993 | template. :meth:`join_path` can be used to implement name
994 | transformations with this.
995 | :param globals: Extend the environment :attr:`globals` with
996 | these extra variables available for all renders of this
997 | template. If the template has already been loaded and
998 | cached, its globals are updated with any new items.
999 |
1000 | .. versionchanged:: 3.0
1001 | If a template is loaded from cache, ``globals`` will update
1002 | the template's globals instead of ignoring the new values.
1003 |
1004 | .. versionchanged:: 2.4
1005 | If ``name`` is a :class:`Template` object it is returned
1006 | unchanged.
1007 | """
1008 | if isinstance(name, Template):
1009 | return name
1010 | if parent is not None:
1011 | name = self.join_path(name, parent)
1012 |
1013 | return self._load_template(name, globals)
1014 |
1015 | @internalcode
1016 | def select_template(
1017 | self,
1018 | names: t.Iterable[t.Union[str, "Template"]],
1019 | parent: t.Optional[str] = None,
1020 | globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1021 | ) -> "Template":
1022 | """Like :meth:`get_template`, but tries loading multiple names.
1023 | If none of the names can be loaded a :exc:`TemplatesNotFound`
1024 | exception is raised.
1025 |
1026 | :param names: List of template names to try loading in order.
1027 | :param parent: The name of the parent template importing this
1028 | template. :meth:`join_path` can be used to implement name
1029 | transformations with this.
1030 | :param globals: Extend the environment :attr:`globals` with
1031 | these extra variables available for all renders of this
1032 | template. If the template has already been loaded and
1033 | cached, its globals are updated with any new items.
1034 |
1035 | .. versionchanged:: 3.0
1036 | If a template is loaded from cache, ``globals`` will update
1037 | the template's globals instead of ignoring the new values.
1038 |
1039 | .. versionchanged:: 2.11
1040 | If ``names`` is :class:`Undefined`, an :exc:`UndefinedError`
1041 | is raised instead. If no templates were found and ``names``
1042 | contains :class:`Undefined`, the message is more helpful.
1043 |
1044 | .. versionchanged:: 2.4
1045 | If ``names`` contains a :class:`Template` object it is
1046 | returned unchanged.
1047 |
1048 | .. versionadded:: 2.3
1049 | """
1050 | if isinstance(names, Undefined):
1051 | names._fail_with_undefined_error()
1052 |
1053 | if not names:
1054 | raise TemplatesNotFound(
1055 | message="Tried to select from an empty list of templates."
1056 | )
1057 |
1058 | for name in names:
1059 | if isinstance(name, Template):
1060 | return name
1061 | if parent is not None:
1062 | name = self.join_path(name, parent)
1063 | try:
1064 | return self._load_template(name, globals)
1065 | except (TemplateNotFound, UndefinedError):
1066 | pass
1067 | raise TemplatesNotFound(names) # type: ignore
1068 |
1069 | @internalcode
1070 | def get_or_select_template(
1071 | self,
1072 | template_name_or_list: t.Union[
1073 | str, "Template", t.List[t.Union[str, "Template"]]
1074 | ],
1075 | parent: t.Optional[str] = None,
1076 | globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1077 | ) -> "Template":
1078 | """Use :meth:`select_template` if an iterable of template names
1079 | is given, or :meth:`get_template` if one name is given.
1080 |
1081 | .. versionadded:: 2.3
1082 | """
1083 | if isinstance(template_name_or_list, (str, Undefined)):
1084 | return self.get_template(template_name_or_list, parent, globals)
1085 | elif isinstance(template_name_or_list, Template):
1086 | return template_name_or_list
1087 | return self.select_template(template_name_or_list, parent, globals)
1088 |
1089 | def from_string(
1090 | self,
1091 | source: t.Union[str, nodes.Template],
1092 | globals: t.Optional[t.MutableMapping[str, t.Any]] = None,
1093 | template_class: t.Optional[t.Type["Template"]] = None,
1094 | ) -> "Template":
1095 | """Load a template from a source string without using
1096 | :attr:`loader`.
1097 |
1098 | :param source: Jinja source to compile into a template.
1099 | :param globals: Extend the environment :attr:`globals` with
1100 | these extra variables available for all renders of this
1101 | template. If the template has already been loaded and
1102 | cached, its globals are updated with any new items.
1103 | :param template_class: Return an instance of this
1104 | :class:`Template` class.
1105 | """
1106 | gs = self.make_globals(globals)
1107 | cls = template_class or self.template_class
1108 | return cls.from_code(self, self.compile(source), gs, None)
1109 |
1110 | def make_globals(
1111 | self, d: t.Optional[t.MutableMapping[str, t.Any]]
1112 | ) -> t.MutableMapping[str, t.Any]:
1113 | """Make the globals map for a template. Any given template
1114 | globals overlay the environment :attr:`globals`.
1115 |
1116 | Returns a :class:`collections.ChainMap`. This allows any changes
1117 | to a template's globals to only affect that template, while
1118 | changes to the environment's globals are still reflected.
1119 | However, avoid modifying any globals after a template is loaded.
1120 |
1121 | :param d: Dict of template-specific globals.
1122 |
1123 | .. versionchanged:: 3.0
1124 | Use :class:`collections.ChainMap` to always prevent mutating
1125 | environment globals.
1126 | """
1127 | if d is None:
1128 | d = {}
1129 |
1130 | return ChainMap(d, self.globals)
1131 |
1132 |
1133 | class Template:
1134 | """A compiled template that can be rendered.
1135 |
1136 | Use the methods on :class:`Environment` to create or load templates.
1137 | The environment is used to configure how templates are compiled and
1138 | behave.
1139 |
1140 | It is also possible to create a template object directly. This is
1141 | not usually recommended. The constructor takes most of the same
1142 | arguments as :class:`Environment`. All templates created with the
1143 | same environment arguments share the same ephemeral ``Environment``
1144 | instance behind the scenes.
1145 |
1146 | A template object should be considered immutable. Modifications on
1147 | the object are not supported.
1148 | """
1149 |
1150 | #: Type of environment to create when creating a template directly
1151 | #: rather than through an existing environment.
1152 | environment_class: t.Type[Environment] = Environment
1153 |
1154 | environment: Environment
1155 | globals: t.MutableMapping[str, t.Any]
1156 | name: t.Optional[str]
1157 | filename: t.Optional[str]
1158 | blocks: t.Dict[str, t.Callable[[Context], t.Iterator[str]]]
1159 | root_render_func: t.Callable[[Context], t.Iterator[str]]
1160 | _module: t.Optional["TemplateModule"]
1161 | _debug_info: str
1162 | _uptodate: t.Optional[t.Callable[[], bool]]
1163 |
1164 | def __new__(
1165 | cls,
1166 | source: t.Union[str, nodes.Template],
1167 | block_start_string: str = BLOCK_START_STRING,
1168 | block_end_string: str = BLOCK_END_STRING,
1169 | variable_start_string: str = VARIABLE_START_STRING,
1170 | variable_end_string: str = VARIABLE_END_STRING,
1171 | comment_start_string: str = COMMENT_START_STRING,
1172 | comment_end_string: str = COMMENT_END_STRING,
1173 | line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX,
1174 | line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX,
1175 | trim_blocks: bool = TRIM_BLOCKS,
1176 | lstrip_blocks: bool = LSTRIP_BLOCKS,
1177 | newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE,
1178 | keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE,
1179 | extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (),
1180 | optimized: bool = True,
1181 | undefined: t.Type[Undefined] = Undefined,
1182 | finalize: t.Optional[t.Callable[..., t.Any]] = None,
1183 | autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False,
1184 | enable_async: bool = False,
1185 | ) -> t.Any: # it returns a `Template`, but this breaks the sphinx build...
1186 | env = get_spontaneous_environment(
1187 | cls.environment_class, # type: ignore
1188 | block_start_string,
1189 | block_end_string,
1190 | variable_start_string,
1191 | variable_end_string,
1192 | comment_start_string,
1193 | comment_end_string,
1194 | line_statement_prefix,
1195 | line_comment_prefix,
1196 | trim_blocks,
1197 | lstrip_blocks,
1198 | newline_sequence,
1199 | keep_trailing_newline,
1200 | frozenset(extensions),
1201 | optimized,
1202 | undefined, # type: ignore
1203 | finalize,
1204 | autoescape,
1205 | None,
1206 | 0,
1207 | False,
1208 | None,
1209 | enable_async,
1210 | )
1211 | return env.from_string(source, template_class=cls)
1212 |
1213 | @classmethod
1214 | def from_code(
1215 | cls,
1216 | environment: Environment,
1217 | code: CodeType,
1218 | globals: t.MutableMapping[str, t.Any],
1219 | uptodate: t.Optional[t.Callable[[], bool]] = None,
1220 | ) -> "Template":
1221 | """Creates a template object from compiled code and the globals. This
1222 | is used by the loaders and environment to create a template object.
1223 | """
1224 | namespace = {"environment": environment, "__file__": code.co_filename}
1225 | exec(code, namespace)
1226 | rv = cls._from_namespace(environment, namespace, globals)
1227 | rv._uptodate = uptodate
1228 | return rv
1229 |
1230 | @classmethod
1231 | def from_module_dict(
1232 | cls,
1233 | environment: Environment,
1234 | module_dict: t.MutableMapping[str, t.Any],
1235 | globals: t.MutableMapping[str, t.Any],
1236 | ) -> "Template":
1237 | """Creates a template object from a module. This is used by the
1238 | module loader to create a template object.
1239 |
1240 | .. versionadded:: 2.4
1241 | """
1242 | return cls._from_namespace(environment, module_dict, globals)
1243 |
1244 | @classmethod
1245 | def _from_namespace(
1246 | cls,
1247 | environment: Environment,
1248 | namespace: t.MutableMapping[str, t.Any],
1249 | globals: t.MutableMapping[str, t.Any],
1250 | ) -> "Template":
1251 | t: "Template" = object.__new__(cls)
1252 | t.environment = environment
1253 | t.globals = globals
1254 | t.name = namespace["name"]
1255 | t.filename = namespace["__file__"]
1256 | t.blocks = namespace["blocks"]
1257 |
1258 | # render function and module
1259 | t.root_render_func = namespace["root"]
1260 | t._module = None
1261 |
1262 | # debug and loader helpers
1263 | t._debug_info = namespace["debug_info"]
1264 | t._uptodate = None
1265 |
1266 | # store the reference
1267 | namespace["environment"] = environment
1268 | namespace["__jinja_template__"] = t
1269 |
1270 | return t
1271 |
1272 | def render(self, *args: t.Any, **kwargs: t.Any) -> str:
1273 | """This method accepts the same arguments as the `dict` constructor:
1274 | A dict, a dict subclass or some keyword arguments. If no arguments
1275 | are given the context will be empty. These two calls do the same::
1276 |
1277 | template.render(knights='that say nih')
1278 | template.render({'knights': 'that say nih'})
1279 |
1280 | This will return the rendered template as a string.
1281 | """
1282 | if self.environment.is_async:
1283 | import asyncio
1284 |
1285 | close = False
1286 |
1287 | try:
1288 | loop = asyncio.get_running_loop()
1289 | except RuntimeError:
1290 | loop = asyncio.new_event_loop()
1291 | close = True
1292 |
1293 | try:
1294 | return loop.run_until_complete(self.render_async(*args, **kwargs))
1295 | finally:
1296 | if close:
1297 | loop.close()
1298 |
1299 | ctx = self.new_context(dict(*args, **kwargs))
1300 |
1301 | try:
1302 | return self.environment.concat(self.root_render_func(ctx)) # type: ignore
1303 | except Exception:
1304 | self.environment.handle_exception()
1305 |
1306 | async def render_async(self, *args: t.Any, **kwargs: t.Any) -> str:
1307 | """This works similar to :meth:`render` but returns a coroutine
1308 | that when awaited returns the entire rendered template string. This
1309 | requires the async feature to be enabled.
1310 |
1311 | Example usage::
1312 |
1313 | await template.render_async(knights='that say nih; asynchronously')
1314 | """
1315 | if not self.environment.is_async:
1316 | raise RuntimeError(
1317 | "The environment was not created with async mode enabled."
1318 | )
1319 |
1320 | ctx = self.new_context(dict(*args, **kwargs))
1321 |
1322 | try:
1323 | return self.environment.concat( # type: ignore
1324 | [n async for n in self.root_render_func(ctx)] # type: ignore
1325 | )
1326 | except Exception:
1327 | return self.environment.handle_exception()
1328 |
1329 | def stream(self, *args: t.Any, **kwargs: t.Any) -> "TemplateStream":
1330 | """Works exactly like :meth:`generate` but returns a
1331 | :class:`TemplateStream`.
1332 | """
1333 | return TemplateStream(self.generate(*args, **kwargs))
1334 |
1335 | def generate(self, *args: t.Any, **kwargs: t.Any) -> t.Iterator[str]:
1336 | """For very large templates it can be useful to not render the whole
1337 | template at once but evaluate each statement after another and yield
1338 | piece for piece. This method basically does exactly that and returns
1339 | a generator that yields one item after another as strings.
1340 |
1341 | It accepts the same arguments as :meth:`render`.
1342 | """
1343 | if self.environment.is_async:
1344 | import asyncio
1345 |
1346 | async def to_list() -> t.List[str]:
1347 | return [x async for x in self.generate_async(*args, **kwargs)]
1348 |
1349 | yield from asyncio.run(to_list())
1350 | return
1351 |
1352 | ctx = self.new_context(dict(*args, **kwargs))
1353 |
1354 | try:
1355 | yield from self.root_render_func(ctx)
1356 | except Exception:
1357 | yield self.environment.handle_exception()
1358 |
1359 | async def generate_async(
1360 | self, *args: t.Any, **kwargs: t.Any
1361 | ) -> t.AsyncIterator[str]:
1362 | """An async version of :meth:`generate`. Works very similarly but
1363 | returns an async iterator instead.
1364 | """
1365 | if not self.environment.is_async:
1366 | raise RuntimeError(
1367 | "The environment was not created with async mode enabled."
1368 | )
1369 |
1370 | ctx = self.new_context(dict(*args, **kwargs))
1371 |
1372 | try:
1373 | async for event in self.root_render_func(ctx): # type: ignore
1374 | yield event
1375 | except Exception:
1376 | yield self.environment.handle_exception()
1377 |
1378 | def new_context(
1379 | self,
1380 | vars: t.Optional[t.Dict[str, t.Any]] = None,
1381 | shared: bool = False,
1382 | locals: t.Optional[t.Mapping[str, t.Any]] = None,
1383 | ) -> Context:
1384 | """Create a new :class:`Context` for this template. The vars
1385 | provided will be passed to the template. Per default the globals
1386 | are added to the context. If shared is set to `True` the data
1387 | is passed as is to the context without adding the globals.
1388 |
1389 | `locals` can be a dict of local variables for internal usage.
1390 | """
1391 | return new_context(
1392 | self.environment, self.name, self.blocks, vars, shared, self.globals, locals
1393 | )
1394 |
1395 | def make_module(
1396 | self,
1397 | vars: t.Optional[t.Dict[str, t.Any]] = None,
1398 | shared: bool = False,
1399 | locals: t.Optional[t.Mapping[str, t.Any]] = None,
1400 | ) -> "TemplateModule":
1401 | """This method works like the :attr:`module` attribute when called
1402 | without arguments but it will evaluate the template on every call
1403 | rather than caching it. It's also possible to provide
1404 | a dict which is then used as context. The arguments are the same
1405 | as for the :meth:`new_context` method.
1406 | """
1407 | ctx = self.new_context(vars, shared, locals)
1408 | return TemplateModule(self, ctx)
1409 |
1410 | async def make_module_async(
1411 | self,
1412 | vars: t.Optional[t.Dict[str, t.Any]] = None,
1413 | shared: bool = False,
1414 | locals: t.Optional[t.Mapping[str, t.Any]] = None,
1415 | ) -> "TemplateModule":
1416 | """As template module creation can invoke template code for
1417 | asynchronous executions this method must be used instead of the
1418 | normal :meth:`make_module` one. Likewise the module attribute
1419 | becomes unavailable in async mode.
1420 | """
1421 | ctx = self.new_context(vars, shared, locals)
1422 | return TemplateModule(
1423 | self,
1424 | ctx,
1425 | [x async for x in self.root_render_func(ctx)], # type: ignore
1426 | )
1427 |
1428 | @internalcode
1429 | def _get_default_module(self, ctx: t.Optional[Context] = None) -> "TemplateModule":
1430 | """If a context is passed in, this means that the template was
1431 | imported. Imported templates have access to the current
1432 | template's globals by default, but they can only be accessed via
1433 | the context during runtime.
1434 |
1435 | If there are new globals, we need to create a new module because
1436 | the cached module is already rendered and will not have access
1437 | to globals from the current context. This new module is not
1438 | cached because the template can be imported elsewhere, and it
1439 | should have access to only the current template's globals.
1440 | """
1441 | if self.environment.is_async:
1442 | raise RuntimeError("Module is not available in async mode.")
1443 |
1444 | if ctx is not None:
1445 | keys = ctx.globals_keys - self.globals.keys()
1446 |
1447 | if keys:
1448 | return self.make_module({k: ctx.parent[k] for k in keys})
1449 |
1450 | if self._module is None:
1451 | self._module = self.make_module()
1452 |
1453 | return self._module
1454 |
1455 | async def _get_default_module_async(
1456 | self, ctx: t.Optional[Context] = None
1457 | ) -> "TemplateModule":
1458 | if ctx is not None:
1459 | keys = ctx.globals_keys - self.globals.keys()
1460 |
1461 | if keys:
1462 | return await self.make_module_async({k: ctx.parent[k] for k in keys})
1463 |
1464 | if self._module is None:
1465 | self._module = await self.make_module_async()
1466 |
1467 | return self._module
1468 |
1469 | @property
1470 | def module(self) -> "TemplateModule":
1471 | """The template as module. This is used for imports in the
1472 | template runtime but is also useful if one wants to access
1473 | exported template variables from the Python layer:
1474 |
1475 | >>> t = Template('{% macro foo() %}42{% endmacro %}23')
1476 | >>> str(t.module)
1477 | '23'
1478 | >>> t.module.foo() == u'42'
1479 | True
1480 |
1481 | This attribute is not available if async mode is enabled.
1482 | """
1483 | return self._get_default_module()
1484 |
1485 | def get_corresponding_lineno(self, lineno: int) -> int:
1486 | """Return the source line number of a line number in the
1487 | generated bytecode as they are not in sync.
1488 | """
1489 | for template_line, code_line in reversed(self.debug_info):
1490 | if code_line <= lineno:
1491 | return template_line
1492 | return 1
1493 |
1494 | @property
1495 | def is_up_to_date(self) -> bool:
1496 | """If this variable is `False` there is a newer version available."""
1497 | if self._uptodate is None:
1498 | return True
1499 | return self._uptodate()
1500 |
1501 | @property
1502 | def debug_info(self) -> t.List[t.Tuple[int, int]]:
1503 | """The debug info mapping."""
1504 | if self._debug_info:
1505 | return [
1506 | tuple(map(int, x.split("="))) # type: ignore
1507 | for x in self._debug_info.split("&")
1508 | ]
1509 |
1510 | return []
1511 |
1512 | def __repr__(self) -> str:
1513 | if self.name is None:
1514 | name = f"memory:{id(self):x}"
1515 | else:
1516 | name = repr(self.name)
1517 | return f"<{type(self).__name__} {name}>"
1518 |
1519 |
1520 | class TemplateModule:
1521 | """Represents an imported template. All the exported names of the
1522 | template are available as attributes on this object. Additionally
1523 | converting it into a string renders the contents.
1524 | """
1525 |
1526 | def __init__(
1527 | self,
1528 | template: Template,
1529 | context: Context,
1530 | body_stream: t.Optional[t.Iterable[str]] = None,
1531 | ) -> None:
1532 | if body_stream is None:
1533 | if context.environment.is_async:
1534 | raise RuntimeError(
1535 | "Async mode requires a body stream to be passed to"
1536 | " a template module. Use the async methods of the"
1537 | " API you are using."
1538 | )
1539 |
1540 | body_stream = list(template.root_render_func(context))
1541 |
1542 | self._body_stream = body_stream
1543 | self.__dict__.update(context.get_exported())
1544 | self.__name__ = template.name
1545 |
1546 | def __html__(self) -> Markup:
1547 | return Markup(concat(self._body_stream))
1548 |
1549 | def __str__(self) -> str:
1550 | return concat(self._body_stream)
1551 |
1552 | def __repr__(self) -> str:
1553 | if self.__name__ is None:
1554 | name = f"memory:{id(self):x}"
1555 | else:
1556 | name = repr(self.__name__)
1557 | return f"<{type(self).__name__} {name}>"
1558 |
1559 |
1560 | class TemplateExpression:
1561 | """The :meth:`jinja2.Environment.compile_expression` method returns an
1562 | instance of this object. It encapsulates the expression-like access
1563 | to the template with an expression it wraps.
1564 | """
1565 |
1566 | def __init__(self, template: Template, undefined_to_none: bool) -> None:
1567 | self._template = template
1568 | self._undefined_to_none = undefined_to_none
1569 |
1570 | def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]:
1571 | context = self._template.new_context(dict(*args, **kwargs))
1572 | consume(self._template.root_render_func(context))
1573 | rv = context.vars["result"]
1574 | if self._undefined_to_none and isinstance(rv, Undefined):
1575 | rv = None
1576 | return rv
1577 |
1578 |
1579 | class TemplateStream:
1580 | """A template stream works pretty much like an ordinary python generator
1581 | but it can buffer multiple items to reduce the number of total iterations.
1582 | Per default the output is unbuffered which means that for every unbuffered
1583 | instruction in the template one string is yielded.
1584 |
1585 | If buffering is enabled with a buffer size of 5, five items are combined
1586 | into a new string. This is mainly useful if you are streaming
1587 | big templates to a client via WSGI which flushes after each iteration.
1588 | """
1589 |
1590 | def __init__(self, gen: t.Iterator[str]) -> None:
1591 | self._gen = gen
1592 | self.disable_buffering()
1593 |
1594 | def dump(
1595 | self,
1596 | fp: t.Union[str, t.IO[bytes]],
1597 | encoding: t.Optional[str] = None,
1598 | errors: t.Optional[str] = "strict",
1599 | ) -> None:
1600 | """Dump the complete stream into a file or file-like object.
1601 | Per default strings are written, if you want to encode
1602 | before writing specify an `encoding`.
1603 |
1604 | Example usage::
1605 |
1606 | Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
1607 | """
1608 | close = False
1609 |
1610 | if isinstance(fp, str):
1611 | if encoding is None:
1612 | encoding = "utf-8"
1613 |
1614 | real_fp: t.IO[bytes] = open(fp, "wb")
1615 | close = True
1616 | else:
1617 | real_fp = fp
1618 |
1619 | try:
1620 | if encoding is not None:
1621 | iterable = (x.encode(encoding, errors) for x in self) # type: ignore
1622 | else:
1623 | iterable = self # type: ignore
1624 |
1625 | if hasattr(real_fp, "writelines"):
1626 | real_fp.writelines(iterable)
1627 | else:
1628 | for item in iterable:
1629 | real_fp.write(item)
1630 | finally:
1631 | if close:
1632 | real_fp.close()
1633 |
1634 | def disable_buffering(self) -> None:
1635 | """Disable the output buffering."""
1636 | self._next = partial(next, self._gen)
1637 | self.buffered = False
1638 |
1639 | def _buffered_generator(self, size: int) -> t.Iterator[str]:
1640 | buf: t.List[str] = []
1641 | c_size = 0
1642 | push = buf.append
1643 |
1644 | while True:
1645 | try:
1646 | while c_size < size:
1647 | c = next(self._gen)
1648 | push(c)
1649 | if c:
1650 | c_size += 1
1651 | except StopIteration:
1652 | if not c_size:
1653 | return
1654 | yield concat(buf)
1655 | del buf[:]
1656 | c_size = 0
1657 |
1658 | def enable_buffering(self, size: int = 5) -> None:
1659 | """Enable buffering. Buffer `size` items before yielding them."""
1660 | if size <= 1:
1661 | raise ValueError("buffer size too small")
1662 |
1663 | self.buffered = True
1664 | self._next = partial(next, self._buffered_generator(size))
1665 |
1666 | def __iter__(self) -> "TemplateStream":
1667 | return self
1668 |
1669 | def __next__(self) -> str:
1670 | return self._next() # type: ignore
1671 |
1672 |
1673 | # hook in default template class. if anyone reads this comment: ignore that
1674 | # it's possible to use custom templates ;-)
1675 | Environment.template_class = Template
1676 |
```