This is page 48 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/markupsafe/__init__.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import collections.abc as cabc
4 | import string
5 | import typing as t
6 |
7 | try:
8 | from ._speedups import _escape_inner
9 | except ImportError:
10 | from ._native import _escape_inner
11 |
12 | if t.TYPE_CHECKING:
13 | import typing_extensions as te
14 |
15 |
16 | class _HasHTML(t.Protocol):
17 | def __html__(self, /) -> str: ...
18 |
19 |
20 | class _TPEscape(t.Protocol):
21 | def __call__(self, s: t.Any, /) -> Markup: ...
22 |
23 |
24 | def escape(s: t.Any, /) -> Markup:
25 | """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in
26 | the string with HTML-safe sequences. Use this if you need to display
27 | text that might contain such characters in HTML.
28 |
29 | If the object has an ``__html__`` method, it is called and the
30 | return value is assumed to already be safe for HTML.
31 |
32 | :param s: An object to be converted to a string and escaped.
33 | :return: A :class:`Markup` string with the escaped text.
34 | """
35 | # If the object is already a plain string, skip __html__ check and string
36 | # conversion. This is the most common use case.
37 | # Use type(s) instead of s.__class__ because a proxy object may be reporting
38 | # the __class__ of the proxied value.
39 | if type(s) is str:
40 | return Markup(_escape_inner(s))
41 |
42 | if hasattr(s, "__html__"):
43 | return Markup(s.__html__())
44 |
45 | return Markup(_escape_inner(str(s)))
46 |
47 |
48 | def escape_silent(s: t.Any | None, /) -> Markup:
49 | """Like :func:`escape` but treats ``None`` as the empty string.
50 | Useful with optional values, as otherwise you get the string
51 | ``'None'`` when the value is ``None``.
52 |
53 | >>> escape(None)
54 | Markup('None')
55 | >>> escape_silent(None)
56 | Markup('')
57 | """
58 | if s is None:
59 | return Markup()
60 |
61 | return escape(s)
62 |
63 |
64 | def soft_str(s: t.Any, /) -> str:
65 | """Convert an object to a string if it isn't already. This preserves
66 | a :class:`Markup` string rather than converting it back to a basic
67 | string, so it will still be marked as safe and won't be escaped
68 | again.
69 |
70 | >>> value = escape("<User 1>")
71 | >>> value
72 | Markup('<User 1>')
73 | >>> escape(str(value))
74 | Markup('&lt;User 1&gt;')
75 | >>> escape(soft_str(value))
76 | Markup('<User 1>')
77 | """
78 | if not isinstance(s, str):
79 | return str(s)
80 |
81 | return s
82 |
83 |
84 | class Markup(str):
85 | """A string that is ready to be safely inserted into an HTML or XML
86 | document, either because it was escaped or because it was marked
87 | safe.
88 |
89 | Passing an object to the constructor converts it to text and wraps
90 | it to mark it safe without escaping. To escape the text, use the
91 | :meth:`escape` class method instead.
92 |
93 | >>> Markup("Hello, <em>World</em>!")
94 | Markup('Hello, <em>World</em>!')
95 | >>> Markup(42)
96 | Markup('42')
97 | >>> Markup.escape("Hello, <em>World</em>!")
98 | Markup('Hello <em>World</em>!')
99 |
100 | This implements the ``__html__()`` interface that some frameworks
101 | use. Passing an object that implements ``__html__()`` will wrap the
102 | output of that method, marking it safe.
103 |
104 | >>> class Foo:
105 | ... def __html__(self):
106 | ... return '<a href="/foo">foo</a>'
107 | ...
108 | >>> Markup(Foo())
109 | Markup('<a href="/foo">foo</a>')
110 |
111 | This is a subclass of :class:`str`. It has the same methods, but
112 | escapes their arguments and returns a ``Markup`` instance.
113 |
114 | >>> Markup("<em>%s</em>") % ("foo & bar",)
115 | Markup('<em>foo & bar</em>')
116 | >>> Markup("<em>Hello</em> ") + "<foo>"
117 | Markup('<em>Hello</em> <foo>')
118 | """
119 |
120 | __slots__ = ()
121 |
122 | def __new__(
123 | cls, object: t.Any = "", encoding: str | None = None, errors: str = "strict"
124 | ) -> te.Self:
125 | if hasattr(object, "__html__"):
126 | object = object.__html__()
127 |
128 | if encoding is None:
129 | return super().__new__(cls, object)
130 |
131 | return super().__new__(cls, object, encoding, errors)
132 |
133 | def __html__(self, /) -> te.Self:
134 | return self
135 |
136 | def __add__(self, value: str | _HasHTML, /) -> te.Self:
137 | if isinstance(value, str) or hasattr(value, "__html__"):
138 | return self.__class__(super().__add__(self.escape(value)))
139 |
140 | return NotImplemented
141 |
142 | def __radd__(self, value: str | _HasHTML, /) -> te.Self:
143 | if isinstance(value, str) or hasattr(value, "__html__"):
144 | return self.escape(value).__add__(self)
145 |
146 | return NotImplemented
147 |
148 | def __mul__(self, value: t.SupportsIndex, /) -> te.Self:
149 | return self.__class__(super().__mul__(value))
150 |
151 | def __rmul__(self, value: t.SupportsIndex, /) -> te.Self:
152 | return self.__class__(super().__mul__(value))
153 |
154 | def __mod__(self, value: t.Any, /) -> te.Self:
155 | if isinstance(value, tuple):
156 | # a tuple of arguments, each wrapped
157 | value = tuple(_MarkupEscapeHelper(x, self.escape) for x in value)
158 | elif hasattr(type(value), "__getitem__") and not isinstance(value, str):
159 | # a mapping of arguments, wrapped
160 | value = _MarkupEscapeHelper(value, self.escape)
161 | else:
162 | # a single argument, wrapped with the helper and a tuple
163 | value = (_MarkupEscapeHelper(value, self.escape),)
164 |
165 | return self.__class__(super().__mod__(value))
166 |
167 | def __repr__(self, /) -> str:
168 | return f"{self.__class__.__name__}({super().__repr__()})"
169 |
170 | def join(self, iterable: cabc.Iterable[str | _HasHTML], /) -> te.Self:
171 | return self.__class__(super().join(map(self.escape, iterable)))
172 |
173 | def split( # type: ignore[override]
174 | self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1
175 | ) -> list[te.Self]:
176 | return [self.__class__(v) for v in super().split(sep, maxsplit)]
177 |
178 | def rsplit( # type: ignore[override]
179 | self, /, sep: str | None = None, maxsplit: t.SupportsIndex = -1
180 | ) -> list[te.Self]:
181 | return [self.__class__(v) for v in super().rsplit(sep, maxsplit)]
182 |
183 | def splitlines( # type: ignore[override]
184 | self, /, keepends: bool = False
185 | ) -> list[te.Self]:
186 | return [self.__class__(v) for v in super().splitlines(keepends)]
187 |
188 | def unescape(self, /) -> str:
189 | """Convert escaped markup back into a text string. This replaces
190 | HTML entities with the characters they represent.
191 |
192 | >>> Markup("Main » <em>About</em>").unescape()
193 | 'Main » <em>About</em>'
194 | """
195 | from html import unescape
196 |
197 | return unescape(str(self))
198 |
199 | def striptags(self, /) -> str:
200 | """:meth:`unescape` the markup, remove tags, and normalize
201 | whitespace to single spaces.
202 |
203 | >>> Markup("Main »\t<em>About</em>").striptags()
204 | 'Main » About'
205 | """
206 | value = str(self)
207 |
208 | # Look for comments then tags separately. Otherwise, a comment that
209 | # contains a tag would end early, leaving some of the comment behind.
210 |
211 | # keep finding comment start marks
212 | while (start := value.find("<!--")) != -1:
213 | # find a comment end mark beyond the start, otherwise stop
214 | if (end := value.find("-->", start)) == -1:
215 | break
216 |
217 | value = f"{value[:start]}{value[end + 3:]}"
218 |
219 | # remove tags using the same method
220 | while (start := value.find("<")) != -1:
221 | if (end := value.find(">", start)) == -1:
222 | break
223 |
224 | value = f"{value[:start]}{value[end + 1:]}"
225 |
226 | # collapse spaces
227 | value = " ".join(value.split())
228 | return self.__class__(value).unescape()
229 |
230 | @classmethod
231 | def escape(cls, s: t.Any, /) -> te.Self:
232 | """Escape a string. Calls :func:`escape` and ensures that for
233 | subclasses the correct type is returned.
234 | """
235 | rv = escape(s)
236 |
237 | if rv.__class__ is not cls:
238 | return cls(rv)
239 |
240 | return rv # type: ignore[return-value]
241 |
242 | def __getitem__(self, key: t.SupportsIndex | slice, /) -> te.Self:
243 | return self.__class__(super().__getitem__(key))
244 |
245 | def capitalize(self, /) -> te.Self:
246 | return self.__class__(super().capitalize())
247 |
248 | def title(self, /) -> te.Self:
249 | return self.__class__(super().title())
250 |
251 | def lower(self, /) -> te.Self:
252 | return self.__class__(super().lower())
253 |
254 | def upper(self, /) -> te.Self:
255 | return self.__class__(super().upper())
256 |
257 | def replace(self, old: str, new: str, count: t.SupportsIndex = -1, /) -> te.Self:
258 | return self.__class__(super().replace(old, self.escape(new), count))
259 |
260 | def ljust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
261 | return self.__class__(super().ljust(width, self.escape(fillchar)))
262 |
263 | def rjust(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
264 | return self.__class__(super().rjust(width, self.escape(fillchar)))
265 |
266 | def lstrip(self, chars: str | None = None, /) -> te.Self:
267 | return self.__class__(super().lstrip(chars))
268 |
269 | def rstrip(self, chars: str | None = None, /) -> te.Self:
270 | return self.__class__(super().rstrip(chars))
271 |
272 | def center(self, width: t.SupportsIndex, fillchar: str = " ", /) -> te.Self:
273 | return self.__class__(super().center(width, self.escape(fillchar)))
274 |
275 | def strip(self, chars: str | None = None, /) -> te.Self:
276 | return self.__class__(super().strip(chars))
277 |
278 | def translate(
279 | self,
280 | table: cabc.Mapping[int, str | int | None], # type: ignore[override]
281 | /,
282 | ) -> str:
283 | return self.__class__(super().translate(table))
284 |
285 | def expandtabs(self, /, tabsize: t.SupportsIndex = 8) -> te.Self:
286 | return self.__class__(super().expandtabs(tabsize))
287 |
288 | def swapcase(self, /) -> te.Self:
289 | return self.__class__(super().swapcase())
290 |
291 | def zfill(self, width: t.SupportsIndex, /) -> te.Self:
292 | return self.__class__(super().zfill(width))
293 |
294 | def casefold(self, /) -> te.Self:
295 | return self.__class__(super().casefold())
296 |
297 | def removeprefix(self, prefix: str, /) -> te.Self:
298 | return self.__class__(super().removeprefix(prefix))
299 |
300 | def removesuffix(self, suffix: str) -> te.Self:
301 | return self.__class__(super().removesuffix(suffix))
302 |
303 | def partition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]:
304 | left, sep, right = super().partition(sep)
305 | cls = self.__class__
306 | return cls(left), cls(sep), cls(right)
307 |
308 | def rpartition(self, sep: str, /) -> tuple[te.Self, te.Self, te.Self]:
309 | left, sep, right = super().rpartition(sep)
310 | cls = self.__class__
311 | return cls(left), cls(sep), cls(right)
312 |
313 | def format(self, *args: t.Any, **kwargs: t.Any) -> te.Self:
314 | formatter = EscapeFormatter(self.escape)
315 | return self.__class__(formatter.vformat(self, args, kwargs))
316 |
317 | def format_map(
318 | self,
319 | mapping: cabc.Mapping[str, t.Any], # type: ignore[override]
320 | /,
321 | ) -> te.Self:
322 | formatter = EscapeFormatter(self.escape)
323 | return self.__class__(formatter.vformat(self, (), mapping))
324 |
325 | def __html_format__(self, format_spec: str, /) -> te.Self:
326 | if format_spec:
327 | raise ValueError("Unsupported format specification for Markup.")
328 |
329 | return self
330 |
331 |
332 | class EscapeFormatter(string.Formatter):
333 | __slots__ = ("escape",)
334 |
335 | def __init__(self, escape: _TPEscape) -> None:
336 | self.escape: _TPEscape = escape
337 | super().__init__()
338 |
339 | def format_field(self, value: t.Any, format_spec: str) -> str:
340 | if hasattr(value, "__html_format__"):
341 | rv = value.__html_format__(format_spec)
342 | elif hasattr(value, "__html__"):
343 | if format_spec:
344 | raise ValueError(
345 | f"Format specifier {format_spec} given, but {type(value)} does not"
346 | " define __html_format__. A class that defines __html__ must define"
347 | " __html_format__ to work with format specifiers."
348 | )
349 | rv = value.__html__()
350 | else:
351 | # We need to make sure the format spec is str here as
352 | # otherwise the wrong callback methods are invoked.
353 | rv = super().format_field(value, str(format_spec))
354 | return str(self.escape(rv))
355 |
356 |
357 | class _MarkupEscapeHelper:
358 | """Helper for :meth:`Markup.__mod__`."""
359 |
360 | __slots__ = ("obj", "escape")
361 |
362 | def __init__(self, obj: t.Any, escape: _TPEscape) -> None:
363 | self.obj: t.Any = obj
364 | self.escape: _TPEscape = escape
365 |
366 | def __getitem__(self, key: t.Any, /) -> te.Self:
367 | return self.__class__(self.obj[key], self.escape)
368 |
369 | def __str__(self, /) -> str:
370 | return str(self.escape(self.obj))
371 |
372 | def __repr__(self, /) -> str:
373 | return str(self.escape(repr(self.obj)))
374 |
375 | def __int__(self, /) -> int:
376 | return int(self.obj)
377 |
378 | def __float__(self, /) -> float:
379 | return float(self.obj)
380 |
381 |
382 | def __getattr__(name: str) -> t.Any:
383 | if name == "__version__":
384 | import importlib.metadata
385 | import warnings
386 |
387 | warnings.warn(
388 | "The '__version__' attribute is deprecated and will be removed in"
389 | " MarkupSafe 3.1. Use feature detection, or"
390 | ' `importlib.metadata.version("markupsafe")`, instead.',
391 | stacklevel=2,
392 | )
393 | return importlib.metadata.version("markupsafe")
394 |
395 | raise AttributeError(name)
396 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/idna/core.py:
--------------------------------------------------------------------------------
```python
1 | import bisect
2 | import re
3 | import unicodedata
4 | from typing import Optional, Union
5 |
6 | from . import idnadata
7 | from .intranges import intranges_contain
8 |
9 | _virama_combining_class = 9
10 | _alabel_prefix = b"xn--"
11 | _unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]")
12 |
13 |
14 | class IDNAError(UnicodeError):
15 | """Base exception for all IDNA-encoding related problems"""
16 |
17 | pass
18 |
19 |
20 | class IDNABidiError(IDNAError):
21 | """Exception when bidirectional requirements are not satisfied"""
22 |
23 | pass
24 |
25 |
26 | class InvalidCodepoint(IDNAError):
27 | """Exception when a disallowed or unallocated codepoint is used"""
28 |
29 | pass
30 |
31 |
32 | class InvalidCodepointContext(IDNAError):
33 | """Exception when the codepoint is not valid in the context it is used"""
34 |
35 | pass
36 |
37 |
38 | def _combining_class(cp: int) -> int:
39 | v = unicodedata.combining(chr(cp))
40 | if v == 0:
41 | if not unicodedata.name(chr(cp)):
42 | raise ValueError("Unknown character in unicodedata")
43 | return v
44 |
45 |
46 | def _is_script(cp: str, script: str) -> bool:
47 | return intranges_contain(ord(cp), idnadata.scripts[script])
48 |
49 |
50 | def _punycode(s: str) -> bytes:
51 | return s.encode("punycode")
52 |
53 |
54 | def _unot(s: int) -> str:
55 | return "U+{:04X}".format(s)
56 |
57 |
58 | def valid_label_length(label: Union[bytes, str]) -> bool:
59 | if len(label) > 63:
60 | return False
61 | return True
62 |
63 |
64 | def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool:
65 | if len(label) > (254 if trailing_dot else 253):
66 | return False
67 | return True
68 |
69 |
70 | def check_bidi(label: str, check_ltr: bool = False) -> bool:
71 | # Bidi rules should only be applied if string contains RTL characters
72 | bidi_label = False
73 | for idx, cp in enumerate(label, 1):
74 | direction = unicodedata.bidirectional(cp)
75 | if direction == "":
76 | # String likely comes from a newer version of Unicode
77 | raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx))
78 | if direction in ["R", "AL", "AN"]:
79 | bidi_label = True
80 | if not bidi_label and not check_ltr:
81 | return True
82 |
83 | # Bidi rule 1
84 | direction = unicodedata.bidirectional(label[0])
85 | if direction in ["R", "AL"]:
86 | rtl = True
87 | elif direction == "L":
88 | rtl = False
89 | else:
90 | raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label)))
91 |
92 | valid_ending = False
93 | number_type: Optional[str] = None
94 | for idx, cp in enumerate(label, 1):
95 | direction = unicodedata.bidirectional(cp)
96 |
97 | if rtl:
98 | # Bidi rule 2
99 | if direction not in [
100 | "R",
101 | "AL",
102 | "AN",
103 | "EN",
104 | "ES",
105 | "CS",
106 | "ET",
107 | "ON",
108 | "BN",
109 | "NSM",
110 | ]:
111 | raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx))
112 | # Bidi rule 3
113 | if direction in ["R", "AL", "EN", "AN"]:
114 | valid_ending = True
115 | elif direction != "NSM":
116 | valid_ending = False
117 | # Bidi rule 4
118 | if direction in ["AN", "EN"]:
119 | if not number_type:
120 | number_type = direction
121 | else:
122 | if number_type != direction:
123 | raise IDNABidiError("Can not mix numeral types in a right-to-left label")
124 | else:
125 | # Bidi rule 5
126 | if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]:
127 | raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx))
128 | # Bidi rule 6
129 | if direction in ["L", "EN"]:
130 | valid_ending = True
131 | elif direction != "NSM":
132 | valid_ending = False
133 |
134 | if not valid_ending:
135 | raise IDNABidiError("Label ends with illegal codepoint directionality")
136 |
137 | return True
138 |
139 |
140 | def check_initial_combiner(label: str) -> bool:
141 | if unicodedata.category(label[0])[0] == "M":
142 | raise IDNAError("Label begins with an illegal combining character")
143 | return True
144 |
145 |
146 | def check_hyphen_ok(label: str) -> bool:
147 | if label[2:4] == "--":
148 | raise IDNAError("Label has disallowed hyphens in 3rd and 4th position")
149 | if label[0] == "-" or label[-1] == "-":
150 | raise IDNAError("Label must not start or end with a hyphen")
151 | return True
152 |
153 |
154 | def check_nfc(label: str) -> None:
155 | if unicodedata.normalize("NFC", label) != label:
156 | raise IDNAError("Label must be in Normalization Form C")
157 |
158 |
159 | def valid_contextj(label: str, pos: int) -> bool:
160 | cp_value = ord(label[pos])
161 |
162 | if cp_value == 0x200C:
163 | if pos > 0:
164 | if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
165 | return True
166 |
167 | ok = False
168 | for i in range(pos - 1, -1, -1):
169 | joining_type = idnadata.joining_types.get(ord(label[i]))
170 | if joining_type == ord("T"):
171 | continue
172 | elif joining_type in [ord("L"), ord("D")]:
173 | ok = True
174 | break
175 | else:
176 | break
177 |
178 | if not ok:
179 | return False
180 |
181 | ok = False
182 | for i in range(pos + 1, len(label)):
183 | joining_type = idnadata.joining_types.get(ord(label[i]))
184 | if joining_type == ord("T"):
185 | continue
186 | elif joining_type in [ord("R"), ord("D")]:
187 | ok = True
188 | break
189 | else:
190 | break
191 | return ok
192 |
193 | if cp_value == 0x200D:
194 | if pos > 0:
195 | if _combining_class(ord(label[pos - 1])) == _virama_combining_class:
196 | return True
197 | return False
198 |
199 | else:
200 | return False
201 |
202 |
203 | def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
204 | cp_value = ord(label[pos])
205 |
206 | if cp_value == 0x00B7:
207 | if 0 < pos < len(label) - 1:
208 | if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C:
209 | return True
210 | return False
211 |
212 | elif cp_value == 0x0375:
213 | if pos < len(label) - 1 and len(label) > 1:
214 | return _is_script(label[pos + 1], "Greek")
215 | return False
216 |
217 | elif cp_value == 0x05F3 or cp_value == 0x05F4:
218 | if pos > 0:
219 | return _is_script(label[pos - 1], "Hebrew")
220 | return False
221 |
222 | elif cp_value == 0x30FB:
223 | for cp in label:
224 | if cp == "\u30fb":
225 | continue
226 | if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"):
227 | return True
228 | return False
229 |
230 | elif 0x660 <= cp_value <= 0x669:
231 | for cp in label:
232 | if 0x6F0 <= ord(cp) <= 0x06F9:
233 | return False
234 | return True
235 |
236 | elif 0x6F0 <= cp_value <= 0x6F9:
237 | for cp in label:
238 | if 0x660 <= ord(cp) <= 0x0669:
239 | return False
240 | return True
241 |
242 | return False
243 |
244 |
245 | def check_label(label: Union[str, bytes, bytearray]) -> None:
246 | if isinstance(label, (bytes, bytearray)):
247 | label = label.decode("utf-8")
248 | if len(label) == 0:
249 | raise IDNAError("Empty Label")
250 |
251 | check_nfc(label)
252 | check_hyphen_ok(label)
253 | check_initial_combiner(label)
254 |
255 | for pos, cp in enumerate(label):
256 | cp_value = ord(cp)
257 | if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]):
258 | continue
259 | elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]):
260 | try:
261 | if not valid_contextj(label, pos):
262 | raise InvalidCodepointContext(
263 | "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
264 | )
265 | except ValueError:
266 | raise IDNAError(
267 | "Unknown codepoint adjacent to joiner {} at position {} in {}".format(
268 | _unot(cp_value), pos + 1, repr(label)
269 | )
270 | )
271 | elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
272 | if not valid_contexto(label, pos):
273 | raise InvalidCodepointContext(
274 | "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
275 | )
276 | else:
277 | raise InvalidCodepoint(
278 | "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label))
279 | )
280 |
281 | check_bidi(label)
282 |
283 |
284 | def alabel(label: str) -> bytes:
285 | try:
286 | label_bytes = label.encode("ascii")
287 | ulabel(label_bytes)
288 | if not valid_label_length(label_bytes):
289 | raise IDNAError("Label too long")
290 | return label_bytes
291 | except UnicodeEncodeError:
292 | pass
293 |
294 | check_label(label)
295 | label_bytes = _alabel_prefix + _punycode(label)
296 |
297 | if not valid_label_length(label_bytes):
298 | raise IDNAError("Label too long")
299 |
300 | return label_bytes
301 |
302 |
303 | def ulabel(label: Union[str, bytes, bytearray]) -> str:
304 | if not isinstance(label, (bytes, bytearray)):
305 | try:
306 | label_bytes = label.encode("ascii")
307 | except UnicodeEncodeError:
308 | check_label(label)
309 | return label
310 | else:
311 | label_bytes = label
312 |
313 | label_bytes = label_bytes.lower()
314 | if label_bytes.startswith(_alabel_prefix):
315 | label_bytes = label_bytes[len(_alabel_prefix) :]
316 | if not label_bytes:
317 | raise IDNAError("Malformed A-label, no Punycode eligible content found")
318 | if label_bytes.decode("ascii")[-1] == "-":
319 | raise IDNAError("A-label must not end with a hyphen")
320 | else:
321 | check_label(label_bytes)
322 | return label_bytes.decode("ascii")
323 |
324 | try:
325 | label = label_bytes.decode("punycode")
326 | except UnicodeError:
327 | raise IDNAError("Invalid A-label")
328 | check_label(label)
329 | return label
330 |
331 |
332 | def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:
333 | """Re-map the characters in the string according to UTS46 processing."""
334 | from .uts46data import uts46data
335 |
336 | output = ""
337 |
338 | for pos, char in enumerate(domain):
339 | code_point = ord(char)
340 | try:
341 | uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1]
342 | status = uts46row[1]
343 | replacement: Optional[str] = None
344 | if len(uts46row) == 3:
345 | replacement = uts46row[2]
346 | if (
347 | status == "V"
348 | or (status == "D" and not transitional)
349 | or (status == "3" and not std3_rules and replacement is None)
350 | ):
351 | output += char
352 | elif replacement is not None and (
353 | status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)
354 | ):
355 | output += replacement
356 | elif status != "I":
357 | raise IndexError()
358 | except IndexError:
359 | raise InvalidCodepoint(
360 | "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain))
361 | )
362 |
363 | return unicodedata.normalize("NFC", output)
364 |
365 |
366 | def encode(
367 | s: Union[str, bytes, bytearray],
368 | strict: bool = False,
369 | uts46: bool = False,
370 | std3_rules: bool = False,
371 | transitional: bool = False,
372 | ) -> bytes:
373 | if not isinstance(s, str):
374 | try:
375 | s = str(s, "ascii")
376 | except UnicodeDecodeError:
377 | raise IDNAError("should pass a unicode string to the function rather than a byte string.")
378 | if uts46:
379 | s = uts46_remap(s, std3_rules, transitional)
380 | trailing_dot = False
381 | result = []
382 | if strict:
383 | labels = s.split(".")
384 | else:
385 | labels = _unicode_dots_re.split(s)
386 | if not labels or labels == [""]:
387 | raise IDNAError("Empty domain")
388 | if labels[-1] == "":
389 | del labels[-1]
390 | trailing_dot = True
391 | for label in labels:
392 | s = alabel(label)
393 | if s:
394 | result.append(s)
395 | else:
396 | raise IDNAError("Empty label")
397 | if trailing_dot:
398 | result.append(b"")
399 | s = b".".join(result)
400 | if not valid_string_length(s, trailing_dot):
401 | raise IDNAError("Domain too long")
402 | return s
403 |
404 |
405 | def decode(
406 | s: Union[str, bytes, bytearray],
407 | strict: bool = False,
408 | uts46: bool = False,
409 | std3_rules: bool = False,
410 | ) -> str:
411 | try:
412 | if not isinstance(s, str):
413 | s = str(s, "ascii")
414 | except UnicodeDecodeError:
415 | raise IDNAError("Invalid ASCII in A-label")
416 | if uts46:
417 | s = uts46_remap(s, std3_rules, False)
418 | trailing_dot = False
419 | result = []
420 | if not strict:
421 | labels = _unicode_dots_re.split(s)
422 | else:
423 | labels = s.split(".")
424 | if not labels or labels == [""]:
425 | raise IDNAError("Empty domain")
426 | if not labels[-1]:
427 | del labels[-1]
428 | trailing_dot = True
429 | for label in labels:
430 | s = ulabel(label)
431 | if s:
432 | result.append(s)
433 | else:
434 | raise IDNAError("Empty label")
435 | if trailing_dot:
436 | result.append("")
437 | return ".".join(result)
438 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/lxml/isoschematron/__init__.py:
--------------------------------------------------------------------------------
```python
1 | """The ``lxml.isoschematron`` package implements ISO Schematron support on top
2 | of the pure-xslt 'skeleton' implementation.
3 | """
4 |
5 | import sys
6 | import os.path
7 | from lxml import etree as _etree # due to validator __init__ signature
8 |
9 |
10 | # some compat stuff, borrowed from lxml.html
11 | try:
12 | unicode
13 | except NameError:
14 | # Python 3
15 | unicode = str
16 | try:
17 | basestring
18 | except NameError:
19 | # Python 3
20 | basestring = str
21 |
22 |
23 | __all__ = ['extract_xsd', 'extract_rng', 'iso_dsdl_include',
24 | 'iso_abstract_expand', 'iso_svrl_for_xslt1',
25 | 'svrl_validation_errors', 'schematron_schema_valid',
26 | 'stylesheet_params', 'Schematron']
27 |
28 |
29 | # some namespaces
30 | #FIXME: Maybe lxml should provide a dedicated place for common namespace
31 | #FIXME: definitions?
32 | XML_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"
33 | RELAXNG_NS = "http://relaxng.org/ns/structure/1.0"
34 | SCHEMATRON_NS = "http://purl.oclc.org/dsdl/schematron"
35 | SVRL_NS = "http://purl.oclc.org/dsdl/svrl"
36 |
37 |
38 | # some helpers
39 | _schematron_root = '{%s}schema' % SCHEMATRON_NS
40 | _xml_schema_root = '{%s}schema' % XML_SCHEMA_NS
41 | _resources_dir = os.path.join(os.path.dirname(__file__), 'resources')
42 |
43 |
44 | # the iso-schematron skeleton implementation steps aka xsl transformations
45 | extract_xsd = _etree.XSLT(_etree.parse(
46 | os.path.join(_resources_dir, 'xsl', 'XSD2Schtrn.xsl')))
47 | extract_rng = _etree.XSLT(_etree.parse(
48 | os.path.join(_resources_dir, 'xsl', 'RNG2Schtrn.xsl')))
49 | iso_dsdl_include = _etree.XSLT(_etree.parse(
50 | os.path.join(_resources_dir, 'xsl', 'iso-schematron-xslt1',
51 | 'iso_dsdl_include.xsl')))
52 | iso_abstract_expand = _etree.XSLT(_etree.parse(
53 | os.path.join(_resources_dir, 'xsl', 'iso-schematron-xslt1',
54 | 'iso_abstract_expand.xsl')))
55 | iso_svrl_for_xslt1 = _etree.XSLT(_etree.parse(
56 | os.path.join(_resources_dir,
57 | 'xsl', 'iso-schematron-xslt1', 'iso_svrl_for_xslt1.xsl')))
58 |
59 |
60 | # svrl result accessors
61 | svrl_validation_errors = _etree.XPath(
62 | '//svrl:failed-assert', namespaces={'svrl': SVRL_NS})
63 |
64 | # RelaxNG validator for schematron schemas
65 | schematron_schema_valid_supported = False
66 | try:
67 | schematron_schema_valid = _etree.RelaxNG(
68 | file=os.path.join(_resources_dir, 'rng', 'iso-schematron.rng'))
69 | schematron_schema_valid_supported = True
70 | except _etree.RelaxNGParseError:
71 | # Some distributions delete the file due to licensing issues.
72 | def schematron_schema_valid(arg):
73 | raise NotImplementedError("Validating the ISO schematron requires iso-schematron.rng")
74 |
75 |
76 | def stylesheet_params(**kwargs):
77 | """Convert keyword args to a dictionary of stylesheet parameters.
78 | XSL stylesheet parameters must be XPath expressions, i.e.:
79 |
80 | * string expressions, like "'5'"
81 | * simple (number) expressions, like "5"
82 | * valid XPath expressions, like "/a/b/text()"
83 |
84 | This function converts native Python keyword arguments to stylesheet
85 | parameters following these rules:
86 | If an arg is a string wrap it with XSLT.strparam().
87 | If an arg is an XPath object use its path string.
88 | If arg is None raise TypeError.
89 | Else convert arg to string.
90 | """
91 | result = {}
92 | for key, val in kwargs.items():
93 | if isinstance(val, basestring):
94 | val = _etree.XSLT.strparam(val)
95 | elif val is None:
96 | raise TypeError('None not allowed as a stylesheet parameter')
97 | elif not isinstance(val, _etree.XPath):
98 | val = unicode(val)
99 | result[key] = val
100 | return result
101 |
102 |
103 | # helper function for use in Schematron __init__
104 | def _stylesheet_param_dict(paramsDict, kwargsDict):
105 | """Return a copy of paramsDict, updated with kwargsDict entries, wrapped as
106 | stylesheet arguments.
107 | kwargsDict entries with a value of None are ignored.
108 | """
109 | # beware of changing mutable default arg
110 | paramsDict = dict(paramsDict)
111 | for k, v in kwargsDict.items():
112 | if v is not None: # None values do not override
113 | paramsDict[k] = v
114 | paramsDict = stylesheet_params(**paramsDict)
115 | return paramsDict
116 |
117 |
118 | class Schematron(_etree._Validator):
119 | """An ISO Schematron validator.
120 |
121 | Pass a root Element or an ElementTree to turn it into a validator.
122 | Alternatively, pass a filename as keyword argument 'file' to parse from
123 | the file system.
124 |
125 | Schematron is a less well known, but very powerful schema language.
126 | The main idea is to use the capabilities of XPath to put restrictions on
127 | the structure and the content of XML documents.
128 |
129 | The standard behaviour is to fail on ``failed-assert`` findings only
130 | (``ASSERTS_ONLY``). To change this, you can either pass a report filter
131 | function to the ``error_finder`` parameter (e.g. ``ASSERTS_AND_REPORTS``
132 | or a custom ``XPath`` object), or subclass isoschematron.Schematron for
133 | complete control of the validation process.
134 |
135 | Built on the Schematron language 'reference' skeleton pure-xslt
136 | implementation, the validator is created as an XSLT 1.0 stylesheet using
137 | these steps:
138 |
139 | 0) (Extract from XML Schema or RelaxNG schema)
140 | 1) Process inclusions
141 | 2) Process abstract patterns
142 | 3) Compile the schematron schema to XSLT
143 |
144 | The ``include`` and ``expand`` keyword arguments can be used to switch off
145 | steps 1) and 2).
146 | To set parameters for steps 1), 2) and 3) hand parameter dictionaries to the
147 | keyword arguments ``include_params``, ``expand_params`` or
148 | ``compile_params``.
149 | For convenience, the compile-step parameter ``phase`` is also exposed as a
150 | keyword argument ``phase``. This takes precedence if the parameter is also
151 | given in the parameter dictionary.
152 |
153 | If ``store_schematron`` is set to True, the (included-and-expanded)
154 | schematron document tree is stored and available through the ``schematron``
155 | property.
156 | If ``store_xslt`` is set to True, the validation XSLT document tree will be
157 | stored and can be retrieved through the ``validator_xslt`` property.
158 | With ``store_report`` set to True (default: False), the resulting validation
159 | report document gets stored and can be accessed as the ``validation_report``
160 | property.
161 |
162 | If ``validate_schema`` is set to False, the validation of the schema file
163 | itself is disabled. Validation happens by default after building the full
164 | schema, unless the schema validation file cannot be found at import time,
165 | in which case the validation gets disabled. Some lxml distributions exclude
166 | this file due to licensing issues. ISO-Schematron validation can then still
167 | be used normally, but the schemas themselves cannot be validated.
168 |
169 | Here is a usage example::
170 |
171 | >>> from lxml import etree
172 | >>> from lxml.isoschematron import Schematron
173 |
174 | >>> schematron = Schematron(etree.XML('''
175 | ... <schema xmlns="http://purl.oclc.org/dsdl/schematron" >
176 | ... <pattern id="id_only_attribute">
177 | ... <title>id is the only permitted attribute name</title>
178 | ... <rule context="*">
179 | ... <report test="@*[not(name()='id')]">Attribute
180 | ... <name path="@*[not(name()='id')]"/> is forbidden<name/>
181 | ... </report>
182 | ... </rule>
183 | ... </pattern>
184 | ... </schema>'''),
185 | ... error_finder=Schematron.ASSERTS_AND_REPORTS)
186 |
187 | >>> xml = etree.XML('''
188 | ... <AAA name="aaa">
189 | ... <BBB id="bbb"/>
190 | ... <CCC color="ccc"/>
191 | ... </AAA>
192 | ... ''')
193 |
194 | >>> schematron.validate(xml)
195 | False
196 |
197 | >>> xml = etree.XML('''
198 | ... <AAA id="aaa">
199 | ... <BBB id="bbb"/>
200 | ... <CCC/>
201 | ... </AAA>
202 | ... ''')
203 |
204 | >>> schematron.validate(xml)
205 | True
206 | """
207 |
208 | # libxml2 error categorization for validation errors
209 | _domain = _etree.ErrorDomains.SCHEMATRONV
210 | _level = _etree.ErrorLevels.ERROR
211 | _error_type = _etree.ErrorTypes.SCHEMATRONV_ASSERT
212 |
213 | # convenience definitions for common behaviours
214 | ASSERTS_ONLY = svrl_validation_errors # Default
215 | ASSERTS_AND_REPORTS = _etree.XPath(
216 | '//svrl:failed-assert | //svrl:successful-report',
217 | namespaces={'svrl': SVRL_NS})
218 |
219 | def _extract(self, element):
220 | """Extract embedded schematron schema from non-schematron host schema.
221 | This method will only be called by __init__ if the given schema document
222 | is not a schematron schema by itself.
223 | Must return a schematron schema document tree or None.
224 | """
225 | schematron = None
226 | if element.tag == _xml_schema_root:
227 | schematron = self._extract_xsd(element)
228 | elif element.nsmap.get(element.prefix) == RELAXNG_NS:
229 | # RelaxNG does not have a single unique root element
230 | schematron = self._extract_rng(element)
231 | return schematron
232 |
233 | # customization points
234 | # etree.XSLT objects that provide the extract, include, expand, compile
235 | # steps
236 | _extract_xsd = extract_xsd
237 | _extract_rng = extract_rng
238 | _include = iso_dsdl_include
239 | _expand = iso_abstract_expand
240 | _compile = iso_svrl_for_xslt1
241 |
242 | # etree.xpath object that determines input document validity when applied to
243 | # the svrl result report; must return a list of result elements (empty if
244 | # valid)
245 | _validation_errors = ASSERTS_ONLY
246 |
247 | def __init__(self, etree=None, file=None, include=True, expand=True,
248 | include_params={}, expand_params={}, compile_params={},
249 | store_schematron=False, store_xslt=False, store_report=False,
250 | phase=None, error_finder=ASSERTS_ONLY,
251 | validate_schema=schematron_schema_valid_supported):
252 | super().__init__()
253 |
254 | self._store_report = store_report
255 | self._schematron = None
256 | self._validator_xslt = None
257 | self._validation_report = None
258 | if error_finder is not self.ASSERTS_ONLY:
259 | self._validation_errors = error_finder
260 |
261 | # parse schema document, may be a schematron schema or an XML Schema or
262 | # a RelaxNG schema with embedded schematron rules
263 | root = None
264 | try:
265 | if etree is not None:
266 | if _etree.iselement(etree):
267 | root = etree
268 | else:
269 | root = etree.getroot()
270 | elif file is not None:
271 | root = _etree.parse(file).getroot()
272 | except Exception:
273 | raise _etree.SchematronParseError(
274 | "No tree or file given: %s" % sys.exc_info()[1])
275 | if root is None:
276 | raise ValueError("Empty tree")
277 | if root.tag == _schematron_root:
278 | schematron = root
279 | else:
280 | schematron = self._extract(root)
281 | if schematron is None:
282 | raise _etree.SchematronParseError(
283 | "Document is not a schematron schema or schematron-extractable")
284 | # perform the iso-schematron skeleton implementation steps to get a
285 | # validating xslt
286 | if include:
287 | schematron = self._include(schematron, **include_params)
288 | if expand:
289 | schematron = self._expand(schematron, **expand_params)
290 | if validate_schema and not schematron_schema_valid(schematron):
291 | raise _etree.SchematronParseError(
292 | "invalid schematron schema: %s" %
293 | schematron_schema_valid.error_log)
294 | if store_schematron:
295 | self._schematron = schematron
296 | # add new compile keyword args here if exposing them
297 | compile_kwargs = {'phase': phase}
298 | compile_params = _stylesheet_param_dict(compile_params, compile_kwargs)
299 | validator_xslt = self._compile(schematron, **compile_params)
300 | if store_xslt:
301 | self._validator_xslt = validator_xslt
302 | self._validator = _etree.XSLT(validator_xslt)
303 |
304 | def __call__(self, etree):
305 | """Validate doc using Schematron.
306 |
307 | Returns true if document is valid, false if not.
308 | """
309 | self._clear_error_log()
310 | result = self._validator(etree)
311 | if self._store_report:
312 | self._validation_report = result
313 | errors = self._validation_errors(result)
314 | if errors:
315 | if _etree.iselement(etree):
316 | fname = etree.getroottree().docinfo.URL or '<file>'
317 | else:
318 | fname = etree.docinfo.URL or '<file>'
319 | for error in errors:
320 | # Does svrl report the line number, anywhere? Don't think so.
321 | self._append_log_message(
322 | domain=self._domain, type=self._error_type,
323 | level=self._level, line=0,
324 | message=_etree.tostring(error, encoding='unicode'),
325 | filename=fname)
326 | return False
327 | return True
328 |
329 | @property
330 | def schematron(self):
331 | """ISO-schematron schema document (None if object has been initialized
332 | with store_schematron=False).
333 | """
334 | return self._schematron
335 |
336 | @property
337 | def validator_xslt(self):
338 | """ISO-schematron skeleton implementation XSLT validator document (None
339 | if object has been initialized with store_xslt=False).
340 | """
341 | return self._validator_xslt
342 |
343 | @property
344 | def validation_report(self):
345 | """ISO-schematron validation result report (None if result-storing has
346 | been turned off).
347 | """
348 | return self._validation_report
349 |
```
--------------------------------------------------------------------------------
/.venv/lib/python3.12/site-packages/flask/config.py:
--------------------------------------------------------------------------------
```python
1 | from __future__ import annotations
2 |
3 | import errno
4 | import json
5 | import os
6 | import types
7 | import typing as t
8 |
9 | from werkzeug.utils import import_string
10 |
11 | if t.TYPE_CHECKING:
12 | import typing_extensions as te
13 |
14 | from .sansio.app import App
15 |
16 |
17 | T = t.TypeVar("T")
18 |
19 |
20 | class ConfigAttribute(t.Generic[T]):
21 | """Makes an attribute forward to the config"""
22 |
23 | def __init__(
24 | self, name: str, get_converter: t.Callable[[t.Any], T] | None = None
25 | ) -> None:
26 | self.__name__ = name
27 | self.get_converter = get_converter
28 |
29 | @t.overload
30 | def __get__(self, obj: None, owner: None) -> te.Self: ...
31 |
32 | @t.overload
33 | def __get__(self, obj: App, owner: type[App]) -> T: ...
34 |
35 | def __get__(self, obj: App | None, owner: type[App] | None = None) -> T | te.Self:
36 | if obj is None:
37 | return self
38 |
39 | rv = obj.config[self.__name__]
40 |
41 | if self.get_converter is not None:
42 | rv = self.get_converter(rv)
43 |
44 | return rv # type: ignore[no-any-return]
45 |
46 | def __set__(self, obj: App, value: t.Any) -> None:
47 | obj.config[self.__name__] = value
48 |
49 |
50 | class Config(dict): # type: ignore[type-arg]
51 | """Works exactly like a dict but provides ways to fill it from files
52 | or special dictionaries. There are two common patterns to populate the
53 | config.
54 |
55 | Either you can fill the config from a config file::
56 |
57 | app.config.from_pyfile('yourconfig.cfg')
58 |
59 | Or alternatively you can define the configuration options in the
60 | module that calls :meth:`from_object` or provide an import path to
61 | a module that should be loaded. It is also possible to tell it to
62 | use the same module and with that provide the configuration values
63 | just before the call::
64 |
65 | DEBUG = True
66 | SECRET_KEY = 'development key'
67 | app.config.from_object(__name__)
68 |
69 | In both cases (loading from any Python file or loading from modules),
70 | only uppercase keys are added to the config. This makes it possible to use
71 | lowercase values in the config file for temporary values that are not added
72 | to the config or to define the config keys in the same file that implements
73 | the application.
74 |
75 | Probably the most interesting way to load configurations is from an
76 | environment variable pointing to a file::
77 |
78 | app.config.from_envvar('YOURAPPLICATION_SETTINGS')
79 |
80 | In this case before launching the application you have to set this
81 | environment variable to the file you want to use. On Linux and OS X
82 | use the export statement::
83 |
84 | export YOURAPPLICATION_SETTINGS='/path/to/config/file'
85 |
86 | On windows use `set` instead.
87 |
88 | :param root_path: path to which files are read relative from. When the
89 | config object is created by the application, this is
90 | the application's :attr:`~flask.Flask.root_path`.
91 | :param defaults: an optional dictionary of default values
92 | """
93 |
94 | def __init__(
95 | self,
96 | root_path: str | os.PathLike[str],
97 | defaults: dict[str, t.Any] | None = None,
98 | ) -> None:
99 | super().__init__(defaults or {})
100 | self.root_path = root_path
101 |
102 | def from_envvar(self, variable_name: str, silent: bool = False) -> bool:
103 | """Loads a configuration from an environment variable pointing to
104 | a configuration file. This is basically just a shortcut with nicer
105 | error messages for this line of code::
106 |
107 | app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
108 |
109 | :param variable_name: name of the environment variable
110 | :param silent: set to ``True`` if you want silent failure for missing
111 | files.
112 | :return: ``True`` if the file was loaded successfully.
113 | """
114 | rv = os.environ.get(variable_name)
115 | if not rv:
116 | if silent:
117 | return False
118 | raise RuntimeError(
119 | f"The environment variable {variable_name!r} is not set"
120 | " and as such configuration could not be loaded. Set"
121 | " this variable and make it point to a configuration"
122 | " file"
123 | )
124 | return self.from_pyfile(rv, silent=silent)
125 |
126 | def from_prefixed_env(
127 | self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads
128 | ) -> bool:
129 | """Load any environment variables that start with ``FLASK_``,
130 | dropping the prefix from the env key for the config key. Values
131 | are passed through a loading function to attempt to convert them
132 | to more specific types than strings.
133 |
134 | Keys are loaded in :func:`sorted` order.
135 |
136 | The default loading function attempts to parse values as any
137 | valid JSON type, including dicts and lists.
138 |
139 | Specific items in nested dicts can be set by separating the
140 | keys with double underscores (``__``). If an intermediate key
141 | doesn't exist, it will be initialized to an empty dict.
142 |
143 | :param prefix: Load env vars that start with this prefix,
144 | separated with an underscore (``_``).
145 | :param loads: Pass each string value to this function and use
146 | the returned value as the config value. If any error is
147 | raised it is ignored and the value remains a string. The
148 | default is :func:`json.loads`.
149 |
150 | .. versionadded:: 2.1
151 | """
152 | prefix = f"{prefix}_"
153 | len_prefix = len(prefix)
154 |
155 | for key in sorted(os.environ):
156 | if not key.startswith(prefix):
157 | continue
158 |
159 | value = os.environ[key]
160 |
161 | try:
162 | value = loads(value)
163 | except Exception:
164 | # Keep the value as a string if loading failed.
165 | pass
166 |
167 | # Change to key.removeprefix(prefix) on Python >= 3.9.
168 | key = key[len_prefix:]
169 |
170 | if "__" not in key:
171 | # A non-nested key, set directly.
172 | self[key] = value
173 | continue
174 |
175 | # Traverse nested dictionaries with keys separated by "__".
176 | current = self
177 | *parts, tail = key.split("__")
178 |
179 | for part in parts:
180 | # If an intermediate dict does not exist, create it.
181 | if part not in current:
182 | current[part] = {}
183 |
184 | current = current[part]
185 |
186 | current[tail] = value
187 |
188 | return True
189 |
190 | def from_pyfile(
191 | self, filename: str | os.PathLike[str], silent: bool = False
192 | ) -> bool:
193 | """Updates the values in the config from a Python file. This function
194 | behaves as if the file was imported as module with the
195 | :meth:`from_object` function.
196 |
197 | :param filename: the filename of the config. This can either be an
198 | absolute filename or a filename relative to the
199 | root path.
200 | :param silent: set to ``True`` if you want silent failure for missing
201 | files.
202 | :return: ``True`` if the file was loaded successfully.
203 |
204 | .. versionadded:: 0.7
205 | `silent` parameter.
206 | """
207 | filename = os.path.join(self.root_path, filename)
208 | d = types.ModuleType("config")
209 | d.__file__ = filename
210 | try:
211 | with open(filename, mode="rb") as config_file:
212 | exec(compile(config_file.read(), filename, "exec"), d.__dict__)
213 | except OSError as e:
214 | if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR):
215 | return False
216 | e.strerror = f"Unable to load configuration file ({e.strerror})"
217 | raise
218 | self.from_object(d)
219 | return True
220 |
221 | def from_object(self, obj: object | str) -> None:
222 | """Updates the values from the given object. An object can be of one
223 | of the following two types:
224 |
225 | - a string: in this case the object with that name will be imported
226 | - an actual object reference: that object is used directly
227 |
228 | Objects are usually either modules or classes. :meth:`from_object`
229 | loads only the uppercase attributes of the module/class. A ``dict``
230 | object will not work with :meth:`from_object` because the keys of a
231 | ``dict`` are not attributes of the ``dict`` class.
232 |
233 | Example of module-based configuration::
234 |
235 | app.config.from_object('yourapplication.default_config')
236 | from yourapplication import default_config
237 | app.config.from_object(default_config)
238 |
239 | Nothing is done to the object before loading. If the object is a
240 | class and has ``@property`` attributes, it needs to be
241 | instantiated before being passed to this method.
242 |
243 | You should not use this function to load the actual configuration but
244 | rather configuration defaults. The actual config should be loaded
245 | with :meth:`from_pyfile` and ideally from a location not within the
246 | package because the package might be installed system wide.
247 |
248 | See :ref:`config-dev-prod` for an example of class-based configuration
249 | using :meth:`from_object`.
250 |
251 | :param obj: an import name or object
252 | """
253 | if isinstance(obj, str):
254 | obj = import_string(obj)
255 | for key in dir(obj):
256 | if key.isupper():
257 | self[key] = getattr(obj, key)
258 |
259 | def from_file(
260 | self,
261 | filename: str | os.PathLike[str],
262 | load: t.Callable[[t.IO[t.Any]], t.Mapping[str, t.Any]],
263 | silent: bool = False,
264 | text: bool = True,
265 | ) -> bool:
266 | """Update the values in the config from a file that is loaded
267 | using the ``load`` parameter. The loaded data is passed to the
268 | :meth:`from_mapping` method.
269 |
270 | .. code-block:: python
271 |
272 | import json
273 | app.config.from_file("config.json", load=json.load)
274 |
275 | import tomllib
276 | app.config.from_file("config.toml", load=tomllib.load, text=False)
277 |
278 | :param filename: The path to the data file. This can be an
279 | absolute path or relative to the config root path.
280 | :param load: A callable that takes a file handle and returns a
281 | mapping of loaded data from the file.
282 | :type load: ``Callable[[Reader], Mapping]`` where ``Reader``
283 | implements a ``read`` method.
284 | :param silent: Ignore the file if it doesn't exist.
285 | :param text: Open the file in text or binary mode.
286 | :return: ``True`` if the file was loaded successfully.
287 |
288 | .. versionchanged:: 2.3
289 | The ``text`` parameter was added.
290 |
291 | .. versionadded:: 2.0
292 | """
293 | filename = os.path.join(self.root_path, filename)
294 |
295 | try:
296 | with open(filename, "r" if text else "rb") as f:
297 | obj = load(f)
298 | except OSError as e:
299 | if silent and e.errno in (errno.ENOENT, errno.EISDIR):
300 | return False
301 |
302 | e.strerror = f"Unable to load configuration file ({e.strerror})"
303 | raise
304 |
305 | return self.from_mapping(obj)
306 |
307 | def from_mapping(
308 | self, mapping: t.Mapping[str, t.Any] | None = None, **kwargs: t.Any
309 | ) -> bool:
310 | """Updates the config like :meth:`update` ignoring items with
311 | non-upper keys.
312 |
313 | :return: Always returns ``True``.
314 |
315 | .. versionadded:: 0.11
316 | """
317 | mappings: dict[str, t.Any] = {}
318 | if mapping is not None:
319 | mappings.update(mapping)
320 | mappings.update(kwargs)
321 | for key, value in mappings.items():
322 | if key.isupper():
323 | self[key] = value
324 | return True
325 |
326 | def get_namespace(
327 | self, namespace: str, lowercase: bool = True, trim_namespace: bool = True
328 | ) -> dict[str, t.Any]:
329 | """Returns a dictionary containing a subset of configuration options
330 | that match the specified namespace/prefix. Example usage::
331 |
332 | app.config['IMAGE_STORE_TYPE'] = 'fs'
333 | app.config['IMAGE_STORE_PATH'] = '/var/app/images'
334 | app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com'
335 | image_store_config = app.config.get_namespace('IMAGE_STORE_')
336 |
337 | The resulting dictionary `image_store_config` would look like::
338 |
339 | {
340 | 'type': 'fs',
341 | 'path': '/var/app/images',
342 | 'base_url': 'http://img.website.com'
343 | }
344 |
345 | This is often useful when configuration options map directly to
346 | keyword arguments in functions or class constructors.
347 |
348 | :param namespace: a configuration namespace
349 | :param lowercase: a flag indicating if the keys of the resulting
350 | dictionary should be lowercase
351 | :param trim_namespace: a flag indicating if the keys of the resulting
352 | dictionary should not include the namespace
353 |
354 | .. versionadded:: 0.11
355 | """
356 | rv = {}
357 | for k, v in self.items():
358 | if not k.startswith(namespace):
359 | continue
360 | if trim_namespace:
361 | key = k[len(namespace) :]
362 | else:
363 | key = k
364 | if lowercase:
365 | key = key.lower()
366 | rv[key] = v
367 | return rv
368 |
369 | def __repr__(self) -> str:
370 | return f"<{type(self).__name__} {dict.__repr__(self)}>"
371 |
```