mirror of
https://github.com/davidhalter/typeshed.git
synced 2025-12-26 05:41:11 +08:00
Improve types for xml.etree.ElementTree (#930)
* Improve types for xml.etree.ElementTree Update signatures to reflect the following peculiarities of the ElementTree library: - The elementtree library accepts unicode or bytes for most xml values in python2, and coerces everywhere -- but in python3, only str makes sense. - In python 2, the library produces str or unicode instances unpredictably, depending on whether the xml is decodeable as ascii or not. In python 3, it always produces str instances. - The parser functions accept unicode or bytes in 2 and 3 -- again, will coerce individual instances so heterogeneous lists are ok. - In python 3, the tostring functions produce bytes or str, depending on the value of the 'encoding' parameter. * improve docs * Improve ElementFactory type by specifying dict of 2nd arg
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Stubs for xml.etree.ElementTree (Python 3.4)
|
||||
# Stubs for xml.etree.ElementTree
|
||||
|
||||
from typing import Any, AnyStr, Union, IO, Callable, Dict, List, Tuple, Sequence, Iterator, TypeVar, Optional, KeysView, ItemsView, Generator
|
||||
from typing import Any, Union, IO, Callable, Dict, List, Tuple, Sequence, Iterator, TypeVar, Optional, KeysView, ItemsView, Generator, Text
|
||||
import io
|
||||
import sys
|
||||
|
||||
@@ -10,53 +10,80 @@ class ParseError(SyntaxError): ...
|
||||
|
||||
def iselement(element: 'Element') -> bool: ...
|
||||
|
||||
_Ss = TypeVar('_Ss', str, bytes)
|
||||
_T = TypeVar('_T')
|
||||
_str_or_bytes = Union[str, bytes]
|
||||
|
||||
# Type for parser inputs. Parser will accept any unicode/str/bytes and coerce,
|
||||
# and this is true in py2 and py3 (even fromstringlist() in python3 can be
|
||||
# called with a heterogeneous list)
|
||||
_parser_input_type = Union[bytes, Text]
|
||||
|
||||
# Type for individual tag/attr/ns/text values in args to most functions.
|
||||
# In py2, the library accepts str or unicode everywhere and coerces
|
||||
# aggressively.
|
||||
# In py3, bytes is not coerced to str and so use of bytes is probably an error,
|
||||
# so we exclude it. (why? the parser never produces bytes when it parses XML,
|
||||
# so e.g., element.get(b'name') will always return None for parsed XML, even if
|
||||
# there is a 'name' attribute.)
|
||||
_str_argument_type = Union[str, Text]
|
||||
|
||||
# Type for return values from individual tag/attr/text values and serialization
|
||||
if sys.version_info >= (3,):
|
||||
# note: in python3, everything comes out as str, yay:
|
||||
_str_result_type = str
|
||||
# unfortunately, tostring and tostringlist can return either bytes or str
|
||||
# depending on the value of `encoding` parameter. Client code knows best:
|
||||
_tostring_result_type = Any
|
||||
else:
|
||||
# in python2, if the tag/attribute/text wasn't decode-able as ascii, it
|
||||
# comes out as a unicode string; otherwise it comes out as str. (see
|
||||
# _fixtext function in the source). Client code knows best:
|
||||
_str_result_type = Any
|
||||
# On the bright side, tostring and tostringlist always return bytes:
|
||||
_tostring_result_type = bytes
|
||||
|
||||
class Element(Sequence['Element']):
|
||||
tag = ... # type: _str_or_bytes
|
||||
attrib = ... # type: Dict[_str_or_bytes, _str_or_bytes]
|
||||
text = ... # type: Optional[_str_or_bytes]
|
||||
tail = ... # type: Optional[_str_or_bytes]
|
||||
def __init__(self, tag: Union[AnyStr, Callable[..., 'Element']], attrib: Dict[AnyStr, AnyStr]=..., **extra: AnyStr) -> None: ...
|
||||
tag = ... # type: _str_result_type
|
||||
attrib = ... # type: Dict[_str_result_type, _str_result_type]
|
||||
text = ... # type: Optional[_str_result_type]
|
||||
tail = ... # type: Optional[_str_result_type]
|
||||
def __init__(self, tag: Union[_str_argument_type, Callable[..., 'Element']], attrib: Dict[_str_argument_type, _str_argument_type]=..., **extra: _str_argument_type) -> None: ...
|
||||
def append(self, subelement: 'Element') -> None: ...
|
||||
def clear(self) -> None: ...
|
||||
def copy(self) -> 'Element': ...
|
||||
def extend(self, elements: Sequence['Element']) -> None: ...
|
||||
def find(self, path: str, namespaces: Dict[str, str]=...) -> Optional['Element']: ...
|
||||
def findall(self, path: str, namespaces: Dict[str, str]=...) -> List['Element']: ...
|
||||
def findtext(self, path: str, default: _T=..., namespaces: Dict[str, str]=...) -> Union[_T, str]: ...
|
||||
def get(self, key: AnyStr, default: _T=...) -> Union[AnyStr, _T]: ...
|
||||
def find(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> Optional['Element']: ...
|
||||
def findall(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> List['Element']: ...
|
||||
def findtext(self, path: _str_argument_type, default: _T=..., namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> Union[_T, _str_result_type]: ...
|
||||
def get(self, key: _str_argument_type, default: _T=...) -> Union[_str_result_type, _T]: ...
|
||||
def getchildren(self) -> List['Element']: ...
|
||||
def getiterator(self, tag: Union[str, AnyStr]=...) -> List['Element']: ...
|
||||
def getiterator(self, tag: _str_argument_type=...) -> List['Element']: ...
|
||||
if sys.version_info >= (3, 2):
|
||||
def insert(self, index: int, subelement: 'Element') -> None: ...
|
||||
else:
|
||||
def insert(self, index: int, element: 'Element') -> None: ...
|
||||
def items(self) -> ItemsView[AnyStr, AnyStr]: ...
|
||||
def iter(self, tag: Union[str, AnyStr]=...) -> Generator['Element', None, None]: ...
|
||||
def iterfind(self, path: str, namespaces: Dict[str, str]=...) -> List['Element']: ...
|
||||
def itertext(self) -> Generator[str, None, None]: ...
|
||||
def keys(self) -> KeysView[AnyStr]: ...
|
||||
def makeelement(self, tag: _Ss, attrib: Dict[_Ss, _Ss]) -> 'Element': ...
|
||||
def items(self) -> ItemsView[_str_result_type, _str_result_type]: ...
|
||||
def iter(self, tag: _str_argument_type=...) -> Generator['Element', None, None]: ...
|
||||
def iterfind(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> List['Element']: ...
|
||||
def itertext(self) -> Generator[_str_result_type, None, None]: ...
|
||||
def keys(self) -> KeysView[_str_result_type]: ...
|
||||
def makeelement(self, tag: _str_argument_type, attrib: Dict[_str_argument_type, _str_argument_type]) -> 'Element': ...
|
||||
def remove(self, subelement: 'Element') -> None: ...
|
||||
def set(self, key: AnyStr, value: AnyStr) -> None: ...
|
||||
def set(self, key: _str_argument_type, value: _str_argument_type) -> None: ...
|
||||
def __bool__(self) -> bool: ...
|
||||
def __delitem__(self, index: int) -> None: ...
|
||||
def __getitem__(self, index) -> 'Element': ...
|
||||
def __len__(self) -> int: ...
|
||||
def __setitem__(self, index: int, element: 'Element') -> None: ...
|
||||
|
||||
def SubElement(parent: Element, tag: AnyStr, attrib: Dict[AnyStr, AnyStr]=..., **extra: AnyStr) -> Element: ...
|
||||
def Comment(text: _str_or_bytes=...) -> Element: ...
|
||||
def ProcessingInstruction(target: str, text: str=...) -> Element: ...
|
||||
def SubElement(parent: Element, tag: _str_argument_type, attrib: Dict[_str_argument_type, _str_argument_type]=..., **extra: _str_argument_type) -> Element: ...
|
||||
def Comment(text: _str_argument_type=...) -> Element: ...
|
||||
def ProcessingInstruction(target: _str_argument_type, text: _str_argument_type=...) -> Element: ...
|
||||
|
||||
PI = ... # type: Callable[..., Element]
|
||||
|
||||
class QName:
|
||||
text = ... # type: str
|
||||
def __init__(self, text_or_uri: str, tag: str=...) -> None: ...
|
||||
def __init__(self, text_or_uri: _str_argument_type, tag: _str_argument_type=...) -> None: ...
|
||||
|
||||
|
||||
_file_or_filename = Union[str, bytes, int, IO[Any]]
|
||||
@@ -65,25 +92,25 @@ class ElementTree:
|
||||
def __init__(self, element: Element=..., file: _file_or_filename=...) -> None: ...
|
||||
def getroot(self) -> Element: ...
|
||||
def parse(self, source: _file_or_filename, parser: 'XMLParser'=...) -> Element: ...
|
||||
def iter(self, tag: Union[str, AnyStr]=...) -> Generator[Element, None, None]: ...
|
||||
def getiterator(self, tag: Union[str, AnyStr]=...) -> List[Element]: ...
|
||||
def find(self, path: str, namespaces: Dict[str, str]=...) -> Optional[Element]: ...
|
||||
def findtext(self, path: str, default: _T=..., namespaces: Dict[str, str]=...) -> Union[_T, str]: ...
|
||||
def findall(self, path: str, namespaces: Dict[str, str]=...) -> List[Element]: ...
|
||||
def iterfind(self, path: str, namespaces: Dict[str, str]=...) -> List[Element]: ...
|
||||
def iter(self, tag: _str_argument_type=...) -> Generator[Element, None, None]: ...
|
||||
def getiterator(self, tag: _str_argument_type=...) -> List[Element]: ...
|
||||
def find(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> Optional[Element]: ...
|
||||
def findtext(self, path: _str_argument_type, default: _T=..., namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> Union[_T, _str_result_type]: ...
|
||||
def findall(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> List[Element]: ...
|
||||
def iterfind(self, path: _str_argument_type, namespaces: Dict[_str_argument_type, _str_argument_type]=...) -> List[Element]: ...
|
||||
if sys.version_info >= (3, 4):
|
||||
def write(self, file_or_filename: _file_or_filename, encoding: str=..., xml_declaration: Optional[bool]=..., default_namespace: str=..., method: str=..., *, short_empty_elements: bool=...) -> None: ...
|
||||
def write(self, file_or_filename: _file_or_filename, encoding: str=..., xml_declaration: Optional[bool]=..., default_namespace: _str_argument_type=..., method: str=..., *, short_empty_elements: bool=...) -> None: ...
|
||||
else:
|
||||
def write(self, file_or_filename: _file_or_filename, encoding: str=..., xml_declaration: Optional[bool]=..., default_namespace: str=..., method: str=...) -> None: ...
|
||||
def write(self, file_or_filename: _file_or_filename, encoding: str=..., xml_declaration: Optional[bool]=..., default_namespace: _str_argument_type=..., method: str=...) -> None: ...
|
||||
def write_c14n(self, file: _file_or_filename) -> None: ...
|
||||
|
||||
def register_namespace(prefix: str, uri: str) -> None: ...
|
||||
def register_namespace(prefix: _str_argument_type, uri: _str_argument_type) -> None: ...
|
||||
if sys.version_info >= (3, 4):
|
||||
def tostring(element: Element, encoding: str=..., method: str=..., *, short_empty_elements: bool=...) -> str: ...
|
||||
def tostringlist(element: Element, encoding: str=..., method: str=..., *, short_empty_elements: bool=...) -> List[str]: ...
|
||||
def tostring(element: Element, encoding: str=..., method: str=..., *, short_empty_elements: bool=...) -> _tostring_result_type: ...
|
||||
def tostringlist(element: Element, encoding: str=..., method: str=..., *, short_empty_elements: bool=...) -> List[_tostring_result_type]: ...
|
||||
else:
|
||||
def tostring(element: Element, encoding: str=..., method: str=...) -> str: ...
|
||||
def tostringlist(element: Element, encoding: str=..., method: str=...) -> List[str]: ...
|
||||
def tostring(element: Element, encoding: str=..., method: str=...) -> _tostring_result_type: ...
|
||||
def tostringlist(element: Element, encoding: str=..., method: str=...) -> List[_tostring_result_type]: ...
|
||||
def dump(elem: Element) -> None: ...
|
||||
def parse(source: _file_or_filename, parser: 'XMLParser'=...) -> ElementTree: ...
|
||||
def iterparse(source: _file_or_filename, events: Sequence[str]=..., parser: 'XMLParser'=...) -> Iterator[Tuple[str, Element]]: ...
|
||||
@@ -95,20 +122,31 @@ if sys.version_info >= (3, 4):
|
||||
def close(self) -> None: ...
|
||||
def read_events(self) -> Iterator[Tuple[str, Element]]: ...
|
||||
|
||||
def XML(text: AnyStr, parser: 'XMLParser'=...) -> Element: ...
|
||||
def XMLID(text: AnyStr, parser: 'XMLParser'=...) -> Tuple[Element, Dict[str, Element]]: ...
|
||||
def XML(text: _parser_input_type, parser: 'XMLParser'=...) -> Element: ...
|
||||
def XMLID(text: _parser_input_type, parser: 'XMLParser'=...) -> Tuple[Element, Dict[_str_result_type, Element]]: ...
|
||||
|
||||
# TODO-improve this type
|
||||
fromstring = ... # type: Callable[..., Element]
|
||||
# This is aliased to XML in the source.
|
||||
fromstring = XML
|
||||
|
||||
def fromstringlist(sequence: Sequence[AnyStr], parser: 'XMLParser'=...) -> Element: ...
|
||||
def fromstringlist(sequence: Sequence[_parser_input_type], parser: 'XMLParser'=...) -> Element: ...
|
||||
|
||||
# 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
|
||||
# some kind of object that has .text and .tail properties.
|
||||
# I've chosen to constrain the ElementFactory to always produce an Element
|
||||
# because that is how almost everyone will use it.
|
||||
# Unfortunately, the type of the factory arguments is dependent on how
|
||||
# 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 = Callable[[Any, Dict[Any, Any]], Element]
|
||||
|
||||
class TreeBuilder:
|
||||
def __init__(self, element_factory: Callable[[AnyStr, Dict[AnyStr, AnyStr]], Element]=...) -> None: ...
|
||||
def __init__(self, element_factory: _ElementFactory=...) -> None: ...
|
||||
def close(self) -> Element: ...
|
||||
def data(self, data: AnyStr) -> None: ...
|
||||
def start(self, tag: AnyStr, attrs: Dict[AnyStr, AnyStr]) -> Element: ...
|
||||
def end(self, tag: AnyStr) -> Element: ...
|
||||
def data(self, data: _parser_input_type) -> None: ...
|
||||
def start(self, tag: _parser_input_type, attrs: Dict[_parser_input_type, _parser_input_type]) -> Element: ...
|
||||
def end(self, tag: _parser_input_type) -> Element: ...
|
||||
|
||||
class XMLParser:
|
||||
parser = ... # type: Any
|
||||
@@ -118,5 +156,5 @@ class XMLParser:
|
||||
version = ... # type: str
|
||||
def __init__(self, html: int=..., target: TreeBuilder=..., encoding: str=...) -> None: ...
|
||||
def doctype(self, name: str, pubid: str, system: str) -> None: ...
|
||||
def close(self) -> Any: ... # TODO-most of the time, this will be Element, but it can be anything target.close() returns
|
||||
def feed(self, data: AnyStr)-> None: ...
|
||||
def close(self) -> Element: ...
|
||||
def feed(self, data: _parser_input_type) -> None: ...
|
||||
|
||||
Reference in New Issue
Block a user