Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions stdlib/xml/etree/ElementInclude.pyi
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from _typeshed import FileDescriptorOrPath
from typing import Final, Literal, Protocol, overload, type_check_only
from typing import Any, Final, Literal, Protocol, overload, type_check_only
from xml.etree.ElementTree import Element

@type_check_only
class _Loader(Protocol):
@overload
def __call__(self, href: FileDescriptorOrPath, parse: Literal["xml"], encoding: str | None = None) -> Element: ...
def __call__(self, href: FileDescriptorOrPath, parse: Literal["xml"], encoding: str | None = None) -> Element[Any]: ...
@overload
def __call__(self, href: FileDescriptorOrPath, parse: Literal["text"], encoding: str | None = None) -> str: ...

Expand All @@ -19,9 +19,11 @@ DEFAULT_MAX_INCLUSION_DEPTH: Final = 6
class FatalIncludeError(SyntaxError): ...

@overload
def default_loader(href: FileDescriptorOrPath, parse: Literal["xml"], encoding: str | None = None) -> Element: ...
def default_loader(href: FileDescriptorOrPath, parse: Literal["xml"], encoding: str | None = None) -> Element[str]: ...
@overload
def default_loader(href: FileDescriptorOrPath, parse: Literal["text"], encoding: str | None = None) -> str: ...
def include(elem: Element, loader: _Loader | None = None, base_url: str | None = None, max_depth: int | None = 6) -> None: ...
def include(
elem: Element[Any], loader: _Loader | None = None, base_url: str | None = None, max_depth: int | None = 6
) -> None: ...

class LimitedRecursiveIncludeError(FatalIncludeError): ...
22 changes: 11 additions & 11 deletions stdlib/xml/etree/ElementPath.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ from collections.abc import Callable, Generator, Iterable
from re import Pattern
from typing import Any, Final, Literal, TypeVar, overload
from typing_extensions import TypeAlias
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import Element, _Tag

xpath_tokenizer_re: Final[Pattern[str]]

_Token: TypeAlias = tuple[str, str]
_Next: TypeAlias = Callable[[], _Token]
_Callback: TypeAlias = Callable[[_SelectorContext, Iterable[Element]], Generator[Element, None, None]]
_Callback: TypeAlias = Callable[[_SelectorContext, Iterable[Element[Any]]], Generator[Element[Any]]]
_T = TypeVar("_T")

def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = None) -> Generator[_Token, None, None]: ...
def get_parent_map(context: _SelectorContext) -> dict[Element, Element]: ...
def xpath_tokenizer(pattern: str, namespaces: dict[str, str] | None = None) -> Generator[_Token]: ...
def get_parent_map(context: _SelectorContext) -> dict[Element[Any], Element[Any]]: ...
def prepare_child(next: _Next, token: _Token) -> _Callback: ...
def prepare_star(next: _Next, token: _Token) -> _Callback: ...
def prepare_self(next: _Next, token: _Token) -> _Callback: ...
Expand All @@ -23,18 +23,18 @@ def prepare_predicate(next: _Next, token: _Token) -> _Callback | None: ...
ops: Final[dict[str, Callable[[_Next, _Token], _Callback | None]]]

class _SelectorContext:
parent_map: dict[Element, Element] | None
root: Element
def __init__(self, root: Element) -> None: ...
parent_map: dict[Element[Any], Element[Any]] | None
root: Element[Any]
def __init__(self, root: Element[Any]) -> None: ...

@overload
def iterfind( # type: ignore[overload-overlap]
elem: Element[Any], path: Literal[""], namespaces: dict[str, str] | None = None
elem: Element[_Tag], path: Literal[""], namespaces: dict[str, str] | None = None
) -> None: ...
@overload
def iterfind(elem: Element[Any], path: str, namespaces: dict[str, str] | None = None) -> Generator[Element, None, None]: ...
def find(elem: Element[Any], path: str, namespaces: dict[str, str] | None = None) -> Element | None: ...
def findall(elem: Element[Any], path: str, namespaces: dict[str, str] | None = None) -> list[Element]: ...
def iterfind(elem: Element[_Tag], path: str, namespaces: dict[str, str] | None = None) -> Generator[Element[_Tag]]: ...
def find(elem: Element[_Tag], path: str, namespaces: dict[str, str] | None = None) -> Element[_Tag] | None: ...
def findall(elem: Element[_Tag], path: str, namespaces: dict[str, str] | None = None) -> list[Element[_Tag]]: ...
@overload
def findtext(elem: Element[Any], path: str, default: None = None, namespaces: dict[str, str] | None = None) -> str | None: ...
@overload
Expand Down
113 changes: 58 additions & 55 deletions stdlib/xml/etree/ElementTree.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ParseError(SyntaxError):
position: tuple[int, int]

