diff --git a/stdlib/@tests/test_cases/check_xml.py b/stdlib/@tests/test_cases/check_xml.py index 31a4fa243eaa..d0df0f6e830c 100644 --- a/stdlib/@tests/test_cases/check_xml.py +++ b/stdlib/@tests/test_cases/check_xml.py @@ -2,6 +2,7 @@ from typing_extensions import assert_type from xml.dom.minidom import Document +from xml.etree.ElementTree import Comment, ElementTree, ProcessingInstruction document = Document() @@ -29,3 +30,18 @@ assert_type(document.toprettyxml(" ", "\r\n", "UTF8"), bytes) assert_type(document.toprettyxml(" ", "\r\n", "UTF8", True), bytes) assert_type(document.toprettyxml(" ", "\r\n", standalone=True), str) + + +# Regression for #14671: ET.Comment/ProcessingInstruction are valid +# element tags at runtime (insert_comments=True), so a plain Element's +# tag must be comparable with them. +def check_comment_tag(doc: ElementTree) -> None: + for el in doc.findall("*"): + _ = el.tag is Comment + _ = el.tag is ProcessingInstruction + + +def check_comment_element() -> None: + c = Comment("a comment") + assert c.tag is Comment + assert c.tag is not ProcessingInstruction diff --git a/stdlib/xml/etree/ElementTree.pyi b/stdlib/xml/etree/ElementTree.pyi index c77af2cb4dd1..51367b040614 100644 --- a/stdlib/xml/etree/ElementTree.pyi +++ b/stdlib/xml/etree/ElementTree.pyi @@ -96,8 +96,8 @@ class Element(Generic[_Tag]): def append(self, subelement: Element[Any], /) -> None: ... def clear(self) -> None: ... def extend(self, elements: Iterable[Element[Any]], /) -> 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 find(self, path: str, namespaces: dict[str, str] | None = None) -> Element[Any] | None: ... + def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element[Any]]: ... @overload def findtext(self, path: str, default: None = None, namespaces: dict[str, str] | None = None) -> str | None: ... @@ -111,12 +111,12 @@ class Element(Generic[_Tag]): def insert(self, index: int, subelement: Element[Any], /) -> None: ... def items(self) -> ItemsView[str, str]: ... - def iter(self, tag: str | None = None) -> Generator[Element]: ... + def iter(self, tag: str | None = None) -> Generator[Element[Any]]: ... @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]: ... + def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element[Any]]: ... def itertext(self) -> Generator[str]: ... def keys(self) -> dict_keys[str, str]: ... @@ -168,21 +168,21 @@ class ElementTree(Generic[_Root]): def __init__(self, element: Element[Any] | None = None, file: _FileRead | None = None) -> None: ... def getroot(self) -> _Root: ... def _setroot(self, element: Element[Any]) -> None: ... - def parse(self, source: _FileRead, parser: XMLParser | None = None) -> Element: ... - def iter(self, tag: str | None = None) -> Generator[Element]: ... - def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element | None: ... + def parse(self, source: _FileRead, parser: XMLParser | None = None) -> Element[Any]: ... + def iter(self, tag: str | None = None) -> Generator[Element[Any]]: ... + def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element[Any] | 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[Any]]: ... @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]: ... + def iterfind(self, path: str, namespaces: dict[str, str] | None = None) -> Generator[Element[Any]]: ... def write( self,