Add type annotations to the Node class in ldml.py
Task-number: QTBUG-129566 Pick-to: 6.8 Change-Id: I70a85654584cdd1117cd670337709620ad84e6d8 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
75155ce5c0
commit
60cb610a40
@ -18,24 +18,28 @@ returned by minidom.parse() and their child-nodes:
|
|||||||
|
|
||||||
See individual classes for further detail.
|
See individual classes for further detail.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
from localetools import Error
|
from localetools import Error
|
||||||
from dateconverter import convert_date
|
from dateconverter import convert_date
|
||||||
|
from typing import Any, Iterator
|
||||||
|
from xml.dom import minidom
|
||||||
|
|
||||||
# The github version of CLDR uses '↑↑↑' to indicate "inherit"
|
# The github version of CLDR uses '↑↑↑' to indicate "inherit"
|
||||||
INHERIT = '↑↑↑'
|
INHERIT = '↑↑↑'
|
||||||
|
|
||||||
def _attrsFromDom(dom):
|
def _attrsFromDom(dom: minidom.Element) -> dict[str, str]:
|
||||||
return { k: (v if isinstance(v, str) else v.nodeValue)
|
return { k: (v if isinstance(v, str) else v.nodeValue)
|
||||||
for k, v in dom.attributes.items() }
|
for k, v in dom.attributes.items() }
|
||||||
|
|
||||||
class Node (object):
|
class Node (object):
|
||||||
"""Wrapper for an arbitrary DOM node.
|
"""Wrapper for an arbitrary DOM node.
|
||||||
|
|
||||||
Provides various ways to select chldren of a node. Selected child
|
Provides various ways to select children of a node. Selected child
|
||||||
nodes are returned wrapped as Node objects. A Node exposes the
|
nodes are returned wrapped as Node objects. A Node exposes the
|
||||||
raw DOM node it wraps via its .dom attribute."""
|
raw DOM node it wraps via its .dom attribute."""
|
||||||
|
|
||||||
def __init__(self, elt, dullAttrs = None, draft = 0):
|
def __init__(self, elt: minidom.Element,
|
||||||
|
dullAttrs: dict[str, tuple[str, ...]]|None = None, draft: int = 0) -> None:
|
||||||
"""Wraps a DOM node for ease of access.
|
"""Wraps a DOM node for ease of access.
|
||||||
|
|
||||||
First argument, elt, is the DOM node to wrap.
|
First argument, elt, is the DOM node to wrap.
|
||||||
@ -51,16 +55,17 @@ class Node (object):
|
|||||||
score of any ancestor of the new node.)"""
|
score of any ancestor of the new node.)"""
|
||||||
self.dom, self.__dull = elt, dullAttrs
|
self.dom, self.__dull = elt, dullAttrs
|
||||||
try:
|
try:
|
||||||
attr = elt.attributes['draft'].nodeValue
|
attr: str = elt.attributes['draft'].nodeValue
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.draft = draft
|
self.draft = draft
|
||||||
else:
|
else:
|
||||||
self.draft = max(draft, self.draftScore(attr))
|
self.draft = max(draft, self.draftScore(attr))
|
||||||
|
|
||||||
def attributes(self):
|
def attributes(self) -> dict[str, str]:
|
||||||
return _attrsFromDom(self.dom)
|
return _attrsFromDom(self.dom)
|
||||||
|
|
||||||
def findAllChildren(self, tag, wanted = None, allDull = False):
|
def findAllChildren(self, tag: str, wanted: dict[str, str]|None = None,
|
||||||
|
allDull: bool = False) -> Iterator[Node]:
|
||||||
"""All children that do have the given tag and attributes.
|
"""All children that do have the given tag and attributes.
|
||||||
|
|
||||||
First argument is the tag: children with any other tag are
|
First argument is the tag: children with any other tag are
|
||||||
@ -76,7 +81,7 @@ class Node (object):
|
|||||||
|
|
||||||
if self.__dull is None:
|
if self.__dull is None:
|
||||||
allDull = True
|
allDull = True
|
||||||
dull = () if allDull else self.__dull[tag]
|
dull: tuple[str, ...] = () if allDull else self.__dull[tag]
|
||||||
|
|
||||||
for child in self.dom.childNodes:
|
for child in self.dom.childNodes:
|
||||||
if child.nodeType != child.ELEMENT_NODE:
|
if child.nodeType != child.ELEMENT_NODE:
|
||||||
@ -102,14 +107,14 @@ class Node (object):
|
|||||||
|
|
||||||
yield Node(child, self.__dull, self.draft)
|
yield Node(child, self.__dull, self.draft)
|
||||||
|
|
||||||
def findUniqueChild(self, tag):
|
def findUniqueChild(self, tag: str) -> Node:
|
||||||
"""Returns the single child with the given nodeName.
|
"""Returns the single child with the given nodeName.
|
||||||
|
|
||||||
Raises Error if there is no such child or there is more than
|
Raises Error if there is no such child or there is more than
|
||||||
one."""
|
one."""
|
||||||
seq = self.findAllChildren(tag)
|
seq: Iterator[Node] = self.findAllChildren(tag)
|
||||||
try:
|
try:
|
||||||
node = next(seq)
|
node: Node = next(seq)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
raise Error('No child found where one was expected', tag)
|
raise Error('No child found where one was expected', tag)
|
||||||
for it in seq:
|
for it in seq:
|
||||||
@ -117,7 +122,7 @@ class Node (object):
|
|||||||
return node
|
return node
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draftScore(cls, level):
|
def draftScore(cls, level: str) -> int:
|
||||||
"""Maps draft level names to numeric scores.
|
"""Maps draft level names to numeric scores.
|
||||||
|
|
||||||
Single parameter, level, is the least sure value of the draft
|
Single parameter, level, is the least sure value of the draft
|
||||||
@ -139,19 +144,19 @@ class Node (object):
|
|||||||
__draftScores = dict(true = 4, unconfirmed = 3, provisional = 2,
|
__draftScores = dict(true = 4, unconfirmed = 3, provisional = 2,
|
||||||
contributed = 1, approved = 0, false = 0)
|
contributed = 1, approved = 0, false = 0)
|
||||||
|
|
||||||
def _parseXPath(selector):
|
def _parseXPath(selector: str) -> tuple[str, dict[str, str]]:
|
||||||
# Split "tag[attr=val][...]" into tag-name and attribute mapping
|
# Split "tag[attr=val][...]" into tag-name and attribute mapping
|
||||||
attrs = selector.split('[')
|
attrs: list[str] = selector.split('[')
|
||||||
name = attrs.pop(0)
|
name: str = attrs.pop(0)
|
||||||
if attrs:
|
if attrs:
|
||||||
attrs = [x.strip() for x in attrs]
|
attrs = [x.strip() for x in attrs]
|
||||||
assert all(x.endswith(']') for x in attrs)
|
assert all(x.endswith(']') for x in attrs)
|
||||||
attrs = [x[:-1].split('=') for x in attrs]
|
attrs: list[list[str]] = [x[:-1].split('=') for x in attrs]
|
||||||
assert all(len(x) in (1, 2) for x in attrs)
|
assert all(len(x) in (1, 2) for x in attrs)
|
||||||
attrs = (('type', x[0]) if len(x) == 1 else x for x in attrs)
|
attrs: Iterator[tuple[str, str]] = (('type', x[0]) if len(x) == 1 else x for x in attrs)
|
||||||
return name, dict(attrs)
|
return name, dict(attrs)
|
||||||
|
|
||||||
def _iterateEach(iters):
|
def _iterateEach(iters: Iterator[Iterator[Any]]) -> Iterator[Any]:
|
||||||
# Flatten a two-layer iterator.
|
# Flatten a two-layer iterator.
|
||||||
for it in iters:
|
for it in iters:
|
||||||
for item in it:
|
for item in it:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user