# In reality it works based on `.tag` attribute duck typing.
def iselement(element: object) -> TypeGuard[Element]: ...
def iselement(element: object) -> TypeGuard[Element[Any]]: ...
@overload
def canonicalize(
xml_data: str | ReadableBuffer | None = None,
Expand Down Expand Up @@ -81,8 +81,9 @@ def canonicalize(
# functions defined in this module.
_ElementCallable: TypeAlias = Callable[..., Element[_ElementCallable]]

_Tag = TypeVar("_Tag", default=str, bound=str | _ElementCallable)
_OtherTag = TypeVar("_OtherTag", default=str, bound=str | _ElementCallable)
_AnyTag: TypeAlias = str | _ElementCallable
_Tag = TypeVar("_Tag", bound=_AnyTag)
_ElementVar = TypeVar("_ElementVar", bound=Element[Any])

@disjoint_base
class Element(Generic[_Tag]):
Expand All @@ -91,11 +92,11 @@ class Element(Generic[_Tag]):
text: str | None
tail: str | None
def __init__(self, tag: _Tag, attrib: dict[str, str] = {}, **extra: str) -> None: ...
def append(self, subelement: Element[Any], /) -> None: ...
def append(self, subelement: Element[_Tag], /) -> None: ...
def clear(self) -> None: ...
def extend(self, elements: Iterable[Element], /) -> None: ...
def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element | None: ...
def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element]: ...
def extend(self, elements: Iterable[Element[_Tag]], /) -> None: ...
def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element[_Tag] | None: ...
def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element[_Tag]]: ...
@overload
def findtext(self, path: str, default: None = None, namespaces: dict[str, str] | None = None) -> str | None: ...
@overload
Expand All @@ -104,39 +105,39 @@ class Element(Generic[_Tag]):
def get(self, key: str, default: None = None) -> str | None: ...
@overload
def get(self, key: str, default: _T) -> str | _T: ...
def insert(self, index: int, subelement: Element, /) -> None: ...
def insert(self, index: int, subelement: Element[_Tag], /) -> None: ...
def items(self) -> ItemsView[str, str]: ...
def iter(self, tag: str | None = None) -> Generator[Element, None, None]: ...
def iter(self, tag: str | None = None) -> Generator[Element[_Tag]]: ...
@overload
def iterfind(self, path: Literal[""], namespaces: dict[str, str] | None = None) -> None: ... # type: ignore[overload-overlap]
@overload
def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element, None, None]: ...
def itertext(self) -> Generator[str, None, None]: ...
def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element[_Tag]]: ...
def itertext(self) -> Generator[str]: ...
def keys(self) -> dict_keys[str, str]: ...
# makeelement returns the type of self in Python impl, but not in C impl
def makeelement(self, tag: _OtherTag, attrib: dict[str, str], /) -> Element[_OtherTag]: ...
def remove(self, subelement: Element, /) -> None: ...
def makeelement(self, tag: _Tag, attrib: dict[str, str], /) -> Element[_Tag]: ...
def remove(self, subelement: Element[_Tag], /) -> None: ...
def set(self, key: str, value: str, /) -> None: ...
def __copy__(self) -> Element[_Tag]: ... # returns the type of self in Python impl, but not in C impl
def __deepcopy__(self, memo: Any, /) -> Element: ... # Only exists in C impl
def __deepcopy__(self, memo: Any, /) -> Element[_Tag]: ... # Only exists in C impl
def __delitem__(self, key: SupportsIndex | slice, /) -> None: ...
@overload
def __getitem__(self, key: SupportsIndex, /) -> Element: ...
def __getitem__(self, key: SupportsIndex, /) -> Element[_Tag]: ...
@overload
def __getitem__(self, key: slice, /) -> list[Element]: ...
def __getitem__(self, key: slice, /) -> list[Element[_Tag]]: ...
def __len__(self) -> int: ...
# Doesn't actually exist at runtime, but instance of the class are indeed iterable due to __getitem__.
def __iter__(self) -> Iterator[Element]: ...
def __iter__(self) -> Iterator[Element[_Tag]]: ...
@overload
def __setitem__(self, key: SupportsIndex, value: Element, /) -> None: ...
def __setitem__(self, key: SupportsIndex, value: Element[_Tag], /) -> None: ...
@overload
def __setitem__(self, key: slice, value: Iterable[Element], /) -> None: ...
def __setitem__(self, key: slice, value: Iterable[Element[_Tag]], /) -> None: ...

