[![PyPI version](https://img.shields.io/pypi/v/types-lxml.svg)](https://pypi.org/project/types-lxml/)
![Supported Python](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Fabelcheung%2Ftypes-lxml%2Fmain%2Fpyproject.toml
)
![Wheel](https://img.shields.io/pypi/wheel/types-lxml.svg)
## Important note
![image showing deprecation warning](https://github.com/user-attachments/assets/6ab30a54-60e7-4e34-932a-2ac2e253c669)
- Since `2024.11.08`:
- `pyright` users will see warning if a single string is supplied where collection of string is expected (`tuple`, `set`, `list` etc). In terms of typing, a single `str` itself is valid as a `Sequence`, so type checkers normally would not raise alarm when using `str` in such function parameters, but can induce unexpected runtime behavior. See [#64](https://github.com/abelcheung/types-lxml/issues/64) for more info. `mypy` does not support this feature (which (ab)uses `@deprecated` warning).
- It is possible to verify release files indeed come from GitHub and not maliciously altered. See [Release file attestation](#release-file-attestation) for detail.
- Since `2024.08.07`:
- Each release will contain multiple builds; besides normal version, there is an alternative build suitable for multiple XML element subclass. Please check out [relevant Installation section](#choosing-the-build) for detail (hint: many people don't need to bother with this). Also note that this release requires `mypy 1.11` if one chooses to use `mypy` for type checking. `pyright` version requirement (`1.1.351`) is not changed.
## Introduction
This repository contains [external type annotations](https://peps.python.org/pep-0561/) for [`lxml`](http://lxml.de/). It can be used by type-checking tools (currently supporting [`pyright`](https://github.com/Microsoft/pyright) and [`mypy`](https://pypi.org/project/mypy/)) to check code that uses `lxml`, or used within IDEs like [VSCode](https://code.visualstudio.com/) to facilitate development.
## Goal ① : Completion
Now the coverage of `lxml` submodules is complete (unless intentionally rejected, see further below), thus no more [considered as `partial`](https://peps.python.org/pep-0561/#partial-stub-packages):
- [x] `lxml.etree`
- [x] `lxml.html`
- [x] `lxml.html.builder`
- [x] `lxml.html.clean` (already removed in lxml 5.2.0, this project will follow suite in future)
- [x] `lxml.html.diff`
- [x] `lxml.html.html5parser`
- [x] `lxml.html.soupparser`
- [x] `lxml.isoschematron`
- [x] `lxml.objectify`
- [x] `lxml.builder`
- [x] `lxml.cssselect`
- [x] `lxml.sax`
- [x] `lxml.ElementInclude`
Following submodules will not be implemented due to irrelevance to type checking or other reasons:
- `lxml.etree.Schematron` (obsolete and superseded by `lxml.isoschematron`)
- `lxml.usedoctest`
- `lxml.html.usedoctest`
- `lxml.html.formfill` (shouldn't have existed, this would belong to HTTP libraries like `requests` or `httpx`)
Check out [project page](https://github.com/abelcheung/types-lxml/projects) for future plans and progress.
## Goal ② : Support multiple type checkers
Currently the annotations are validated for both `pyright` and `mypy`, with `pyright` recommended because of its greater flexibility and early adoption of newer type checking features.
In the future, there is plan to bring even more type checker support.
## Goal ③: Review and test suite
- [x] All prior `lxml-stubs` contributions are reviewed thoroughly, bringing coherency of annotation across the whole package
- [x] Perform runtime check, and compare against static type checker result; this guarantees annotations are indeed working in real world, not just within some cooked up test suite
- [x] Existing static test suite already vastly expanded, and is under progress of migrating to runtime test
- [x] Modernize package building infrastructure
## Goal ④ : Support for IDEs
Despite having no official PEP, some IDEs support showing docstring from external annotations. This package tries to bring type annotation specific docstrings for some `lxml` classes and functions, explaining how they can be used. Following screenshots show what would look like in Visual Studio Code, behaving as if docstrings come from real python code:
![Stub docstring in VSCode mouseover tooltip](https://user-images.githubusercontent.com/83110/277119481-debbd929-afbd-4f59-b9e6-52a1f7f23241.png)
Besides docstring, current annotations are geared towards convenience for code writers instead of absolute logical 'correctness'. The [deviation of class inheritance](https://github.com/abelcheung/types-lxml/wiki/Element-inheritance-change) for `HtmlComment` and friends is one prominent example.
## Installation
The normal choice for most people is to fetch package from PyPI, like:
uv pip install -U types-lxml # using uv
pip install -U types-lxml # using pip
In the unlikely case PyPI is down, one can directly download wheel from [latest release in GitHub](https://github.com/abelcheung/types-lxml/releases/latest), and then perform installation as local file.
As convenience, it is possible to pull type checker directly [with extras](https://peps.python.org/pep-0508/#extras):
uv pip install -U types-lxml[pyright]
pip install -U types-lxml[mypy]
### Choosing the build
Since `2024.08.07` release, there will be two versions of `types-lxml`. First one is the default one; if there's no problem using it, there's no need to switch.
The second version, `types-lxml-multi-subclass`, is intended for specific need, namely creation of multiple lxml element subclasses. For example:
```mermaid
graph TD;
etree.ElementBase-->MyBaseElement;
MyBaseElement-->MySubElement1;
MyBaseElement-->MySubElement2;
```
If a parsed or constructed element tree consists of single type of element nodes, it is safe to assume the children or parent of a node are of the same type too. But this assumption does not hold for multiple subclasses. Using diagram above as example, calling `.iter()` method from `MyBaseElement` node may produce element of any subelement or even `MyBaseElement` itself.
Therefore output type should be simply `MyBaseElement` only.
Such scenario is already in effect for `lxml.html`. `<form>` element (`FormElement`) is supposed to contain other form related tags like `<input>`, `<select>` etc. But we can't possibly pinpoint single subelement type, so `<form>` children can only possibly be of type `HtmlElement`. The multiple subelement scenario is already hardcoded for `HtmlElement` and `ObjectifiedElement` within this annotation package, but users may choose to have their own overridden element subclasses (inherit from `ElementBase`) too.
The 2 paradigms can't coexist within a single type annotation package. See [bug #51](https://github.com/abelcheung/types-lxml/issues/51) that illustrated why multiple build is necessary.
Remember that anybody can only choose one of the 2 builds. It is impossible to install both, as `pip` just [arbitrarily overwrite conflicting files with one another](https://github.com/pypa/pip/issues/4625). If in doubt, removing existing package first, then install the one you needed.
### Release file attestation
Since `2024.11.08` users can download `types-lxml` release files and verify that they indeed do originate from GitHub. For those haven't heard of it, this is sort of like `gnupg` or [`minisign`](https://jedisct1.github.io/minisign/) signatures, but with GitHub backed infrastructure.
After downloading release wheel file (say `pip download types-lxml`, or browser access to PyPI directly), one can use [GitHub cli](https://cli.github.com/) to verify it comes from this GitHub repository without being altered:
```
gh at verify types_lxml-2024.11.8-py3-none-any.whl --repo abelcheung/types-lxml
```
Should generate following result:
```
Loaded digest sha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 for file://types_lxml-2024.11.8-py3-none-any.whl
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
sha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 was attested by:
REPO PREDICATE_TYPE WORKFLOW
abelcheung/types-lxml https://slsa.dev/provenance/v1 .github/workflows/release.yml@refs/tags/2024.11.08
```
## History
Type annotations for `lxml` were initially included in [typeshed](https://www.github.com/python/typeshed), but as it was still incomplete at that time, the stubs are [ripped out as a separate project](https://github.com/python/typeshed/issues/525). The code was since then under governance of lxml, until 2022 when this fork intended to revamp `lxml-stubs` completely and emerge into separate project.
`types-lxml` is a fork of `lxml-stubs` that strives for the goals described above, so that most people would find it more useful.
Raw data
{
"_id": null,
"home_page": null,
"name": "types-lxml-multi-subclass",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "lxml, typing, stubs, annotation",
"author": null,
"author_email": "Abel Cheung <abelcheung@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/25/2a/f25922a75a7e800a93e00f2303bde0126e50c97e04084155f50025e6eb9e/types_lxml_multi_subclass-2024.12.13.tar.gz",
"platform": null,
"description": "[![PyPI version](https://img.shields.io/pypi/v/types-lxml.svg)](https://pypi.org/project/types-lxml/)\n![Supported Python](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Fabelcheung%2Ftypes-lxml%2Fmain%2Fpyproject.toml\n)\n![Wheel](https://img.shields.io/pypi/wheel/types-lxml.svg)\n\n## Important note\n\n![image showing deprecation warning](https://github.com/user-attachments/assets/6ab30a54-60e7-4e34-932a-2ac2e253c669)\n\n- Since `2024.11.08`:\n - `pyright` users will see warning if a single string is supplied where collection of string is expected (`tuple`, `set`, `list` etc). In terms of typing, a single `str` itself is valid as a `Sequence`, so type checkers normally would not raise alarm when using `str` in such function parameters, but can induce unexpected runtime behavior. See [#64](https://github.com/abelcheung/types-lxml/issues/64) for more info. `mypy` does not support this feature (which (ab)uses `@deprecated` warning).\n - It is possible to verify release files indeed come from GitHub and not maliciously altered. See [Release file attestation](#release-file-attestation) for detail.\n- Since `2024.08.07`:\n - Each release will contain multiple builds; besides normal version, there is an alternative build suitable for multiple XML element subclass. Please check out [relevant Installation section](#choosing-the-build) for detail (hint: many people don't need to bother with this). Also note that this release requires `mypy 1.11` if one chooses to use `mypy` for type checking. `pyright` version requirement (`1.1.351`) is not changed.\n\n## Introduction\n\nThis repository contains [external type annotations](https://peps.python.org/pep-0561/) for [`lxml`](http://lxml.de/). It can be used by type-checking tools (currently supporting [`pyright`](https://github.com/Microsoft/pyright) and [`mypy`](https://pypi.org/project/mypy/)) to check code that uses `lxml`, or used within IDEs like [VSCode](https://code.visualstudio.com/) to facilitate development.\n\n## Goal \u2460 : Completion\n\nNow the coverage of `lxml` submodules is complete (unless intentionally rejected, see further below), thus no more [considered as `partial`](https://peps.python.org/pep-0561/#partial-stub-packages):\n - [x] `lxml.etree`\n - [x] `lxml.html`\n - [x] `lxml.html.builder`\n - [x] `lxml.html.clean` (already removed in lxml 5.2.0, this project will follow suite in future)\n - [x] `lxml.html.diff`\n - [x] `lxml.html.html5parser`\n - [x] `lxml.html.soupparser`\n - [x] `lxml.isoschematron`\n - [x] `lxml.objectify`\n - [x] `lxml.builder`\n - [x] `lxml.cssselect`\n - [x] `lxml.sax`\n - [x] `lxml.ElementInclude`\n\nFollowing submodules will not be implemented due to irrelevance to type checking or other reasons:\n\n - `lxml.etree.Schematron` (obsolete and superseded by `lxml.isoschematron`)\n - `lxml.usedoctest`\n - `lxml.html.usedoctest`\n - `lxml.html.formfill` (shouldn't have existed, this would belong to HTTP libraries like `requests` or `httpx`)\n\nCheck out [project page](https://github.com/abelcheung/types-lxml/projects) for future plans and progress.\n\n## Goal \u2461 : Support multiple type checkers\n\nCurrently the annotations are validated for both `pyright` and `mypy`, with `pyright` recommended because of its greater flexibility and early adoption of newer type checking features.\n\nIn the future, there is plan to bring even more type checker support.\n\n## Goal \u2462: Review and test suite\n\n- [x] All prior `lxml-stubs` contributions are reviewed thoroughly, bringing coherency of annotation across the whole package\n- [x] Perform runtime check, and compare against static type checker result; this guarantees annotations are indeed working in real world, not just within some cooked up test suite\n- [x] Existing static test suite already vastly expanded, and is under progress of migrating to runtime test\n- [x] Modernize package building infrastructure\n\n## Goal \u2463 : Support for IDEs\n\nDespite having no official PEP, some IDEs support showing docstring from external annotations. This package tries to bring type annotation specific docstrings for some `lxml` classes and functions, explaining how they can be used. Following screenshots show what would look like in Visual Studio Code, behaving as if docstrings come from real python code:\n\n![Stub docstring in VSCode mouseover tooltip](https://user-images.githubusercontent.com/83110/277119481-debbd929-afbd-4f59-b9e6-52a1f7f23241.png)\n\nBesides docstring, current annotations are geared towards convenience for code writers instead of absolute logical 'correctness'. The [deviation of class inheritance](https://github.com/abelcheung/types-lxml/wiki/Element-inheritance-change) for `HtmlComment` and friends is one prominent example.\n\n\n## Installation\n\nThe normal choice for most people is to fetch package from PyPI, like:\n\n uv pip install -U types-lxml # using uv\n pip install -U types-lxml # using pip\n\nIn the unlikely case PyPI is down, one can directly download wheel from [latest release in GitHub](https://github.com/abelcheung/types-lxml/releases/latest), and then perform installation as local file.\n\nAs convenience, it is possible to pull type checker directly [with extras](https://peps.python.org/pep-0508/#extras):\n\n uv pip install -U types-lxml[pyright]\n pip install -U types-lxml[mypy]\n\n### Choosing the build\n\nSince `2024.08.07` release, there will be two versions of `types-lxml`. First one is the default one; if there's no problem using it, there's no need to switch.\n\nThe second version, `types-lxml-multi-subclass`, is intended for specific need, namely creation of multiple lxml element subclasses. For example:\n\n```mermaid\n graph TD;\n etree.ElementBase-->MyBaseElement;\n MyBaseElement-->MySubElement1;\n MyBaseElement-->MySubElement2;\n```\n\nIf a parsed or constructed element tree consists of single type of element nodes, it is safe to assume the children or parent of a node are of the same type too. But this assumption does not hold for multiple subclasses. Using diagram above as example, calling `.iter()` method from `MyBaseElement` node may produce element of any subelement or even `MyBaseElement` itself.\nTherefore output type should be simply `MyBaseElement` only.\n\nSuch scenario is already in effect for `lxml.html`. `<form>` element (`FormElement`) is supposed to contain other form related tags like `<input>`, `<select>` etc. But we can't possibly pinpoint single subelement type, so `<form>` children can only possibly be of type `HtmlElement`. The multiple subelement scenario is already hardcoded for `HtmlElement` and `ObjectifiedElement` within this annotation package, but users may choose to have their own overridden element subclasses (inherit from `ElementBase`) too.\n\nThe 2 paradigms can't coexist within a single type annotation package. See [bug #51](https://github.com/abelcheung/types-lxml/issues/51) that illustrated why multiple build is necessary.\n\nRemember that anybody can only choose one of the 2 builds. It is impossible to install both, as `pip` just [arbitrarily overwrite conflicting files with one another](https://github.com/pypa/pip/issues/4625). If in doubt, removing existing package first, then install the one you needed.\n\n\n### Release file attestation\n\nSince `2024.11.08` users can download `types-lxml` release files and verify that they indeed do originate from GitHub. For those haven't heard of it, this is sort of like `gnupg` or [`minisign`](https://jedisct1.github.io/minisign/) signatures, but with GitHub backed infrastructure.\n\nAfter downloading release wheel file (say `pip download types-lxml`, or browser access to PyPI directly), one can use [GitHub cli](https://cli.github.com/) to verify it comes from this GitHub repository without being altered:\n\n```\ngh at verify types_lxml-2024.11.8-py3-none-any.whl --repo abelcheung/types-lxml\n```\n\nShould generate following result:\n\n```\nLoaded digest sha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 for file://types_lxml-2024.11.8-py3-none-any.whl\nLoaded 1 attestation from GitHub API\n\u2713 Verification succeeded!\n\nsha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 was attested by:\nREPO PREDICATE_TYPE WORKFLOW\nabelcheung/types-lxml https://slsa.dev/provenance/v1 .github/workflows/release.yml@refs/tags/2024.11.08\n```\n\n\n## History\n\nType annotations for `lxml` were initially included in [typeshed](https://www.github.com/python/typeshed), but as it was still incomplete at that time, the stubs are [ripped out as a separate project](https://github.com/python/typeshed/issues/525). The code was since then under governance of lxml, until 2022 when this fork intended to revamp `lxml-stubs` completely and emerge into separate project.\n\n`types-lxml` is a fork of `lxml-stubs` that strives for the goals described above, so that most people would find it more useful.\n",
"bugtrack_url": null,
"license": null,
"summary": "Complete lxml external type annotation",
"version": "2024.12.13",
"project_urls": {
"homepage": "https://github.com/abelcheung/types-lxml"
},
"split_keywords": [
"lxml",
" typing",
" stubs",
" annotation"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "de19f96dc5a11007fd26eb2ef41cd7dcd6681b6e97bb204bbb91df0d881e9a38",
"md5": "da4ccc50336461484c9909381050eda8",
"sha256": "9d28279929ab1f11cc190b7fb1a99e7ccaf946e52da84ab58766c34f5192dbd5"
},
"downloads": -1,
"filename": "types_lxml_multi_subclass-2024.12.13-py3-none-any.whl",
"has_sig": false,
"md5_digest": "da4ccc50336461484c9909381050eda8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 86257,
"upload_time": "2024-12-13T12:34:26",
"upload_time_iso_8601": "2024-12-13T12:34:26.631809Z",
"url": "https://files.pythonhosted.org/packages/de/19/f96dc5a11007fd26eb2ef41cd7dcd6681b6e97bb204bbb91df0d881e9a38/types_lxml_multi_subclass-2024.12.13-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "252af25922a75a7e800a93e00f2303bde0126e50c97e04084155f50025e6eb9e",
"md5": "3722f2d2037a34733c0e16d46a9b0a37",
"sha256": "bd844512e36a9ef9094a892e84547a241ecd49e3a5ed91d48353482aba9fa019"
},
"downloads": -1,
"filename": "types_lxml_multi_subclass-2024.12.13.tar.gz",
"has_sig": false,
"md5_digest": "3722f2d2037a34733c0e16d46a9b0a37",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 130373,
"upload_time": "2024-12-13T12:34:29",
"upload_time_iso_8601": "2024-12-13T12:34:29.471618Z",
"url": "https://files.pythonhosted.org/packages/25/2a/f25922a75a7e800a93e00f2303bde0126e50c97e04084155f50025e6eb9e/types_lxml_multi_subclass-2024.12.13.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-13 12:34:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "abelcheung",
"github_project": "types-lxml",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "types-lxml-multi-subclass"
}