#
tokens: 51718/50000 1/808 files (page 155/168)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 155 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/lxml/html/__init__.py:
--------------------------------------------------------------------------------

```python
   1 | # Copyright (c) 2004 Ian Bicking. All rights reserved.
   2 | #
   3 | # Redistribution and use in source and binary forms, with or without
   4 | # modification, are permitted provided that the following conditions are
   5 | # met:
   6 | #
   7 | # 1. Redistributions of source code must retain the above copyright
   8 | # notice, this list of conditions and the following disclaimer.
   9 | #
  10 | # 2. Redistributions in binary form must reproduce the above copyright
  11 | # notice, this list of conditions and the following disclaimer in
  12 | # the documentation and/or other materials provided with the
  13 | # distribution.
  14 | #
  15 | # 3. Neither the name of Ian Bicking nor the names of its contributors may
  16 | # be used to endorse or promote products derived from this software
  17 | # without specific prior written permission.
  18 | #
  19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IAN BICKING OR
  23 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30 | 
  31 | """The ``lxml.html`` tool set for HTML handling.
  32 | """
  33 | 
  34 | 
  35 | __all__ = [
  36 |     'document_fromstring', 'fragment_fromstring', 'fragments_fromstring', 'fromstring',
  37 |     'tostring', 'Element', 'defs', 'open_in_browser', 'submit_form',
  38 |     'find_rel_links', 'find_class', 'make_links_absolute',
  39 |     'resolve_base_href', 'iterlinks', 'rewrite_links', 'parse']
  40 | 
  41 | 
  42 | import copy
  43 | import re
  44 | 
  45 | from collections.abc import MutableMapping, MutableSet
  46 | from functools import partial
  47 | from urllib.parse import urljoin
  48 | 
  49 | from .. import etree
  50 | from . import defs
  51 | from ._setmixin import SetMixin
  52 | 
  53 | 
  54 | def __fix_docstring(s):
  55 |     # TODO: remove and clean up doctests
  56 |     if not s:
  57 |         return s
  58 |     sub = re.compile(r"^(\s*)u'", re.M).sub
  59 |     return sub(r"\1'", s)
  60 | 
  61 | 
  62 | XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"
  63 | 
  64 | _rel_links_xpath = etree.XPath("descendant-or-self::a[@rel]|descendant-or-self::x:a[@rel]",
  65 |                                namespaces={'x':XHTML_NAMESPACE})
  66 | _options_xpath = etree.XPath("descendant-or-self::option|descendant-or-self::x:option",
  67 |                              namespaces={'x':XHTML_NAMESPACE})
  68 | _forms_xpath = etree.XPath("descendant-or-self::form|descendant-or-self::x:form",
  69 |                            namespaces={'x':XHTML_NAMESPACE})
  70 | #_class_xpath = etree.XPath(r"descendant-or-self::*[regexp:match(@class, concat('\b', $class_name, '\b'))]", {'regexp': 'http://exslt.org/regular-expressions'})
  71 | _class_xpath = etree.XPath("descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), concat(' ', $class_name, ' '))]")
  72 | _id_xpath = etree.XPath("descendant-or-self::*[@id=$id]")
  73 | _collect_string_content = etree.XPath("string()")
  74 | _iter_css_urls = re.compile(r'url\(('+'["][^"]*["]|'+"['][^']*[']|"+r'[^)]*)\)', re.I).finditer
  75 | _iter_css_imports = re.compile(r'@import "(.*?)"').finditer
  76 | _label_xpath = etree.XPath("//label[@for=$id]|//x:label[@for=$id]",
  77 |                            namespaces={'x':XHTML_NAMESPACE})
  78 | _archive_re = re.compile(r'[^ ]+')
  79 | _parse_meta_refresh_url = re.compile(
  80 |     r'[^;=]*;\s*(?:url\s*=\s*)?(?P<url>.*)$', re.I).search
  81 | 
  82 | 
  83 | def _unquote_match(s, pos):
  84 |     if s[:1] == '"' and s[-1:] == '"' or s[:1] == "'" and s[-1:] == "'":
  85 |         return s[1:-1], pos+1
  86 |     else:
  87 |         return s,pos
  88 | 
  89 | 
  90 | def _transform_result(typ, result):
  91 |     """Convert the result back into the input type.
  92 |     """
  93 |     if issubclass(typ, bytes):
  94 |         return tostring(result, encoding='utf-8')
  95 |     elif issubclass(typ, str):
  96 |         return tostring(result, encoding='unicode')
  97 |     else:
  98 |         return result
  99 | 
 100 | 
 101 | def _nons(tag):
 102 |     if isinstance(tag, str):
 103 |         if tag[0] == '{' and tag[1:len(XHTML_NAMESPACE)+1] == XHTML_NAMESPACE:
 104 |             return tag.split('}')[-1]
 105 |     return tag
 106 | 
 107 | 
 108 | class Classes(MutableSet):
 109 |     """Provides access to an element's class attribute as a set-like collection.
 110 |     Usage::
 111 | 
 112 |         >>> el = fromstring('<p class="hidden large">Text</p>')
 113 |         >>> classes = el.classes  # or: classes = Classes(el.attrib)
 114 |         >>> classes |= ['block', 'paragraph']
 115 |         >>> el.get('class')
 116 |         'hidden large block paragraph'
 117 |         >>> classes.toggle('hidden')
 118 |         False
 119 |         >>> el.get('class')
 120 |         'large block paragraph'
 121 |         >>> classes -= ('some', 'classes', 'block')
 122 |         >>> el.get('class')
 123 |         'large paragraph'
 124 |     """
 125 |     def __init__(self, attributes):
 126 |         self._attributes = attributes
 127 |         self._get_class_value = partial(attributes.get, 'class', '')
 128 | 
 129 |     def add(self, value):
 130 |         """
 131 |         Add a class.
 132 | 
 133 |         This has no effect if the class is already present.
 134 |         """
 135 |         if not value or re.search(r'\s', value):
 136 |             raise ValueError("Invalid class name: %r" % value)
 137 |         classes = self._get_class_value().split()
 138 |         if value in classes:
 139 |             return
 140 |         classes.append(value)
 141 |         self._attributes['class'] = ' '.join(classes)
 142 | 
 143 |     def discard(self, value):
 144 |         """
 145 |         Remove a class if it is currently present.
 146 | 
 147 |         If the class is not present, do nothing.
 148 |         """
 149 |         if not value or re.search(r'\s', value):
 150 |             raise ValueError("Invalid class name: %r" % value)
 151 |         classes = [name for name in self._get_class_value().split()
 152 |                    if name != value]
 153 |         if classes:
 154 |             self._attributes['class'] = ' '.join(classes)
 155 |         elif 'class' in self._attributes:
 156 |             del self._attributes['class']
 157 | 
 158 |     def remove(self, value):
 159 |         """
 160 |         Remove a class; it must currently be present.
 161 | 
 162 |         If the class is not present, raise a KeyError.
 163 |         """
 164 |         if not value or re.search(r'\s', value):
 165 |             raise ValueError("Invalid class name: %r" % value)
 166 |         super().remove(value)
 167 | 
 168 |     def __contains__(self, name):
 169 |         classes = self._get_class_value()
 170 |         return name in classes and name in classes.split()
 171 | 
 172 |     def __iter__(self):
 173 |         return iter(self._get_class_value().split())
 174 | 
 175 |     def __len__(self):
 176 |         return len(self._get_class_value().split())
 177 | 
 178 |     # non-standard methods
 179 | 
 180 |     def update(self, values):
 181 |         """
 182 |         Add all names from 'values'.
 183 |         """
 184 |         classes = self._get_class_value().split()
 185 |         extended = False
 186 |         for value in values:
 187 |             if value not in classes:
 188 |                 classes.append(value)
 189 |                 extended = True
 190 |         if extended:
 191 |             self._attributes['class'] = ' '.join(classes)
 192 | 
 193 |     def toggle(self, value):
 194 |         """
 195 |         Add a class name if it isn't there yet, or remove it if it exists.
 196 | 
 197 |         Returns true if the class was added (and is now enabled) and
 198 |         false if it was removed (and is now disabled).
 199 |         """
 200 |         if not value or re.search(r'\s', value):
 201 |             raise ValueError("Invalid class name: %r" % value)
 202 |         classes = self._get_class_value().split()
 203 |         try:
 204 |             classes.remove(value)
 205 |             enabled = False
 206 |         except ValueError:
 207 |             classes.append(value)
 208 |             enabled = True
 209 |         if classes:
 210 |             self._attributes['class'] = ' '.join(classes)
 211 |         else:
 212 |             del self._attributes['class']
 213 |         return enabled
 214 | 
 215 | 
 216 | class HtmlMixin:
 217 | 
 218 |     def set(self, key, value=None):
 219 |         """set(self, key, value=None)
 220 | 
 221 |         Sets an element attribute.  If no value is provided, or if the value is None,
 222 |         creates a 'boolean' attribute without value, e.g. "<form novalidate></form>"
 223 |         for ``form.set('novalidate')``.
 224 |         """
 225 |         super().set(key, value)
 226 | 
 227 |     @property
 228 |     def classes(self):
 229 |         """
 230 |         A set-like wrapper around the 'class' attribute.
 231 |         """
 232 |         return Classes(self.attrib)
 233 | 
 234 |     @classes.setter
 235 |     def classes(self, classes):
 236 |         assert isinstance(classes, Classes)  # only allow "el.classes |= ..." etc.
 237 |         value = classes._get_class_value()
 238 |         if value:
 239 |             self.set('class', value)
 240 |         elif self.get('class') is not None:
 241 |             del self.attrib['class']
 242 | 
 243 |     @property
 244 |     def base_url(self):
 245 |         """
 246 |         Returns the base URL, given when the page was parsed.
 247 | 
 248 |         Use with ``urlparse.urljoin(el.base_url, href)`` to get
 249 |         absolute URLs.
 250 |         """
 251 |         return self.getroottree().docinfo.URL
 252 | 
 253 |     @property
 254 |     def forms(self):
 255 |         """
 256 |         Return a list of all the forms
 257 |         """
 258 |         return _forms_xpath(self)
 259 | 
 260 |     @property
 261 |     def body(self):
 262 |         """
 263 |         Return the <body> element.  Can be called from a child element
 264 |         to get the document's head.
 265 |         """
 266 |         return self.xpath('//body|//x:body', namespaces={'x':XHTML_NAMESPACE})[0]
 267 | 
 268 |     @property
 269 |     def head(self):
 270 |         """
 271 |         Returns the <head> element.  Can be called from a child
 272 |         element to get the document's head.
 273 |         """
 274 |         return self.xpath('//head|//x:head', namespaces={'x':XHTML_NAMESPACE})[0]
 275 | 
 276 |     @property
 277 |     def label(self):
 278 |         """
 279 |         Get or set any <label> element associated with this element.
 280 |         """
 281 |         id = self.get('id')
 282 |         if not id:
 283 |             return None
 284 |         result = _label_xpath(self, id=id)
 285 |         if not result:
 286 |             return None
 287 |         else:
 288 |             return result[0]
 289 | 
 290 |     @label.setter
 291 |     def label(self, label):
 292 |         id = self.get('id')
 293 |         if not id:
 294 |             raise TypeError(
 295 |                 "You cannot set a label for an element (%r) that has no id"
 296 |                 % self)
 297 |         if _nons(label.tag) != 'label':
 298 |             raise TypeError(
 299 |                 "You can only assign label to a label element (not %r)"
 300 |                 % label)
 301 |         label.set('for', id)
 302 | 
 303 |     @label.deleter
 304 |     def label(self):
 305 |         label = self.label
 306 |         if label is not None:
 307 |             del label.attrib['for']
 308 | 
 309 |     def drop_tree(self):
 310 |         """
 311 |         Removes this element from the tree, including its children and
 312 |         text.  The tail text is joined to the previous element or
 313 |         parent.
 314 |         """
 315 |         parent = self.getparent()
 316 |         assert parent is not None
 317 |         if self.tail:
 318 |             previous = self.getprevious()
 319 |             if previous is None:
 320 |                 parent.text = (parent.text or '') + self.tail
 321 |             else:
 322 |                 previous.tail = (previous.tail or '') + self.tail
 323 |         parent.remove(self)
 324 | 
 325 |     def drop_tag(self):
 326 |         """
 327 |         Remove the tag, but not its children or text.  The children and text
 328 |         are merged into the parent.
 329 | 
 330 |         Example::
 331 | 
 332 |             >>> h = fragment_fromstring('<div>Hello <b>World!</b></div>')
 333 |             >>> h.find('.//b').drop_tag()
 334 |             >>> print(tostring(h, encoding='unicode'))
 335 |             <div>Hello World!</div>
 336 |         """
 337 |         parent = self.getparent()
 338 |         assert parent is not None
 339 |         previous = self.getprevious()
 340 |         if self.text and isinstance(self.tag, str):
 341 |             # not a Comment, etc.
 342 |             if previous is None:
 343 |                 parent.text = (parent.text or '') + self.text
 344 |             else:
 345 |                 previous.tail = (previous.tail or '') + self.text
 346 |         if self.tail:
 347 |             if len(self):
 348 |                 last = self[-1]
 349 |                 last.tail = (last.tail or '') + self.tail
 350 |             elif previous is None:
 351 |                 parent.text = (parent.text or '') + self.tail
 352 |             else:
 353 |                 previous.tail = (previous.tail or '') + self.tail
 354 |         index = parent.index(self)
 355 |         parent[index:index+1] = self[:]
 356 | 
 357 |     def find_rel_links(self, rel):
 358 |         """
 359 |         Find any links like ``<a rel="{rel}">...</a>``; returns a list of elements.
 360 |         """
 361 |         rel = rel.lower()
 362 |         return [el for el in _rel_links_xpath(self)
 363 |                 if el.get('rel').lower() == rel]
 364 | 
 365 |     def find_class(self, class_name):
 366 |         """
 367 |         Find any elements with the given class name.
 368 |         """
 369 |         return _class_xpath(self, class_name=class_name)
 370 | 
 371 |     def get_element_by_id(self, id, *default):
 372 |         """
 373 |         Get the first element in a document with the given id.  If none is
 374 |         found, return the default argument if provided or raise KeyError
 375 |         otherwise.
 376 | 
 377 |         Note that there can be more than one element with the same id,
 378 |         and this isn't uncommon in HTML documents found in the wild.
 379 |         Browsers return only the first match, and this function does
 380 |         the same.
 381 |         """
 382 |         try:
 383 |             # FIXME: should this check for multiple matches?
 384 |             # browsers just return the first one
 385 |             return _id_xpath(self, id=id)[0]
 386 |         except IndexError:
 387 |             if default:
 388 |                 return default[0]
 389 |             else:
 390 |                 raise KeyError(id)
 391 | 
 392 |     def text_content(self):
 393 |         """
 394 |         Return the text content of the tag (and the text in any children).
 395 |         """
 396 |         return _collect_string_content(self)
 397 | 
 398 |     def cssselect(self, expr, translator='html'):
 399 |         """
 400 |         Run the CSS expression on this element and its children,
 401 |         returning a list of the results.
 402 | 
 403 |         Equivalent to lxml.cssselect.CSSSelect(expr, translator='html')(self)
 404 |         -- note that pre-compiling the expression can provide a substantial
 405 |         speedup.
 406 |         """
 407 |         # Do the import here to make the dependency optional.
 408 |         from lxml.cssselect import CSSSelector
 409 |         return CSSSelector(expr, translator=translator)(self)
 410 | 
 411 |     ########################################
 412 |     ## Link functions
 413 |     ########################################
 414 | 
 415 |     def make_links_absolute(self, base_url=None, resolve_base_href=True,
 416 |                             handle_failures=None):
 417 |         """
 418 |         Make all links in the document absolute, given the
 419 |         ``base_url`` for the document (the full URL where the document
 420 |         came from), or if no ``base_url`` is given, then the ``.base_url``
 421 |         of the document.
 422 | 
 423 |         If ``resolve_base_href`` is true, then any ``<base href>``
 424 |         tags in the document are used *and* removed from the document.
 425 |         If it is false then any such tag is ignored.
 426 | 
 427 |         If ``handle_failures`` is None (default), a failure to process
 428 |         a URL will abort the processing.  If set to 'ignore', errors
 429 |         are ignored.  If set to 'discard', failing URLs will be removed.
 430 |         """
 431 |         if base_url is None:
 432 |             base_url = self.base_url
 433 |             if base_url is None:
 434 |                 raise TypeError(
 435 |                     "No base_url given, and the document has no base_url")
 436 |         if resolve_base_href:
 437 |             self.resolve_base_href()
 438 | 
 439 |         if handle_failures == 'ignore':
 440 |             def link_repl(href):
 441 |                 try:
 442 |                     return urljoin(base_url, href)
 443 |                 except ValueError:
 444 |                     return href
 445 |         elif handle_failures == 'discard':
 446 |             def link_repl(href):
 447 |                 try:
 448 |                     return urljoin(base_url, href)
 449 |                 except ValueError:
 450 |                     return None
 451 |         elif handle_failures is None:
 452 |             def link_repl(href):
 453 |                 return urljoin(base_url, href)
 454 |         else:
 455 |             raise ValueError(
 456 |                 "unexpected value for handle_failures: %r" % handle_failures)
 457 | 
 458 |         self.rewrite_links(link_repl)
 459 | 
 460 |     def resolve_base_href(self, handle_failures=None):
 461 |         """
 462 |         Find any ``<base href>`` tag in the document, and apply its
 463 |         values to all links found in the document.  Also remove the
 464 |         tag once it has been applied.
 465 | 
 466 |         If ``handle_failures`` is None (default), a failure to process
 467 |         a URL will abort the processing.  If set to 'ignore', errors
 468 |         are ignored.  If set to 'discard', failing URLs will be removed.
 469 |         """
 470 |         base_href = None
 471 |         basetags = self.xpath('//base[@href]|//x:base[@href]',
 472 |                               namespaces={'x': XHTML_NAMESPACE})
 473 |         for b in basetags:
 474 |             base_href = b.get('href')
 475 |             b.drop_tree()
 476 |         if not base_href:
 477 |             return
 478 |         self.make_links_absolute(base_href, resolve_base_href=False,
 479 |                                  handle_failures=handle_failures)
 480 | 
 481 |     def iterlinks(self):
 482 |         """
 483 |         Yield (element, attribute, link, pos), where attribute may be None
 484 |         (indicating the link is in the text).  ``pos`` is the position
 485 |         where the link occurs; often 0, but sometimes something else in
 486 |         the case of links in stylesheets or style tags.
 487 | 
 488 |         Note: <base href> is *not* taken into account in any way.  The
 489 |         link you get is exactly the link in the document.
 490 | 
 491 |         Note: multiple links inside of a single text string or
 492 |         attribute value are returned in reversed order.  This makes it
 493 |         possible to replace or delete them from the text string value
 494 |         based on their reported text positions.  Otherwise, a
 495 |         modification at one text position can change the positions of
 496 |         links reported later on.
 497 |         """
 498 |         link_attrs = defs.link_attrs
 499 |         for el in self.iter(etree.Element):
 500 |             attribs = el.attrib
 501 |             tag = _nons(el.tag)
 502 |             if tag == 'object':
 503 |                 codebase = None
 504 |                 ## <object> tags have attributes that are relative to
 505 |                 ## codebase
 506 |                 if 'codebase' in attribs:
 507 |                     codebase = el.get('codebase')
 508 |                     yield (el, 'codebase', codebase, 0)
 509 |                 for attrib in ('classid', 'data'):
 510 |                     if attrib in attribs:
 511 |                         value = el.get(attrib)
 512 |                         if codebase is not None:
 513 |                             value = urljoin(codebase, value)
 514 |                         yield (el, attrib, value, 0)
 515 |                 if 'archive' in attribs:
 516 |                     for match in _archive_re.finditer(el.get('archive')):
 517 |                         value = match.group(0)
 518 |                         if codebase is not None:
 519 |                             value = urljoin(codebase, value)
 520 |                         yield (el, 'archive', value, match.start())
 521 |             else:
 522 |                 for attrib in link_attrs:
 523 |                     if attrib in attribs:
 524 |                         yield (el, attrib, attribs[attrib], 0)
 525 |             if tag == 'meta':
 526 |                 http_equiv = attribs.get('http-equiv', '').lower()
 527 |                 if http_equiv == 'refresh':
 528 |                     content = attribs.get('content', '')
 529 |                     match = _parse_meta_refresh_url(content)
 530 |                     url = (match.group('url') if match else content).strip()
 531 |                     # unexpected content means the redirect won't work, but we might
 532 |                     # as well be permissive and return the entire string.
 533 |                     if url:
 534 |                         url, pos = _unquote_match(
 535 |                             url, match.start('url') if match else content.find(url))
 536 |                         yield (el, 'content', url, pos)
 537 |             elif tag == 'param':
 538 |                 valuetype = el.get('valuetype') or ''
 539 |                 if valuetype.lower() == 'ref':
 540 |                     ## FIXME: while it's fine we *find* this link,
 541 |                     ## according to the spec we aren't supposed to
 542 |                     ## actually change the value, including resolving
 543 |                     ## it.  It can also still be a link, even if it
 544 |                     ## doesn't have a valuetype="ref" (which seems to be the norm)
 545 |                     ## http://www.w3.org/TR/html401/struct/objects.html#adef-valuetype
 546 |                     yield (el, 'value', el.get('value'), 0)
 547 |             elif tag == 'style' and el.text:
 548 |                 urls = [
 549 |                     # (start_pos, url)
 550 |                     _unquote_match(match.group(1), match.start(1))[::-1]
 551 |                     for match in _iter_css_urls(el.text)
 552 |                     ] + [
 553 |                     (match.start(1), match.group(1))
 554 |                     for match in _iter_css_imports(el.text)
 555 |                     ]
 556 |                 if urls:
 557 |                     # sort by start pos to bring both match sets back into order
 558 |                     # and reverse the list to report correct positions despite
 559 |                     # modifications
 560 |                     urls.sort(reverse=True)
 561 |                     for start, url in urls:
 562 |                         yield (el, None, url, start)
 563 |             if 'style' in attribs:
 564 |                 urls = list(_iter_css_urls(attribs['style']))
 565 |                 if urls:
 566 |                     # return in reversed order to simplify in-place modifications
 567 |                     for match in urls[::-1]:
 568 |                         url, start = _unquote_match(match.group(1), match.start(1))
 569 |                         yield (el, 'style', url, start)
 570 | 
 571 |     def rewrite_links(self, link_repl_func, resolve_base_href=True,
 572 |                       base_href=None):
 573 |         """
 574 |         Rewrite all the links in the document.  For each link
 575 |         ``link_repl_func(link)`` will be called, and the return value
 576 |         will replace the old link.
 577 | 
 578 |         Note that links may not be absolute (unless you first called
 579 |         ``make_links_absolute()``), and may be internal (e.g.,
 580 |         ``'#anchor'``).  They can also be values like
 581 |         ``'mailto:email'`` or ``'javascript:expr'``.
 582 | 
 583 |         If you give ``base_href`` then all links passed to
 584 |         ``link_repl_func()`` will take that into account.
 585 | 
 586 |         If the ``link_repl_func`` returns None, the attribute or
 587 |         tag text will be removed completely.
 588 |         """
 589 |         if base_href is not None:
 590 |             # FIXME: this can be done in one pass with a wrapper
 591 |             # around link_repl_func
 592 |             self.make_links_absolute(
 593 |                 base_href, resolve_base_href=resolve_base_href)
 594 |         elif resolve_base_href:
 595 |             self.resolve_base_href()
 596 | 
 597 |         for el, attrib, link, pos in self.iterlinks():
 598 |             new_link = link_repl_func(link.strip())
 599 |             if new_link == link:
 600 |                 continue
 601 |             if new_link is None:
 602 |                 # Remove the attribute or element content
 603 |                 if attrib is None:
 604 |                     el.text = ''
 605 |                 else:
 606 |                     del el.attrib[attrib]
 607 |                 continue
 608 | 
 609 |             if attrib is None:
 610 |                 new = el.text[:pos] + new_link + el.text[pos+len(link):]
 611 |                 el.text = new
 612 |             else:
 613 |                 cur = el.get(attrib)
 614 |                 if not pos and len(cur) == len(link):
 615 |                     new = new_link  # most common case
 616 |                 else:
 617 |                     new = cur[:pos] + new_link + cur[pos+len(link):]
 618 |                 el.set(attrib, new)
 619 | 
 620 | 
 621 | class _MethodFunc:
 622 |     """
 623 |     An object that represents a method on an element as a function;
 624 |     the function takes either an element or an HTML string.  It
 625 |     returns whatever the function normally returns, or if the function
 626 |     works in-place (and so returns None) it returns a serialized form
 627 |     of the resulting document.
 628 |     """
 629 |     def __init__(self, name, copy=False, source_class=HtmlMixin):
 630 |         self.name = name
 631 |         self.copy = copy
 632 |         self.__doc__ = getattr(source_class, self.name).__doc__
 633 |     def __call__(self, doc, *args, **kw):
 634 |         result_type = type(doc)
 635 |         if isinstance(doc, (str, bytes)):
 636 |             if 'copy' in kw:
 637 |                 raise TypeError(
 638 |                     "The keyword 'copy' can only be used with element inputs to %s, not a string input" % self.name)
 639 |             doc = fromstring(doc, **kw)
 640 |         else:
 641 |             if 'copy' in kw:
 642 |                 make_a_copy = kw.pop('copy')
 643 |             else:
 644 |                 make_a_copy = self.copy
 645 |             if make_a_copy:
 646 |                 doc = copy.deepcopy(doc)
 647 |         meth = getattr(doc, self.name)
 648 |         result = meth(*args, **kw)
 649 |         # FIXME: this None test is a bit sloppy
 650 |         if result is None:
 651 |             # Then return what we got in
 652 |             return _transform_result(result_type, doc)
 653 |         else:
 654 |             return result
 655 | 
 656 | 
 657 | find_rel_links = _MethodFunc('find_rel_links', copy=False)
 658 | find_class = _MethodFunc('find_class', copy=False)
 659 | make_links_absolute = _MethodFunc('make_links_absolute', copy=True)
 660 | resolve_base_href = _MethodFunc('resolve_base_href', copy=True)
 661 | iterlinks = _MethodFunc('iterlinks', copy=False)
 662 | rewrite_links = _MethodFunc('rewrite_links', copy=True)
 663 | 
 664 | 
 665 | class HtmlComment(HtmlMixin, etree.CommentBase):
 666 |     pass
 667 | 
 668 | 
 669 | class HtmlElement(HtmlMixin, etree.ElementBase):
 670 |     pass
 671 | 
 672 | 
 673 | class HtmlProcessingInstruction(HtmlMixin, etree.PIBase):
 674 |     pass
 675 | 
 676 | 
 677 | class HtmlEntity(HtmlMixin, etree.EntityBase):
 678 |     pass
 679 | 
 680 | 
 681 | class HtmlElementClassLookup(etree.CustomElementClassLookup):
 682 |     """A lookup scheme for HTML Element classes.
 683 | 
 684 |     To create a lookup instance with different Element classes, pass a tag
 685 |     name mapping of Element classes in the ``classes`` keyword argument and/or
 686 |     a tag name mapping of Mixin classes in the ``mixins`` keyword argument.
 687 |     The special key '*' denotes a Mixin class that should be mixed into all
 688 |     Element classes.
 689 |     """
 690 |     _default_element_classes = {}
 691 | 
 692 |     def __init__(self, classes=None, mixins=None):
 693 |         etree.CustomElementClassLookup.__init__(self)
 694 |         if classes is None:
 695 |             classes = self._default_element_classes.copy()
 696 |         if mixins:
 697 |             mixers = {}
 698 |             for name, value in mixins:
 699 |                 if name == '*':
 700 |                     for n in classes.keys():
 701 |                         mixers.setdefault(n, []).append(value)
 702 |                 else:
 703 |                     mixers.setdefault(name, []).append(value)
 704 |             for name, mix_bases in mixers.items():
 705 |                 cur = classes.get(name, HtmlElement)
 706 |                 bases = tuple(mix_bases + [cur])
 707 |                 classes[name] = type(cur.__name__, bases, {})
 708 |         self._element_classes = classes
 709 | 
 710 |     def lookup(self, node_type, document, namespace, name):
 711 |         if node_type == 'element':
 712 |             return self._element_classes.get(name.lower(), HtmlElement)
 713 |         elif node_type == 'comment':
 714 |             return HtmlComment
 715 |         elif node_type == 'PI':
 716 |             return HtmlProcessingInstruction
 717 |         elif node_type == 'entity':
 718 |             return HtmlEntity
 719 |         # Otherwise normal lookup
 720 |         return None
 721 | 
 722 | 
 723 | ################################################################################
 724 | # parsing
 725 | ################################################################################
 726 | 
 727 | _looks_like_full_html_unicode = re.compile(
 728 |     r'^\s*<(?:html|!doctype)', re.I).match
 729 | _looks_like_full_html_bytes = re.compile(
 730 |     br'^\s*<(?:html|!doctype)', re.I).match
 731 | 
 732 | 
 733 | def document_fromstring(html, parser=None, ensure_head_body=False, **kw):
 734 |     if parser is None:
 735 |         parser = html_parser
 736 |     value = etree.fromstring(html, parser, **kw)
 737 |     if value is None:
 738 |         raise etree.ParserError(
 739 |             "Document is empty")
 740 |     if ensure_head_body and value.find('head') is None:
 741 |         value.insert(0, Element('head'))
 742 |     if ensure_head_body and value.find('body') is None:
 743 |         value.append(Element('body'))
 744 |     return value
 745 | 
 746 | 
 747 | def fragments_fromstring(html, no_leading_text=False, base_url=None,
 748 |                          parser=None, **kw):
 749 |     """Parses several HTML elements, returning a list of elements.
 750 | 
 751 |     The first item in the list may be a string.
 752 |     If no_leading_text is true, then it will be an error if there is
 753 |     leading text, and it will always be a list of only elements.
 754 | 
 755 |     base_url will set the document's base_url attribute
 756 |     (and the tree's docinfo.URL).
 757 |     """
 758 |     if parser is None:
 759 |         parser = html_parser
 760 |     # FIXME: check what happens when you give html with a body, head, etc.
 761 |     if isinstance(html, bytes):
 762 |         if not _looks_like_full_html_bytes(html):
 763 |             # can't use %-formatting in early Py3 versions
 764 |             html = (b'<html><body>' + html +
 765 |                     b'</body></html>')
 766 |     else:
 767 |         if not _looks_like_full_html_unicode(html):
 768 |             html = '<html><body>%s</body></html>' % html
 769 |     doc = document_fromstring(html, parser=parser, base_url=base_url, **kw)
 770 |     assert _nons(doc.tag) == 'html'
 771 |     bodies = [e for e in doc if _nons(e.tag) == 'body']
 772 |     assert len(bodies) == 1, ("too many bodies: %r in %r" % (bodies, html))
 773 |     body = bodies[0]
 774 |     elements = []
 775 |     if no_leading_text and body.text and body.text.strip():
 776 |         raise etree.ParserError(
 777 |             "There is leading text: %r" % body.text)
 778 |     if body.text and body.text.strip():
 779 |         elements.append(body.text)
 780 |     elements.extend(body)
 781 |     # FIXME: removing the reference to the parent artificial document
 782 |     # would be nice
 783 |     return elements
 784 | 
 785 | 
 786 | def fragment_fromstring(html, create_parent=False, base_url=None,
 787 |                         parser=None, **kw):
 788 |     """
 789 |     Parses a single HTML element; it is an error if there is more than
 790 |     one element, or if anything but whitespace precedes or follows the
 791 |     element.
 792 | 
 793 |     If ``create_parent`` is true (or is a tag name) then a parent node
 794 |     will be created to encapsulate the HTML in a single element.  In this
 795 |     case, leading or trailing text is also allowed, as are multiple elements
 796 |     as result of the parsing.
 797 | 
 798 |     Passing a ``base_url`` will set the document's ``base_url`` attribute
 799 |     (and the tree's docinfo.URL).
 800 |     """
 801 |     if parser is None:
 802 |         parser = html_parser
 803 | 
 804 |     accept_leading_text = bool(create_parent)
 805 | 
 806 |     elements = fragments_fromstring(
 807 |         html, parser=parser, no_leading_text=not accept_leading_text,
 808 |         base_url=base_url, **kw)
 809 | 
 810 |     if create_parent:
 811 |         if not isinstance(create_parent, str):
 812 |             create_parent = 'div'
 813 |         new_root = Element(create_parent)
 814 |         if elements:
 815 |             if isinstance(elements[0], str):
 816 |                 new_root.text = elements[0]
 817 |                 del elements[0]
 818 |             new_root.extend(elements)
 819 |         return new_root
 820 | 
 821 |     if not elements:
 822 |         raise etree.ParserError('No elements found')
 823 |     if len(elements) > 1:
 824 |         raise etree.ParserError(
 825 |             "Multiple elements found (%s)"
 826 |             % ', '.join([_element_name(e) for e in elements]))
 827 |     el = elements[0]
 828 |     if el.tail and el.tail.strip():
 829 |         raise etree.ParserError(
 830 |             "Element followed by text: %r" % el.tail)
 831 |     el.tail = None
 832 |     return el
 833 | 
 834 | 
 835 | def fromstring(html, base_url=None, parser=None, **kw):
 836 |     """
 837 |     Parse the html, returning a single element/document.
 838 | 
 839 |     This tries to minimally parse the chunk of text, without knowing if it
 840 |     is a fragment or a document.
 841 | 
 842 |     base_url will set the document's base_url attribute (and the tree's docinfo.URL)
 843 |     """
 844 |     if parser is None:
 845 |         parser = html_parser
 846 |     if isinstance(html, bytes):
 847 |         is_full_html = _looks_like_full_html_bytes(html)
 848 |     else:
 849 |         is_full_html = _looks_like_full_html_unicode(html)
 850 |     doc = document_fromstring(html, parser=parser, base_url=base_url, **kw)
 851 |     if is_full_html:
 852 |         return doc
 853 |     # otherwise, lets parse it out...
 854 |     bodies = doc.findall('body')
 855 |     if not bodies:
 856 |         bodies = doc.findall('{%s}body' % XHTML_NAMESPACE)
 857 |     if bodies:
 858 |         body = bodies[0]
 859 |         if len(bodies) > 1:
 860 |             # Somehow there are multiple bodies, which is bad, but just
 861 |             # smash them into one body
 862 |             for other_body in bodies[1:]:
 863 |                 if other_body.text:
 864 |                     if len(body):
 865 |                         body[-1].tail = (body[-1].tail or '') + other_body.text
 866 |                     else:
 867 |                         body.text = (body.text or '') + other_body.text
 868 |                 body.extend(other_body)
 869 |                 # We'll ignore tail
 870 |                 # I guess we are ignoring attributes too
 871 |                 other_body.drop_tree()
 872 |     else:
 873 |         body = None
 874 |     heads = doc.findall('head')
 875 |     if not heads:
 876 |         heads = doc.findall('{%s}head' % XHTML_NAMESPACE)
 877 |     if heads:
 878 |         # Well, we have some sort of structure, so lets keep it all
 879 |         head = heads[0]
 880 |         if len(heads) > 1:
 881 |             for other_head in heads[1:]:
 882 |                 head.extend(other_head)
 883 |                 # We don't care about text or tail in a head
 884 |                 other_head.drop_tree()
 885 |         return doc
 886 |     if body is None:
 887 |         return doc
 888 |     if (len(body) == 1 and (not body.text or not body.text.strip())
 889 |         and (not body[-1].tail or not body[-1].tail.strip())):
 890 |         # The body has just one element, so it was probably a single
 891 |         # element passed in
 892 |         return body[0]
 893 |     # Now we have a body which represents a bunch of tags which have the
 894 |     # content that was passed in.  We will create a fake container, which
 895 |     # is the body tag, except <body> implies too much structure.
 896 |     if _contains_block_level_tag(body):
 897 |         body.tag = 'div'
 898 |     else:
 899 |         body.tag = 'span'
 900 |     return body
 901 | 
 902 | 
 903 | def parse(filename_or_url, parser=None, base_url=None, **kw):
 904 |     """
 905 |     Parse a filename, URL, or file-like object into an HTML document
 906 |     tree.  Note: this returns a tree, not an element.  Use
 907 |     ``parse(...).getroot()`` to get the document root.
 908 | 
 909 |     You can override the base URL with the ``base_url`` keyword.  This
 910 |     is most useful when parsing from a file-like object.
 911 |     """
 912 |     if parser is None:
 913 |         parser = html_parser
 914 |     return etree.parse(filename_or_url, parser, base_url=base_url, **kw)
 915 | 
 916 | 
 917 | def _contains_block_level_tag(el):
 918 |     # FIXME: I could do this with XPath, but would that just be
 919 |     # unnecessarily slow?
 920 |     for el in el.iter(etree.Element):
 921 |         if _nons(el.tag) in defs.block_tags:
 922 |             return True
 923 |     return False
 924 | 
 925 | 
 926 | def _element_name(el):
 927 |     if isinstance(el, etree.CommentBase):
 928 |         return 'comment'
 929 |     elif isinstance(el, str):
 930 |         return 'string'
 931 |     else:
 932 |         return _nons(el.tag)
 933 | 
 934 | 
 935 | ################################################################################
 936 | # form handling
 937 | ################################################################################
 938 | 
 939 | class FormElement(HtmlElement):
 940 |     """
 941 |     Represents a <form> element.
 942 |     """
 943 | 
 944 |     @property
 945 |     def inputs(self):
 946 |         """
 947 |         Returns an accessor for all the input elements in the form.
 948 | 
 949 |         See `InputGetter` for more information about the object.
 950 |         """
 951 |         return InputGetter(self)
 952 | 
 953 |     @property
 954 |     def fields(self):
 955 |         """
 956 |         Dictionary-like object that represents all the fields in this
 957 |         form.  You can set values in this dictionary to effect the
 958 |         form.
 959 |         """
 960 |         return FieldsDict(self.inputs)
 961 | 
 962 |     @fields.setter
 963 |     def fields(self, value):
 964 |         fields = self.fields
 965 |         prev_keys = fields.keys()
 966 |         for key, value in value.items():
 967 |             if key in prev_keys:
 968 |                 prev_keys.remove(key)
 969 |             fields[key] = value
 970 |         for key in prev_keys:
 971 |             if key is None:
 972 |                 # Case of an unnamed input; these aren't really
 973 |                 # expressed in form_values() anyway.
 974 |                 continue
 975 |             fields[key] = None
 976 | 
 977 |     def _name(self):
 978 |         if self.get('name'):
 979 |             return self.get('name')
 980 |         elif self.get('id'):
 981 |             return '#' + self.get('id')
 982 |         iter_tags = self.body.iter
 983 |         forms = list(iter_tags('form'))
 984 |         if not forms:
 985 |             forms = list(iter_tags('{%s}form' % XHTML_NAMESPACE))
 986 |         return str(forms.index(self))
 987 | 
 988 |     def form_values(self):
 989 |         """
 990 |         Return a list of tuples of the field values for the form.
 991 |         This is suitable to be passed to ``urllib.urlencode()``.
 992 |         """
 993 |         results = []
 994 |         for el in self.inputs:
 995 |             name = el.name
 996 |             if not name or 'disabled' in el.attrib:
 997 |                 continue
 998 |             tag = _nons(el.tag)
 999 |             if tag == 'textarea':
1000 |                 results.append((name, el.value))
1001 |             elif tag == 'select':
1002 |                 value = el.value
1003 |                 if el.multiple:
1004 |                     for v in value:
1005 |                         results.append((name, v))
1006 |                 elif value is not None:
1007 |                     results.append((name, el.value))
1008 |             else:
1009 |                 assert tag == 'input', (
1010 |                     "Unexpected tag: %r" % el)
1011 |                 if el.checkable and not el.checked:
1012 |                     continue
1013 |                 if el.type in ('submit', 'image', 'reset', 'file'):
1014 |                     continue
1015 |                 value = el.value
1016 |                 if value is not None:
1017 |                     results.append((name, el.value))
1018 |         return results
1019 | 
1020 |     @property
1021 |     def action(self):
1022 |         """
1023 |         Get/set the form's ``action`` attribute.
1024 |         """
1025 |         base_url = self.base_url
1026 |         action = self.get('action')
1027 |         if base_url and action is not None:
1028 |             return urljoin(base_url, action)
1029 |         else:
1030 |             return action
1031 | 
1032 |     @action.setter
1033 |     def action(self, value):
1034 |         self.set('action', value)
1035 | 
1036 |     @action.deleter
1037 |     def action(self):
1038 |         attrib = self.attrib
1039 |         if 'action' in attrib:
1040 |             del attrib['action']
1041 | 
1042 |     @property
1043 |     def method(self):
1044 |         """
1045 |         Get/set the form's method.  Always returns a capitalized
1046 |         string, and defaults to ``'GET'``
1047 |         """
1048 |         return self.get('method', 'GET').upper()
1049 | 
1050 |     @method.setter
1051 |     def method(self, value):
1052 |         self.set('method', value.upper())
1053 | 
1054 | 
1055 | HtmlElementClassLookup._default_element_classes['form'] = FormElement
1056 | 
1057 | 
1058 | def submit_form(form, extra_values=None, open_http=None):
1059 |     """
1060 |     Helper function to submit a form.  Returns a file-like object, as from
1061 |     ``urllib.urlopen()``.  This object also has a ``.geturl()`` function,
1062 |     which shows the URL if there were any redirects.
1063 | 
1064 |     You can use this like::
1065 | 
1066 |         form = doc.forms[0]
1067 |         form.inputs['foo'].value = 'bar' # etc
1068 |         response = form.submit()
1069 |         doc = parse(response)
1070 |         doc.make_links_absolute(response.geturl())
1071 | 
1072 |     To change the HTTP requester, pass a function as ``open_http`` keyword
1073 |     argument that opens the URL for you.  The function must have the following
1074 |     signature::
1075 | 
1076 |         open_http(method, URL, values)
1077 | 
1078 |     The action is one of 'GET' or 'POST', the URL is the target URL as a
1079 |     string, and the values are a sequence of ``(name, value)`` tuples with the
1080 |     form data.
1081 |     """
1082 |     values = form.form_values()
1083 |     if extra_values:
1084 |         if hasattr(extra_values, 'items'):
1085 |             extra_values = extra_values.items()
1086 |         values.extend(extra_values)
1087 |     if open_http is None:
1088 |         open_http = open_http_urllib
1089 |     if form.action:
1090 |         url = form.action
1091 |     else:
1092 |         url = form.base_url
1093 |     return open_http(form.method, url, values)
1094 | 
1095 | 
1096 | def open_http_urllib(method, url, values):
1097 |     if not url:
1098 |         raise ValueError("cannot submit, no URL provided")
1099 |     ## FIXME: should test that it's not a relative URL or something
1100 |     try:
1101 |         from urllib import urlencode, urlopen
1102 |     except ImportError: # Python 3
1103 |         from urllib.request import urlopen
1104 |         from urllib.parse import urlencode
1105 |     if method == 'GET':
1106 |         if '?' in url:
1107 |             url += '&'
1108 |         else:
1109 |             url += '?'
1110 |         url += urlencode(values)
1111 |         data = None
1112 |     else:
1113 |         data = urlencode(values)
1114 |         if not isinstance(data, bytes):
1115 |             data = data.encode('ASCII')
1116 |     return urlopen(url, data)
1117 | 
1118 | 
1119 | class FieldsDict(MutableMapping):
1120 | 
1121 |     def __init__(self, inputs):
1122 |         self.inputs = inputs
1123 |     def __getitem__(self, item):
1124 |         return self.inputs[item].value
1125 |     def __setitem__(self, item, value):
1126 |         self.inputs[item].value = value
1127 |     def __delitem__(self, item):
1128 |         raise KeyError(
1129 |             "You cannot remove keys from ElementDict")
1130 |     def keys(self):
1131 |         return self.inputs.keys()
1132 |     def __contains__(self, item):
1133 |         return item in self.inputs
1134 |     def __iter__(self):
1135 |         return iter(self.inputs.keys())
1136 |     def __len__(self):
1137 |         return len(self.inputs)
1138 | 
1139 |     def __repr__(self):
1140 |         return '<%s for form %s>' % (
1141 |             self.__class__.__name__,
1142 |             self.inputs.form._name())
1143 | 
1144 | 
1145 | class InputGetter:
1146 | 
1147 |     """
1148 |     An accessor that represents all the input fields in a form.
1149 | 
1150 |     You can get fields by name from this, with
1151 |     ``form.inputs['field_name']``.  If there are a set of checkboxes
1152 |     with the same name, they are returned as a list (a `CheckboxGroup`
1153 |     which also allows value setting).  Radio inputs are handled
1154 |     similarly.  Use ``.keys()`` and ``.items()`` to process all fields
1155 |     in this way.
1156 | 
1157 |     You can also iterate over this to get all input elements.  This
1158 |     won't return the same thing as if you get all the names, as
1159 |     checkboxes and radio elements are returned individually.
1160 |     """
1161 | 
1162 |     def __init__(self, form):
1163 |         self.form = form
1164 | 
1165 |     def __repr__(self):
1166 |         return '<%s for form %s>' % (
1167 |             self.__class__.__name__,
1168 |             self.form._name())
1169 | 
1170 |     ## FIXME: there should be more methods, and it's unclear if this is
1171 |     ## a dictionary-like object or list-like object
1172 | 
1173 |     def __getitem__(self, name):
1174 |         fields = [field for field in self if field.name == name]
1175 |         if not fields:
1176 |             raise KeyError("No input element with the name %r" % name)
1177 | 
1178 |         input_type = fields[0].get('type')
1179 |         if input_type == 'radio' and len(fields) > 1:
1180 |             group = RadioGroup(fields)
1181 |             group.name = name
1182 |             return group
1183 |         elif input_type == 'checkbox' and len(fields) > 1:
1184 |             group = CheckboxGroup(fields)
1185 |             group.name = name
1186 |             return group
1187 |         else:
1188 |             # I don't like throwing away elements like this
1189 |             return fields[0]
1190 | 
1191 |     def __contains__(self, name):
1192 |         for field in self:
1193 |             if field.name == name:
1194 |                 return True
1195 |         return False
1196 | 
1197 |     def keys(self):
1198 |         """
1199 |         Returns all unique field names, in document order.
1200 | 
1201 |         :return: A list of all unique field names.
1202 |         """
1203 |         names = []
1204 |         seen = {None}
1205 |         for el in self:
1206 |             name = el.name
1207 |             if name not in seen:
1208 |                 names.append(name)
1209 |                 seen.add(name)
1210 |         return names
1211 | 
1212 |     def items(self):
1213 |         """
1214 |         Returns all fields with their names, similar to dict.items().
1215 | 
1216 |         :return: A list of (name, field) tuples.
1217 |         """
1218 |         items = []
1219 |         seen = set()
1220 |         for el in self:
1221 |             name = el.name
1222 |             if name not in seen:
1223 |                 seen.add(name)
1224 |                 items.append((name, self[name]))
1225 |         return items
1226 | 
1227 |     def __iter__(self):
1228 |         return self.form.iter('select', 'input', 'textarea')
1229 | 
1230 |     def __len__(self):
1231 |         return sum(1 for _ in self)
1232 | 
1233 | 
1234 | class InputMixin:
1235 |     """
1236 |     Mix-in for all input elements (input, select, and textarea)
1237 |     """
1238 |     @property
1239 |     def name(self):
1240 |         """
1241 |         Get/set the name of the element
1242 |         """
1243 |         return self.get('name')
1244 | 
1245 |     @name.setter
1246 |     def name(self, value):
1247 |         self.set('name', value)
1248 | 
1249 |     @name.deleter
1250 |     def name(self):
1251 |         attrib = self.attrib
1252 |         if 'name' in attrib:
1253 |             del attrib['name']
1254 | 
1255 |     def __repr__(self):
1256 |         type_name = getattr(self, 'type', None)
1257 |         if type_name:
1258 |             type_name = ' type=%r' % type_name
1259 |         else:
1260 |             type_name = ''
1261 |         return '<%s %x name=%r%s>' % (
1262 |             self.__class__.__name__, id(self), self.name, type_name)
1263 | 
1264 | 
1265 | class TextareaElement(InputMixin, HtmlElement):
1266 |     """
1267 |     ``<textarea>`` element.  You can get the name with ``.name`` and
1268 |     get/set the value with ``.value``
1269 |     """
1270 |     @property
1271 |     def value(self):
1272 |         """
1273 |         Get/set the value (which is the contents of this element)
1274 |         """
1275 |         content = self.text or ''
1276 |         if self.tag.startswith("{%s}" % XHTML_NAMESPACE):
1277 |             serialisation_method = 'xml'
1278 |         else:
1279 |             serialisation_method = 'html'
1280 |         for el in self:
1281 |             # it's rare that we actually get here, so let's not use ''.join()
1282 |             content += etree.tostring(
1283 |                 el, method=serialisation_method, encoding='unicode')
1284 |         return content
1285 | 
1286 |     @value.setter
1287 |     def value(self, value):
1288 |         del self[:]
1289 |         self.text = value
1290 | 
1291 |     @value.deleter
1292 |     def value(self):
1293 |         self.text = ''
1294 |         del self[:]
1295 | 
1296 | 
1297 | HtmlElementClassLookup._default_element_classes['textarea'] = TextareaElement
1298 | 
1299 | 
1300 | class SelectElement(InputMixin, HtmlElement):
1301 |     """
1302 |     ``<select>`` element.  You can get the name with ``.name``.
1303 | 
1304 |     ``.value`` will be the value of the selected option, unless this
1305 |     is a multi-select element (``<select multiple>``), in which case
1306 |     it will be a set-like object.  In either case ``.value_options``
1307 |     gives the possible values.
1308 | 
1309 |     The boolean attribute ``.multiple`` shows if this is a
1310 |     multi-select.
1311 |     """
1312 |     @property
1313 |     def value(self):
1314 |         """
1315 |         Get/set the value of this select (the selected option).
1316 | 
1317 |         If this is a multi-select, this is a set-like object that
1318 |         represents all the selected options.
1319 |         """
1320 |         if self.multiple:
1321 |             return MultipleSelectOptions(self)
1322 |         options = _options_xpath(self)
1323 | 
1324 |         try:
1325 |             selected_option = next(el for el in reversed(options) if el.get('selected') is not None)
1326 |         except StopIteration:
1327 |             try:
1328 |                 selected_option = next(el for el in options if el.get('disabled') is None)
1329 |             except StopIteration:
1330 |                 return None
1331 |         value = selected_option.get('value')
1332 |         if value is None:
1333 |             value = (selected_option.text or '').strip()
1334 |         return value
1335 | 
1336 |     @value.setter
1337 |     def value(self, value):
1338 |         if self.multiple:
1339 |             if isinstance(value, str):
1340 |                 raise TypeError("You must pass in a sequence")
1341 |             values = self.value
1342 |             values.clear()
1343 |             values.update(value)
1344 |             return
1345 |         checked_option = None
1346 |         if value is not None:
1347 |             for el in _options_xpath(self):
1348 |                 opt_value = el.get('value')
1349 |                 if opt_value is None:
1350 |                     opt_value = (el.text or '').strip()
1351 |                 if opt_value == value:
1352 |                     checked_option = el
1353 |                     break
1354 |             else:
1355 |                 raise ValueError(
1356 |                     "There is no option with the value of %r" % value)
1357 |         for el in _options_xpath(self):
1358 |             if 'selected' in el.attrib:
1359 |                 del el.attrib['selected']
1360 |         if checked_option is not None:
1361 |             checked_option.set('selected', '')
1362 | 
1363 |     @value.deleter
1364 |     def value(self):
1365 |         # FIXME: should del be allowed at all?
1366 |         if self.multiple:
1367 |             self.value.clear()
1368 |         else:
1369 |             self.value = None
1370 | 
1371 |     @property
1372 |     def value_options(self):
1373 |         """
1374 |         All the possible values this select can have (the ``value``
1375 |         attribute of all the ``<option>`` elements.
1376 |         """
1377 |         options = []
1378 |         for el in _options_xpath(self):
1379 |             value = el.get('value')
1380 |             if value is None:
1381 |                 value = (el.text or '').strip()
1382 |             options.append(value)
1383 |         return options
1384 | 
1385 |     @property
1386 |     def multiple(self):
1387 |         """
1388 |         Boolean attribute: is there a ``multiple`` attribute on this element.
1389 |         """
1390 |         return 'multiple' in self.attrib
1391 | 
1392 |     @multiple.setter
1393 |     def multiple(self, value):
1394 |         if value:
1395 |             self.set('multiple', '')
1396 |         elif 'multiple' in self.attrib:
1397 |             del self.attrib['multiple']
1398 | 
1399 | 
1400 | HtmlElementClassLookup._default_element_classes['select'] = SelectElement
1401 | 
1402 | 
1403 | class MultipleSelectOptions(SetMixin):
1404 |     """
1405 |     Represents all the selected options in a ``<select multiple>`` element.
1406 | 
1407 |     You can add to this set-like option to select an option, or remove
1408 |     to unselect the option.
1409 |     """
1410 | 
1411 |     def __init__(self, select):
1412 |         self.select = select
1413 | 
1414 |     @property
1415 |     def options(self):
1416 |         """
1417 |         Iterator of all the ``<option>`` elements.
1418 |         """
1419 |         return iter(_options_xpath(self.select))
1420 | 
1421 |     def __iter__(self):
1422 |         for option in self.options:
1423 |             if 'selected' in option.attrib:
1424 |                 opt_value = option.get('value')
1425 |                 if opt_value is None:
1426 |                     opt_value = (option.text or '').strip()
1427 |                 yield opt_value
1428 | 
1429 |     def add(self, item):
1430 |         for option in self.options:
1431 |             opt_value = option.get('value')
1432 |             if opt_value is None:
1433 |                 opt_value = (option.text or '').strip()
1434 |             if opt_value == item:
1435 |                 option.set('selected', '')
1436 |                 break
1437 |         else:
1438 |             raise ValueError(
1439 |                 "There is no option with the value %r" % item)
1440 | 
1441 |     def remove(self, item):
1442 |         for option in self.options:
1443 |             opt_value = option.get('value')
1444 |             if opt_value is None:
1445 |                 opt_value = (option.text or '').strip()
1446 |             if opt_value == item:
1447 |                 if 'selected' in option.attrib:
1448 |                     del option.attrib['selected']
1449 |                 else:
1450 |                     raise ValueError(
1451 |                         "The option %r is not currently selected" % item)
1452 |                 break
1453 |         else:
1454 |             raise ValueError(
1455 |                 "There is not option with the value %r" % item)
1456 | 
1457 |     def __repr__(self):
1458 |         return '<%s {%s} for select name=%r>' % (
1459 |             self.__class__.__name__,
1460 |             ', '.join([repr(v) for v in self]),
1461 |             self.select.name)
1462 | 
1463 | 
1464 | class RadioGroup(list):
1465 |     """
1466 |     This object represents several ``<input type=radio>`` elements
1467 |     that have the same name.
1468 | 
1469 |     You can use this like a list, but also use the property
1470 |     ``.value`` to check/uncheck inputs.  Also you can use
1471 |     ``.value_options`` to get the possible values.
1472 |     """
1473 |     @property
1474 |     def value(self):
1475 |         """
1476 |         Get/set the value, which checks the radio with that value (and
1477 |         unchecks any other value).
1478 |         """
1479 |         for el in self:
1480 |             if 'checked' in el.attrib:
1481 |                 return el.get('value')
1482 |         return None
1483 | 
1484 |     @value.setter
1485 |     def value(self, value):
1486 |         checked_option = None
1487 |         if value is not None:
1488 |             for el in self:
1489 |                 if el.get('value') == value:
1490 |                     checked_option = el
1491 |                     break
1492 |             else:
1493 |                 raise ValueError("There is no radio input with the value %r" % value)
1494 |         for el in self:
1495 |             if 'checked' in el.attrib:
1496 |                 del el.attrib['checked']
1497 |         if checked_option is not None:
1498 |             checked_option.set('checked', '')
1499 | 
1500 |     @value.deleter
1501 |     def value(self):
1502 |         self.value = None
1503 | 
1504 |     @property
1505 |     def value_options(self):
1506 |         """
1507 |         Returns a list of all the possible values.
1508 |         """
1509 |         return [el.get('value') for el in self]
1510 | 
1511 |     def __repr__(self):
1512 |         return '%s(%s)' % (
1513 |             self.__class__.__name__,
1514 |             list.__repr__(self))
1515 | 
1516 | 
1517 | class CheckboxGroup(list):
1518 |     """
1519 |     Represents a group of checkboxes (``<input type=checkbox>``) that
1520 |     have the same name.
1521 | 
1522 |     In addition to using this like a list, the ``.value`` attribute
1523 |     returns a set-like object that you can add to or remove from to
1524 |     check and uncheck checkboxes.  You can also use ``.value_options``
1525 |     to get the possible values.
1526 |     """
1527 |     @property
1528 |     def value(self):
1529 |         """
1530 |         Return a set-like object that can be modified to check or
1531 |         uncheck individual checkboxes according to their value.
1532 |         """
1533 |         return CheckboxValues(self)
1534 | 
1535 |     @value.setter
1536 |     def value(self, value):
1537 |         values = self.value
1538 |         values.clear()
1539 |         if not hasattr(value, '__iter__'):
1540 |             raise ValueError(
1541 |                 "A CheckboxGroup (name=%r) must be set to a sequence (not %r)"
1542 |                 % (self[0].name, value))
1543 |         values.update(value)
1544 | 
1545 |     @value.deleter
1546 |     def value(self):
1547 |         self.value.clear()
1548 | 
1549 |     @property
1550 |     def value_options(self):
1551 |         """
1552 |         Returns a list of all the possible values.
1553 |         """
1554 |         return [el.get('value') for el in self]
1555 | 
1556 |     def __repr__(self):
1557 |         return '%s(%s)' % (
1558 |             self.__class__.__name__, list.__repr__(self))
1559 | 
1560 | 
1561 | class CheckboxValues(SetMixin):
1562 |     """
1563 |     Represents the values of the checked checkboxes in a group of
1564 |     checkboxes with the same name.
1565 |     """
1566 | 
1567 |     def __init__(self, group):
1568 |         self.group = group
1569 | 
1570 |     def __iter__(self):
1571 |         return iter([
1572 |             el.get('value')
1573 |             for el in self.group
1574 |             if 'checked' in el.attrib])
1575 | 
1576 |     def add(self, value):
1577 |         for el in self.group:
1578 |             if el.get('value') == value:
1579 |                 el.set('checked', '')
1580 |                 break
1581 |         else:
1582 |             raise KeyError("No checkbox with value %r" % value)
1583 | 
1584 |     def remove(self, value):
1585 |         for el in self.group:
1586 |             if el.get('value') == value:
1587 |                 if 'checked' in el.attrib:
1588 |                     del el.attrib['checked']
1589 |                 else:
1590 |                     raise KeyError(
1591 |                         "The checkbox with value %r was already unchecked" % value)
1592 |                 break
1593 |         else:
1594 |             raise KeyError(
1595 |                 "No checkbox with value %r" % value)
1596 | 
1597 |     def __repr__(self):
1598 |         return '<%s {%s} for checkboxes name=%r>' % (
1599 |             self.__class__.__name__,
1600 |             ', '.join([repr(v) for v in self]),
1601 |             self.group.name)
1602 | 
1603 | 
1604 | class InputElement(InputMixin, HtmlElement):
1605 |     """
1606 |     Represents an ``<input>`` element.
1607 | 
1608 |     You can get the type with ``.type`` (which is lower-cased and
1609 |     defaults to ``'text'``).
1610 | 
1611 |     Also you can get and set the value with ``.value``
1612 | 
1613 |     Checkboxes and radios have the attribute ``input.checkable ==
1614 |     True`` (for all others it is false) and a boolean attribute
1615 |     ``.checked``.
1616 | 
1617 |     """
1618 | 
1619 |     ## FIXME: I'm a little uncomfortable with the use of .checked
1620 |     @property
1621 |     def value(self):
1622 |         """
1623 |         Get/set the value of this element, using the ``value`` attribute.
1624 | 
1625 |         Also, if this is a checkbox and it has no value, this defaults
1626 |         to ``'on'``.  If it is a checkbox or radio that is not
1627 |         checked, this returns None.
1628 |         """
1629 |         if self.checkable:
1630 |             if self.checked:
1631 |                 return self.get('value') or 'on'
1632 |             else:
1633 |                 return None
1634 |         return self.get('value')
1635 | 
1636 |     @value.setter
1637 |     def value(self, value):
1638 |         if self.checkable:
1639 |             if not value:
1640 |                 self.checked = False
1641 |             else:
1642 |                 self.checked = True
1643 |                 if isinstance(value, str):
1644 |                     self.set('value', value)
1645 |         else:
1646 |             self.set('value', value)
1647 | 
1648 |     @value.deleter
1649 |     def value(self):
1650 |         if self.checkable:
1651 |             self.checked = False
1652 |         else:
1653 |             if 'value' in self.attrib:
1654 |                 del self.attrib['value']
1655 | 
1656 |     @property
1657 |     def type(self):
1658 |         """
1659 |         Return the type of this element (using the type attribute).
1660 |         """
1661 |         return self.get('type', 'text').lower()
1662 | 
1663 |     @type.setter
1664 |     def type(self, value):
1665 |         self.set('type', value)
1666 | 
1667 |     @property
1668 |     def checkable(self):
1669 |         """
1670 |         Boolean: can this element be checked?
1671 |         """
1672 |         return self.type in ('checkbox', 'radio')
1673 | 
1674 |     @property
1675 |     def checked(self):
1676 |         """
1677 |         Boolean attribute to get/set the presence of the ``checked``
1678 |         attribute.
1679 | 
1680 |         You can only use this on checkable input types.
1681 |         """
1682 |         if not self.checkable:
1683 |             raise AttributeError('Not a checkable input type')
1684 |         return 'checked' in self.attrib
1685 | 
1686 |     @checked.setter
1687 |     def checked(self, value):
1688 |         if not self.checkable:
1689 |             raise AttributeError('Not a checkable input type')
1690 |         if value:
1691 |             self.set('checked', '')
1692 |         else:
1693 |             attrib = self.attrib
1694 |             if 'checked' in attrib:
1695 |                 del attrib['checked']
1696 | 
1697 | 
1698 | HtmlElementClassLookup._default_element_classes['input'] = InputElement
1699 | 
1700 | 
1701 | class LabelElement(HtmlElement):
1702 |     """
1703 |     Represents a ``<label>`` element.
1704 | 
1705 |     Label elements are linked to other elements with their ``for``
1706 |     attribute.  You can access this element with ``label.for_element``.
1707 |     """
1708 |     @property
1709 |     def for_element(self):
1710 |         """
1711 |         Get/set the element this label points to.  Return None if it
1712 |         can't be found.
1713 |         """
1714 |         id = self.get('for')
1715 |         if not id:
1716 |             return None
1717 |         return self.body.get_element_by_id(id)
1718 | 
1719 |     @for_element.setter
1720 |     def for_element(self, other):
1721 |         id = other.get('id')
1722 |         if not id:
1723 |             raise TypeError(
1724 |                 "Element %r has no id attribute" % other)
1725 |         self.set('for', id)
1726 | 
1727 |     @for_element.deleter
1728 |     def for_element(self):
1729 |         attrib = self.attrib
1730 |         if 'id' in attrib:
1731 |             del attrib['id']
1732 | 
1733 | 
1734 | HtmlElementClassLookup._default_element_classes['label'] = LabelElement
1735 | 
1736 | 
1737 | ############################################################
1738 | ## Serialization
1739 | ############################################################
1740 | 
1741 | def html_to_xhtml(html):
1742 |     """Convert all tags in an HTML tree to XHTML by moving them to the
1743 |     XHTML namespace.
1744 |     """
1745 |     try:
1746 |         html = html.getroot()
1747 |     except AttributeError:
1748 |         pass
1749 |     prefix = "{%s}" % XHTML_NAMESPACE
1750 |     for el in html.iter(etree.Element):
1751 |         tag = el.tag
1752 |         if tag[0] != '{':
1753 |             el.tag = prefix + tag
1754 | 
1755 | 
1756 | def xhtml_to_html(xhtml):
1757 |     """Convert all tags in an XHTML tree to HTML by removing their
1758 |     XHTML namespace.
1759 |     """
1760 |     try:
1761 |         xhtml = xhtml.getroot()
1762 |     except AttributeError:
1763 |         pass
1764 |     prefix = "{%s}" % XHTML_NAMESPACE
1765 |     prefix_len = len(prefix)
1766 |     for el in xhtml.iter(prefix + "*"):
1767 |         el.tag = el.tag[prefix_len:]
1768 | 
1769 | 
1770 | # This isn't a general match, but it's a match for what libxml2
1771 | # specifically serialises:
1772 | __str_replace_meta_content_type = re.compile(
1773 |     r'<meta http-equiv="Content-Type"[^>]*>').sub
1774 | __bytes_replace_meta_content_type = re.compile(
1775 |     br'<meta http-equiv="Content-Type"[^>]*>').sub
1776 | 
1777 | 
1778 | def tostring(doc, pretty_print=False, include_meta_content_type=False,
1779 |              encoding=None, method="html", with_tail=True, doctype=None):
1780 |     """Return an HTML string representation of the document.
1781 | 
1782 |     Note: if include_meta_content_type is true this will create a
1783 |     ``<meta http-equiv="Content-Type" ...>`` tag in the head;
1784 |     regardless of the value of include_meta_content_type any existing
1785 |     ``<meta http-equiv="Content-Type" ...>`` tag will be removed
1786 | 
1787 |     The ``encoding`` argument controls the output encoding (defaults to
1788 |     ASCII, with &#...; character references for any characters outside
1789 |     of ASCII).  Note that you can pass the name ``'unicode'`` as
1790 |     ``encoding`` argument to serialise to a Unicode string.
1791 | 
1792 |     The ``method`` argument defines the output method.  It defaults to
1793 |     'html', but can also be 'xml' for xhtml output, or 'text' to
1794 |     serialise to plain text without markup.
1795 | 
1796 |     To leave out the tail text of the top-level element that is being
1797 |     serialised, pass ``with_tail=False``.
1798 | 
1799 |     The ``doctype`` option allows passing in a plain string that will
1800 |     be serialised before the XML tree.  Note that passing in non
1801 |     well-formed content here will make the XML output non well-formed.
1802 |     Also, an existing doctype in the document tree will not be removed
1803 |     when serialising an ElementTree instance.
1804 | 
1805 |     Example::
1806 | 
1807 |         >>> from lxml import html
1808 |         >>> root = html.fragment_fromstring('<p>Hello<br>world!</p>')
1809 | 
1810 |         >>> html.tostring(root)
1811 |         b'<p>Hello<br>world!</p>'
1812 |         >>> html.tostring(root, method='html')
1813 |         b'<p>Hello<br>world!</p>'
1814 | 
1815 |         >>> html.tostring(root, method='xml')
1816 |         b'<p>Hello<br/>world!</p>'
1817 | 
1818 |         >>> html.tostring(root, method='text')
1819 |         b'Helloworld!'
1820 | 
1821 |         >>> html.tostring(root, method='text', encoding='unicode')
1822 |         u'Helloworld!'
1823 | 
1824 |         >>> root = html.fragment_fromstring('<div><p>Hello<br>world!</p>TAIL</div>')
1825 |         >>> html.tostring(root[0], method='text', encoding='unicode')
1826 |         u'Helloworld!TAIL'
1827 | 
1828 |         >>> html.tostring(root[0], method='text', encoding='unicode', with_tail=False)
1829 |         u'Helloworld!'
1830 | 
1831 |         >>> doc = html.document_fromstring('<p>Hello<br>world!</p>')
1832 |         >>> html.tostring(doc, method='html', encoding='unicode')
1833 |         u'<html><body><p>Hello<br>world!</p></body></html>'
1834 | 
1835 |         >>> print(html.tostring(doc, method='html', encoding='unicode',
1836 |         ...          doctype='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'
1837 |         ...                  ' "http://www.w3.org/TR/html4/strict.dtd">'))
1838 |         <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
1839 |         <html><body><p>Hello<br>world!</p></body></html>
1840 |     """
1841 |     html = etree.tostring(doc, method=method, pretty_print=pretty_print,
1842 |                           encoding=encoding, with_tail=with_tail,
1843 |                           doctype=doctype)
1844 |     if method == 'html' and not include_meta_content_type:
1845 |         if isinstance(html, str):
1846 |             html = __str_replace_meta_content_type('', html)
1847 |         else:
1848 |             html = __bytes_replace_meta_content_type(b'', html)
1849 |     return html
1850 | 
1851 | 
1852 | tostring.__doc__ = __fix_docstring(tostring.__doc__)
1853 | 
1854 | 
1855 | def open_in_browser(doc, encoding=None):
1856 |     """
1857 |     Open the HTML document in a web browser, saving it to a temporary
1858 |     file to open it.  Note that this does not delete the file after
1859 |     use.  This is mainly meant for debugging.
1860 |     """
1861 |     import os
1862 |     import webbrowser
1863 |     import tempfile
1864 |     if not isinstance(doc, etree._ElementTree):
1865 |         doc = etree.ElementTree(doc)
1866 |     handle, fn = tempfile.mkstemp(suffix='.html')
1867 |     f = os.fdopen(handle, 'wb')
1868 |     try:
1869 |         doc.write(f, method="html", encoding=encoding or doc.docinfo.encoding or "UTF-8")
1870 |     finally:
1871 |         # we leak the file itself here, but we should at least close it
1872 |         f.close()
1873 |     url = 'file://' + fn.replace(os.path.sep, '/')
1874 |     print(url)
1875 |     webbrowser.open(url)
1876 | 
1877 | 
1878 | ################################################################################
1879 | # configure Element class lookup
1880 | ################################################################################
1881 | 
1882 | class HTMLParser(etree.HTMLParser):
1883 |     """An HTML parser that is configured to return lxml.html Element
1884 |     objects.
1885 |     """
1886 |     def __init__(self, **kwargs):
1887 |         super().__init__(**kwargs)
1888 |         self.set_element_class_lookup(HtmlElementClassLookup())
1889 | 
1890 | 
1891 | class XHTMLParser(etree.XMLParser):
1892 |     """An XML parser that is configured to return lxml.html Element
1893 |     objects.
1894 | 
1895 |     Note that this parser is not really XHTML aware unless you let it
1896 |     load a DTD that declares the HTML entities.  To do this, make sure
1897 |     you have the XHTML DTDs installed in your catalogs, and create the
1898 |     parser like this::
1899 | 
1900 |         >>> parser = XHTMLParser(load_dtd=True)
1901 | 
1902 |     If you additionally want to validate the document, use this::
1903 | 
1904 |         >>> parser = XHTMLParser(dtd_validation=True)
1905 | 
1906 |     For catalog support, see http://www.xmlsoft.org/catalog.html.
1907 |     """
1908 |     def __init__(self, **kwargs):
1909 |         super().__init__(**kwargs)
1910 |         self.set_element_class_lookup(HtmlElementClassLookup())
1911 | 
1912 | 
1913 | def Element(*args, **kw):
1914 |     """Create a new HTML Element.
1915 | 
1916 |     This can also be used for XHTML documents.
1917 |     """
1918 |     v = html_parser.makeelement(*args, **kw)
1919 |     return v
1920 | 
1921 | 
1922 | html_parser = HTMLParser()
1923 | xhtml_parser = XHTMLParser()
1924 | 
```
Page 155/168FirstPrevNextLast