# Doesn't really exist in earlier versions, where __len__ is called implicitly instead
@deprecated("Testing an element's truth value is deprecated.")
def __bool__(self) -> bool: ...

def SubElement(parent: Element, tag: str, attrib: dict[str, str] = ..., **extra: str) -> Element: ...
def SubElement(parent: Element[_Tag], tag: _Tag, attrib: dict[str, str] = ..., **extra: str) -> Element[_Tag]: ...
def Comment(text: str | None = None) -> Element[_ElementCallable]: ...
def ProcessingInstruction(target: str, text: str | None = None) -> Element[_ElementCallable]: ...

Expand All @@ -152,23 +153,21 @@ class QName:
def __eq__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...

_Root = TypeVar("_Root", Element, Element | None, default=Element | None)

class ElementTree(Generic[_Root]):
def __init__(self, element: Element | None = None, file: _FileRead | None = None) -> None: ...
def getroot(self) -> _Root: ...
def parse(self, source: _FileRead, parser: XMLParser | None = None) -> Element: ...
def iter(self, tag: str | None = None) -> Generator[Element, None, None]: ...
def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element | None: ...
class ElementTree(Generic[_Tag]):
def __init__(self, element: Element[_Tag] | None = None, file: _FileRead | None = None) -> None: ...
def getroot(self) -> Element[_Tag]: ...
def parse(self, source: _FileRead, parser: XMLParser[_ElementVar] | None = None) -> _ElementVar: ...
def iter(self, tag: str | None = None) -> Generator[Element[_Tag]]: ...
def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element[_Tag] | None: ...
@overload
def findtext(self, path: str, default: None = None, namespaces: dict[str, str] | None = None) -> str | None: ...
@overload
def findtext(self, path: str, default: _T, namespaces: dict[str, str] | None = None) -> _T | str: ...
def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element]: ...
def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element[_Tag]]: ...
@overload
def iterfind(self, path: Literal[""], namespaces: dict[str, str] | None = None) -> None: ... # type: ignore[overload-overlap]
@overload
def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element, None, None]: ...
def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element[_Tag]]: ...
def write(
self,
file_or_filename: _FileWrite,
Expand All @@ -186,7 +185,7 @@ HTML_EMPTY: Final[set[str]]
def register_namespace(prefix: str, uri: str) -> None: ...
@overload
def tostring(
element: Element,
element: Element[Any],
encoding: None = None,
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
Expand All @@ -196,7 +195,7 @@ def tostring(
) -> bytes: ...
@overload
def tostring(
element: Element,
element: Element[Any],
encoding: Literal["unicode"],
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
Expand All @@ -206,7 +205,7 @@ def tostring(
) -> str: ...
@overload
def tostring(
element: Element,
element: Element[Any],
encoding: str,
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
Expand All @@ -216,7 +215,7 @@ def tostring(
) -> Any: ...
@overload
def tostringlist(
element: Element,
element: Element[Any],
encoding: None = None,
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
Expand All @@ -226,7 +225,7 @@ def tostringlist(
) -> list[bytes]: ...
@overload
def tostringlist(
element: Element,
element: Element[Any],
encoding: Literal["unicode"],
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
Expand All @@ -236,28 +235,30 @@ def tostringlist(
) -> list[str]: ...
@overload
def tostringlist(
element: Element,
element: Element[Any],
encoding: str,
method: Literal["xml", "html", "text", "c14n"] | None = None,
*,
xml_declaration: bool | None = None,
default_namespace: str | None = None,
short_empty_elements: bool = True,
) -> list[Any]: ...
def dump(elem: Element | ElementTree[Any]) -> None: ...
def indent(tree: Element | ElementTree[Any], space: str = " ", level: int = 0) -> None: ...
def parse(source: _FileRead, parser: XMLParser[Any] | None = None) -> ElementTree[Element]: ...
def dump(elem: Element[Any] | ElementTree[Any]) -> None: ...
def indent(tree: Element[Any] | ElementTree[Any], space: str = " ", level: int = 0) -> None: ...
def parse(source: _FileRead, parser: XMLParser[Element[_Tag]] | None = None) -> ElementTree[_Tag]: ...

# This class is defined inside the body of iterparse
@type_check_only
class _IterParseIterator(Iterator[tuple[str, Element]], Protocol):
def __next__(self) -> tuple[str, Element]: ...
class _IterParseIterator(Iterator[tuple[str, Element[_Tag]]], Protocol):
def __next__(self) -> tuple[str, Element[_Tag]]: ...
if sys.version_info >= (3, 13):
def close(self) -> None: ...
if sys.version_info >= (3, 11):
def __del__(self) -> None: ...

def iterparse(source: _FileRead, events: Sequence[str] | None = None, parser: XMLParser | None = None) -> _IterParseIterator: ...
def iterparse(
source: _FileRead, events: Sequence[str] | None = None, parser: XMLParser[Element[_Tag]] | None = None
) -> _IterParseIterator[_Tag]: ...

_EventQueue: TypeAlias = tuple[str] | tuple[str, tuple[str, str]] | tuple[str, None]

Expand All @@ -268,13 +269,15 @@ class XMLPullParser(Generic[_E]):
def read_events(self) -> Iterator[_EventQueue | tuple[str, _E]]: ...
def flush(self) -> None: ...

def XML(text: str | ReadableBuffer, parser: XMLParser | None = None) -> Element: ...
def XMLID(text: str | ReadableBuffer, parser: XMLParser | None = None) -> tuple[Element, dict[str, Element]]: ...
def XML(text: str | ReadableBuffer, parser: XMLParser[Element[_Tag]] | None = None) -> Element[_Tag]: ...
def XMLID(
text: str | ReadableBuffer, parser: XMLParser[Element[_Tag]] | None = None
) -> tuple[Element[_Tag], dict[str, Element[_Tag]]]: ...

# This is aliased to XML in the source.
fromstring = XML

def fromstringlist(sequence: Sequence[str | ReadableBuffer], parser: XMLParser | None = None) -> Element: ...
def fromstringlist(sequence: Sequence[str | ReadableBuffer], parser: XMLParser[Element[_Tag]] | None = None) -> Element[_Tag]: ...

# This type is both not precise enough and too precise. The TreeBuilder
# requires the elementfactory to accept tag and attrs in its args and produce
Expand All @@ -285,32 +288,32 @@ def fromstringlist(sequence: Sequence[str | ReadableBuffer], parser: XMLParser |
# TreeBuilder is called by client code (they could pass strs, bytes or whatever);
# but we don't want to use a too-broad type, or it would be too hard to write
# elementfactories.
_ElementFactory: TypeAlias = Callable[[Any, dict[Any, Any]], Element]
_ElementFactory: TypeAlias = Callable[[Any, dict[Any, Any]], Element[Any]]

@disjoint_base
class TreeBuilder:
class TreeBuilder(Generic[_Tag]):
# comment_factory can take None because passing None to Comment is not an error
def __init__(
self,
element_factory: _ElementFactory | None = None,
*,
comment_factory: Callable[[str | None], Element[Any]] | None = None,
pi_factory: Callable[[str, str | None], Element[Any]] | None = None,
comment_factory: Callable[[str | None], Element[_ElementCallable]] | None = None,
pi_factory: Callable[[str, str | None], Element[_ElementCallable]] | None = None,
insert_comments: bool = False,
insert_pis: bool = False,
) -> None: ...
insert_comments: bool
insert_pis: bool

def close(self) -> Element: ...
def close(self) -> Element[_Tag]: ...
def data(self, data: str, /) -> None: ...
# tag and attrs are passed to the element_factory, so they could be anything
# depending on what the particular factory supports.
def start(self, tag: Any, attrs: dict[Any, Any], /) -> Element: ...
def end(self, tag: str, /) -> Element: ...
def start(self, tag: Any, attrs: dict[Any, Any], /) -> Element[_Tag]: ...
def end(self, tag: _Tag, /) -> Element[_Tag]: ...
# These two methods have pos-only parameters in the C implementation
def comment(self, text: str | None, /) -> Element[Any]: ...
def pi(self, target: str, text: str | None = None, /) -> Element[Any]: ...
def comment(self, text: str | None, /) -> Element[_ElementCallable]: ...
def pi(self, target: str, text: str | None = None, /) -> Element[_ElementCallable]: ...

class C14NWriterTarget:
def __init__(
Expand Down Expand Up @@ -347,7 +350,7 @@ class _Target(Protocol):
# close: Callable[[], Any] | None
...

_E = TypeVar("_E", default=Element)
_E = TypeVar("_E", default=Element[Any])

# This is generic because the return type of close() depends on the target.
# The default target is TreeBuilder, which returns Element.
Expand Down
Loading