Add type annotations to QLocaleXmlReader

Task-number: QTBUG-129564
Pick-to: 6.8
Change-Id: I8711152840e6bcb39ff1b1e67ff60b53801f28f0
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Mate Barany 2024-10-15 17:12:25 +02:00
parent 6efec3850d
commit feb39b2d03

View File

@ -19,8 +19,9 @@ You can download jing from https://relaxng.org/jclark/jing.html if your
package manager lacks the jing package. package manager lacks the jing package.
""" """
from typing import Iterator from typing import Callable, Iterable, Iterator
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
from xml.dom import minidom
from localetools import Error, qtVersion from localetools import Error, qtVersion
@ -46,15 +47,17 @@ def startCount(c, text): # strspn
return len(text) return len(text)
class QLocaleXmlReader (object): class QLocaleXmlReader (object):
def __init__(self, filename): def __init__(self, filename: str) -> None:
self.root = self.__parse(filename) self.root: minidom.Element = self.__parse(filename)
from enumdata import language_map, script_map, territory_map from enumdata import language_map, script_map, territory_map
# Lists of (id, enum name, code, en.xml name) tuples: # Tuples of (id, enum name, code, en.xml name) tuples:
languages = tuple(self.__loadMap('language', language_map)) languages = tuple(self.__loadMap('language', language_map))
scripts = tuple(self.__loadMap('script', script_map)) scripts = tuple(self.__loadMap('script', script_map))
territories = tuple(self.__loadMap('territory', territory_map)) territories = tuple(self.__loadMap('territory', territory_map))
self.__likely = tuple(self.__likelySubtagsMap()) # as enum numeric values
# as enum numeric values, tuple[tuple[int, int, int], tuple[int, int, int]]
self.__likely = tuple(self.__likelySubtagsMap())
# Mappings {ID: (enum name, code, en.xml name)} # Mappings {ID: (enum name, code, en.xml name)}
self.languages = {v[0]: v[1:] for v in languages} self.languages = {v[0]: v[1:] for v in languages}
@ -69,13 +72,14 @@ class QLocaleXmlReader (object):
self.__dupes = set(v[1] for v in languages) & set(v[1] for v in territories) self.__dupes = set(v[1] for v in languages) & set(v[1] for v in territories)
self.cldrVersion = self.root.attributes['versionCldr'].nodeValue self.cldrVersion = self.root.attributes['versionCldr'].nodeValue
self.qtVersion = self.root.attributes['versionQt'].nodeValue self.qtVersion: str = self.root.attributes['versionQt'].nodeValue
assert self.qtVersion == qtVersion, ( assert self.qtVersion == qtVersion, (
'Using QLocaleXml file from incompatible Qt version', 'Using QLocaleXml file from incompatible Qt version',
self.qtVersion, qtVersion self.qtVersion, qtVersion
) )
def loadLocaleMap(self, calendars, grumble = lambda text: None): def loadLocaleMap(self, calendars: Iterable[str], grumble = lambda text: None
) -> Iterator[tuple[tuple[int, int, int], "Locale"]]:
"""Yields id-triplet and locale object for each locale read. """Yields id-triplet and locale object for each locale read.
The id-triplet gives the (language, script, territory) numeric The id-triplet gives the (language, script, territory) numeric
@ -83,18 +87,20 @@ class QLocaleXmlReader (object):
locale. Where the relevant enum value is zero (an Any* member locale. Where the relevant enum value is zero (an Any* member
of the enum), likely subtag rules are used to fill in the of the enum), likely subtag rules are used to fill in the
script or territory, if missing, in this triplet.""" script or territory, if missing, in this triplet."""
kid = self.__firstChildText kid: Callable[[minidom.Element, str], str] = self.__firstChildText
likely = dict(self.__likely) likely: dict[tuple[int, int, int], tuple[int, int, int]] = dict(self.__likely)
for elt in self.__eachEltInGroup(self.root, 'localeList', 'locale'): for elt in self.__eachEltInGroup(self.root, 'localeList', 'locale'):
locale = Locale.fromXmlData(lambda k: kid(elt, k), calendars) locale: Locale = Locale.fromXmlData(lambda k: kid(elt, k), calendars)
# region is tuple[str|None, ...]
# zone and meta are dict[str, dict[str, str | tuple[str | None, ...]]]
region, zone, meta = self.__zoneData(elt) region, zone, meta = self.__zoneData(elt)
locale.update(regionFormats = region, locale.update(regionFormats = region,
zoneNaming = zone, zoneNaming = zone,
metaNaming = meta) metaNaming = meta)
language = self.__langByName[locale.language][0] language: int = self.__langByName[locale.language][0]
script = self.__textByName[locale.script][0] script: int = self.__textByName[locale.script][0]
territory = self.__landByName[locale.territory][0] territory: int = self.__landByName[locale.territory][0]
if language != 1: # C if language != 1: # C
if territory == 0: if territory == 0:
@ -105,7 +111,7 @@ class QLocaleXmlReader (object):
# http://www.unicode.org/reports/tr35/#Likely_Subtags # http://www.unicode.org/reports/tr35/#Likely_Subtags
try: try:
try: try:
to = likely[(language, 0, territory)] to: tuple[int, int, int] = likely[(language, 0, territory)]
except KeyError: except KeyError:
to = likely[(language, 0, 0)] to = likely[(language, 0, 0)]
except KeyError: except KeyError:
@ -116,7 +122,8 @@ class QLocaleXmlReader (object):
yield (language, script, territory), locale yield (language, script, territory), locale
def pruneZoneNaming(self, locmap, report=lambda *x: None): def pruneZoneNaming(self, locmap: dict[tuple[int, int, int], "Locale"],
report=lambda *x: 0) -> None:
"""Deduplicate zoneNaming and metaNaming mapings. """Deduplicate zoneNaming and metaNaming mapings.
Where one locale would fall back to another via likely subtag Where one locale would fall back to another via likely subtag
@ -125,13 +132,15 @@ class QLocaleXmlReader (object):
This prunes over half of the (locale, zone) table and nearly two This prunes over half of the (locale, zone) table and nearly two
thirds of the (locale, meta) table.""" thirds of the (locale, meta) table."""
likely = tuple((has, got) for have, has, give, got in self.likelyMap()) likely: tuple[tuple[tuple[int, int, int], tuple[int, int, int]], ...
def fallbacks(key): ] = tuple((has, got) for have, has, give, got in self.likelyMap())
def fallbacks(key) -> Iterator[Locale]:
# Should match QtTimeZoneLocale::fallbackLocalesFor() in qlocale.cpp # Should match QtTimeZoneLocale::fallbackLocalesFor() in qlocale.cpp
tried, head = { key }, 2 tried: set[tuple[int, int, int]] = { key }
head = 2
while head > 0: while head > 0:
# Retain [:head] of key but use 0 (i.e. Any) for the rest: # Retain [:head] of key but use 0 (i.e. Any) for the rest:
it = self.__fillLikely(key[:head] + (0,) * (3 - head), likely) it: tuple[int, int, int] = self.__fillLikely(key[:head] + (0,) * (3 - head), likely)
if it not in tried: if it not in tried:
tried.add(it) tried.add(it)
if it in locmap: if it in locmap:
@ -178,51 +187,52 @@ class QLocaleXmlReader (object):
f'and {metaCount} (of {metaPrior}) metazone ' f'and {metaCount} (of {metaPrior}) metazone '
f'entries from {locCount} (of {len(locmap)}) locales.\n') f'entries from {locCount} (of {len(locmap)}) locales.\n')
def aliasToIana(self): def aliasToIana(self) -> Iterator[tuple[str, str]]:
def attr(elt, key): def attr(elt: minidom.Element, key: str) -> str:
return elt.attributes[key].nodeValue return elt.attributes[key].nodeValue
for elt in self.__eachEltInGroup(self.root, 'zoneAliases', 'zoneAlias'): for elt in self.__eachEltInGroup(self.root, 'zoneAliases', 'zoneAlias'):
yield attr(elt, 'alias'), attr(elt, 'iana') yield attr(elt, 'alias'), attr(elt, 'iana')
def msToIana(self): def msToIana(self) -> Iterator[tuple[str, str]]:
kid = self.__firstChildText kid: Callable[[minidom.Element, str], str] = self.__firstChildText
for elt in self.__eachEltInGroup(self.root, 'windowsZone', 'msZoneIana'): for elt in self.__eachEltInGroup(self.root, 'windowsZone', 'msZoneIana'):
yield kid(elt, 'msid'), elt.attributes['iana'].nodeValue yield kid(elt, 'msid'), elt.attributes['iana'].nodeValue
def msLandIanas(self): def msLandIanas(self) -> Iterator[tuple[str, str, str]]:
kid = self.__firstChildText kid: Callable[[minidom.Element, str], str] = self.__firstChildText
for elt in self.__eachEltInGroup(self.root, 'windowsZone', 'msLandZones'): for elt in self.__eachEltInGroup(self.root, 'windowsZone', 'msLandZones'):
land = elt.attributes['territory'].nodeValue land: str = elt.attributes['territory'].nodeValue
yield kid(elt, 'msid'), land, kid(elt, 'ianaids') yield kid(elt, 'msid'), land, kid(elt, 'ianaids')
def territoryZone(self): def territoryZone(self) -> Iterator[tuple[str, str]]:
for elt in self.__eachEltInGroup(self.root, 'landZones', 'landZone'): for elt in self.__eachEltInGroup(self.root, 'landZones', 'landZone'):
iana, land = self.__textThenAttrs(elt, 'territory') iana, land = self.__textThenAttrs(elt, 'territory')
yield land, iana yield land, iana
def metaLandZone(self): def metaLandZone(self) -> Iterator[tuple[str, int, str, str]]:
kid = self.__firstChildText kid: Callable[[minidom.Element, str], str] = self.__firstChildText
for elt in self.__eachEltInGroup(self.root, 'metaZones', 'metaZone'): for elt in self.__eachEltInGroup(self.root, 'metaZones', 'metaZone'):
meta, mkey = kid(elt, 'metaname'), int(elt.attributes['metakey'].nodeValue) meta: str = kid(elt, 'metaname')
node = self.__firstChildElt(elt, 'landZone') mkey: int = int(elt.attributes['metakey'].nodeValue)
node: minidom.Element = self.__firstChildElt(elt, 'landZone')
while node: while node:
if self.__isNodeNamed(node, 'landZone'): if self.__isNodeNamed(node, 'landZone'):
iana, land = self.__textThenAttrs(node, 'territory') iana, land = self.__textThenAttrs(node, 'territory')
yield meta, mkey, land, iana yield meta, mkey, land, iana
node = node.nextSibling node = node.nextSibling
def zoneMetaStory(self): def zoneMetaStory(self) -> Iterator[tuple[str, int, int, int]]:
kid = lambda n, k: int(n.attributes[k].nodeValue) kid = lambda n, k: int(n.attributes[k].nodeValue)
for elt in self.__eachEltInGroup(self.root, 'zoneStories', 'zoneStory'): for elt in self.__eachEltInGroup(self.root, 'zoneStories', 'zoneStory'):
iana = elt.attributes['iana'].nodeValue iana: str = elt.attributes['iana'].nodeValue
node = self.__firstChildElt(elt, 'metaInterval') node: minidom.Element = self.__firstChildElt(elt, 'metaInterval')
while node: while node:
if self.__isNodeNamed(node, 'metaInterval'): if self.__isNodeNamed(node, 'metaInterval'):
meta = kid(node, 'metakey') meta: int = kid(node, 'metakey')
yield iana, kid(node, 'start'), kid(node, 'stop'), meta yield iana, kid(node, 'start'), kid(node, 'stop'), meta
node = node.nextSibling node = node.nextSibling
def languageIndices(self, locales): def languageIndices(self, locales: tuple[int, ...]) -> Iterator[tuple[int, str]]:
index = 0 index = 0
for key, value in self.languages.items(): for key, value in self.languages.items():
i, count = 0, locales.count(key) i, count = 0, locales.count(key)
@ -231,17 +241,20 @@ class QLocaleXmlReader (object):
index += count index += count
yield i, value[0] yield i, value[0]
def likelyMap(self): def likelyMap(self) -> Iterator[tuple[str, tuple[int, int, int], str, tuple[int, int, int]]]:
def tag(t): def tag(t: tuple[tuple[int, str], tuple[int, str], tuple[int, str]]) -> Iterator[str]:
lang, script, land = t lang, script, land = t
yield lang[1] if lang[0] else 'und' yield lang[1] if lang[0] else 'und'
if script[0]: yield script[1] if script[0]: yield script[1]
if land[0]: yield land[1] if land[0]: yield land[1]
def ids(t): def ids(t: tuple[tuple[int, str], tuple[int, str], tuple[int, str]]
) -> tuple[int, int, int]:
return tuple(x[0] for x in t) return tuple(x[0] for x in t)
def keyLikely(pair, kl=self.__keyLikely): def keyLikely(pair: tuple[tuple[tuple[int, str], tuple[int, str], tuple[int, str]],
tuple[tuple[int, str], tuple[int, str], tuple[int, str]]],
kl=self.__keyLikely) -> tuple[int, int, int]:
"""Sort by IDs from first entry in pair """Sort by IDs from first entry in pair
We're passed a pair (h, g) of triplets (lang, script, territory) of We're passed a pair (h, g) of triplets (lang, script, territory) of
@ -272,7 +285,7 @@ class QLocaleXmlReader (object):
assert have[0] == give[0], (have, give) assert have[0] == give[0], (have, give)
yield (give[:2], give[2]) yield (give[:2], give[2])
def enumify(self, name, suffix): def enumify(self, name: str, suffix: str) -> str:
"""Stick together the parts of an enumdata.py name. """Stick together the parts of an enumdata.py name.
Names given in enumdata.py include spaces and hyphens that we Names given in enumdata.py include spaces and hyphens that we
@ -299,7 +312,8 @@ class QLocaleXmlReader (object):
return name return name
# Implementation details: # Implementation details:
def __loadMap(self, category, enum): def __loadMap(self, category: str, enum: dict[int, tuple[str, str]]
) -> Iterator[tuple[int, str, str, str]]:
"""Load the language-, script- or territory-map. """Load the language-, script- or territory-map.
First parameter, category, names the map to load, second is the First parameter, category, names the map to load, second is the
@ -312,23 +326,26 @@ class QLocaleXmlReader (object):
key = int(key) key = int(key)
yield key, enum[key][0], code, name yield key, enum[key][0], code, name
def __fromIds(self, ids): def __fromIds(self, ids: tuple[int, int, int]
) -> tuple[tuple[int, str], tuple[int, str], tuple[int, str]]:
# Three (ID, code) pairs: # Three (ID, code) pairs:
return ((ids[0], self.languages[ids[0]][1]), return ((ids[0], self.languages[ids[0]][1]),
(ids[1], self.scripts[ids[1]][1]), (ids[1], self.scripts[ids[1]][1]),
(ids[2], self.territories[ids[2]][1])) (ids[2], self.territories[ids[2]][1]))
# Likely subtag management: # Likely subtag management:
def __likelySubtagsMap(self): def __likelySubtagsMap(self) -> Iterator[tuple[tuple[int, int, int], tuple[int, int, int]]]:
def triplet(element, keys=('language', 'script', 'territory')): def triplet(element: minidom.Element,
keys: tuple[str, str, str]=('language', 'script', 'territory')
) -> tuple[int, int, int]:
return tuple(int(element.attributes[key].nodeValue) for key in keys) return tuple(int(element.attributes[key].nodeValue) for key in keys)
kid = self.__firstChildElt kid: Callable[[minidom.Element, str], minidom.Element] = self.__firstChildElt
for elt in self.__eachEltInGroup(self.root, 'likelySubtags', 'likelySubtag'): for elt in self.__eachEltInGroup(self.root, 'likelySubtags', 'likelySubtag'):
yield triplet(kid(elt, "from")), triplet(kid(elt, "to")) yield triplet(kid(elt, "from")), triplet(kid(elt, "to"))
@staticmethod @staticmethod
def __keyLikely(key, huge=0x10000): def __keyLikely(key: tuple[int, int, int], huge: int=0x10000) -> tuple[int, int, int]:
"""Sort order key for a likely subtag key """Sort order key for a likely subtag key
Although the entries are (lang, script, region), sort by (lang, region, Although the entries are (lang, script, region), sort by (lang, region,
@ -344,16 +361,18 @@ class QLocaleXmlReader (object):
return have[0], have[2], have[1] return have[0], have[2], have[1]
@classmethod @classmethod
def __lowerLikely(cls, key, likely): def __lowerLikely(cls, key: tuple[int, int, int],
likely: tuple[tuple[tuple[int, int, int], tuple[int, int, int]], ...]
) -> int:
"""Lower-bound index for key in the likely subtag table """Lower-bound index for key in the likely subtag table
Equivalent to the std::lower_bound() calls in Equivalent to the std::lower_bound() calls in
QLocaleId::withLikelySubtagsAdded().""" QLocaleId::withLikelySubtagsAdded()."""
lo, hi = 0, len(likely) lo, hi = 0, len(likely)
key = cls.__keyLikely(key) key: tuple[int, int, int] = cls.__keyLikely(key)
while lo + 1 < hi: while lo + 1 < hi:
mid, rem = divmod(lo + hi, 2) mid, rem = divmod(lo + hi, 2)
has = cls.__keyLikely(likely[mid][0]) has: tuple[int, int, int] = cls.__keyLikely(likely[mid][0])
if has < key: if has < key:
lo = mid lo = mid
elif has > key: elif has > key:
@ -363,7 +382,9 @@ class QLocaleXmlReader (object):
return hi return hi
@classmethod @classmethod
def __fillLikely(cls, key, likely): def __fillLikely(cls, key: tuple[int, int, int],
likely: tuple[tuple[tuple[int, int, int], tuple[int, int, int]], ...]
) -> tuple[int, int, int]:
"""Equivalent to QLocaleId::withLikelySubtagsAdded() """Equivalent to QLocaleId::withLikelySubtagsAdded()
Takes one (language, script, territory) triple, key, of QLocale enum Takes one (language, script, territory) triple, key, of QLocale enum
@ -371,7 +392,8 @@ class QLocaleXmlReader (object):
on the likely subtag data supplied as likely.""" on the likely subtag data supplied as likely."""
lang, script, land = key lang, script, land = key
if lang and likely: if lang and likely:
likely = likely[cls.__lowerLikely(key, likely):] likely: tuple[tuple[tuple[int, int, int], tuple[int, int, int]], ...
] = likely[cls.__lowerLikely(key, likely):]
for entry in likely: for entry in likely:
vox, txt, ter = entry[0] vox, txt, ter = entry[0]
if vox != lang: if vox != lang:
@ -420,17 +442,18 @@ class QLocaleXmlReader (object):
# DOM access: # DOM access:
from xml.dom import minidom from xml.dom import minidom
@staticmethod @staticmethod
def __parse(filename, read = minidom.parse): def __parse(filename: str, read = minidom.parse) -> minidom.Element:
return read(filename).documentElement return read(filename).documentElement
@staticmethod @staticmethod
def __isNodeNamed(elt, name, TYPE=minidom.Node.ELEMENT_NODE): def __isNodeNamed(elt: minidom.Element|minidom.Text, name: str,
TYPE: int = minidom.Node.ELEMENT_NODE) -> bool:
return elt.nodeType == TYPE and elt.nodeName == name return elt.nodeType == TYPE and elt.nodeName == name
del minidom del minidom
@staticmethod @staticmethod
def __eltWords(elt): def __eltWords(elt: minidom.Element) -> Iterator[str]:
child = elt.firstChild child: minidom.Text|minidom.CDATASection|None = elt.firstChild
while child: while child:
if child.nodeType in (elt.TEXT_NODE, elt.CDATA_SECTION_NODE): if child.nodeType in (elt.TEXT_NODE, elt.CDATA_SECTION_NODE):
# Note: do not strip(), as some group separators are # Note: do not strip(), as some group separators are
@ -439,8 +462,8 @@ class QLocaleXmlReader (object):
child = child.nextSibling child = child.nextSibling
@classmethod @classmethod
def __firstChildElt(cls, parent, name): def __firstChildElt(cls, parent: minidom.Element, name: str) -> minidom.Element:
child = parent.firstChild child: minidom.Text|minidom.Element = parent.firstChild
while child: while child:
if cls.__isNodeNamed(child, name): if cls.__isNodeNamed(child, name):
return child return child
@ -449,12 +472,12 @@ class QLocaleXmlReader (object):
raise Error(f'No {name} child found') raise Error(f'No {name} child found')
@classmethod @classmethod
def __firstChildText(cls, elt, key): def __firstChildText(cls, elt: minidom.Element, key: str) -> str:
return ' '.join(cls.__eltWords(cls.__firstChildElt(elt, key))) return ' '.join(cls.__eltWords(cls.__firstChildElt(elt, key)))
@classmethod @classmethod
def __textThenAttrs(cls, elt, *names): def __textThenAttrs(cls, elt: minidom.Element, *names: str) -> Iterator[str]:
"""Read an element's text, then a sequence of its attributes. """Read an elements text than a sequence of its attributes.
First parameter is the XML element, subsequent parameters name First parameter is the XML element, subsequent parameters name
attributes of it. Yields the text of the element, followed by the text attributes of it. Yields the text of the element, followed by the text
@ -464,42 +487,46 @@ class QLocaleXmlReader (object):
yield elt.attributes[name].nodeValue yield elt.attributes[name].nodeValue
@classmethod @classmethod
def __zoneData(cls, elt): def __zoneData(cls, elt: minidom.Element
) -> tuple[tuple[str | None, ...],
dict[str, dict[str, str | tuple[str | None, ...]]],
dict[str, dict[str, str | tuple[str | None, ...]]]]:
# Inverse of writer's __writeLocaleZones() # Inverse of writer's __writeLocaleZones()
region = cls.__readZoneForms(elt, 'regionZoneFormats') region: tuple[str | None, ...] = cls.__readZoneForms(elt, 'regionZoneFormats')
try: try:
zone = cls.__firstChildElt(elt, 'zoneNaming') zone: minidom.Element = cls.__firstChildElt(elt, 'zoneNaming')
except Error as what: except Error as what:
if what.message != 'No zoneNaming child found': if what.message != 'No zoneNaming child found':
raise raise
zone = {} zone: dict[str, dict[str, str|tuple[str|None, ...]]] = {}
else: else:
zone = dict(cls.__readZoneNaming(zone)) zone = dict(cls.__readZoneNaming(zone))
try: try:
meta = cls.__firstChildElt(elt, 'metaZoneNaming') meta: minidom.Element = cls.__firstChildElt(elt, 'metaZoneNaming')
except Error as what: except Error as what:
if what.message != 'No metaZoneNaming child found': if what.message != 'No metaZoneNaming child found':
raise raise
meta = {} meta: dict[str, dict[str, str|tuple[str|None, ...]]] = {}
else: else:
meta = dict(cls.__readZoneNaming(meta)) meta = dict(cls.__readZoneNaming(meta))
assert not any('exemplarCity' in v for v in meta.values()) assert not any('exemplarCity' in v for v in meta.values())
return region, zone, meta return region, zone, meta
@classmethod @classmethod
def __readZoneNaming(cls, elt): def __readZoneNaming(cls, elt: minidom.Element
) -> Iterator[tuple[str, dict[str, str|tuple[str|None, ...]]]]:
# Inverse of writer's __writeZoneNaming() # Inverse of writer's __writeZoneNaming()
child = elt.firstChild child: minidom.Element = elt.firstChild
while child: while child:
if cls.__isNodeNamed(child, 'zoneNames'): if cls.__isNodeNamed(child, 'zoneNames'):
iana = child.attributes['name'].nodeValue iana: str = child.attributes['name'].nodeValue
try: try:
city = cls.__firstChildText(child, 'exemplar') city: str = cls.__firstChildText(child, 'exemplar')
except Error: except Error:
data = {} data: dict[str, tuple[str|None, str|None, str|None]] = {}
else: else:
assert city is not None assert city is not None
data = { 'exemplarCity': city } data: dict[str, str|tuple[str|None, ...]] = { 'exemplarCity': city }
for form in ('short', 'long'): for form in ('short', 'long'):
data[form] = cls.__readZoneForms(child, form) data[form] = cls.__readZoneForms(child, form)
yield iana, data yield iana, data
@ -507,9 +534,10 @@ class QLocaleXmlReader (object):
child = child.nextSibling child = child.nextSibling
@classmethod @classmethod
def __readZoneForms(cls, elt, name): def __readZoneForms(cls, elt: minidom.Element, name: str
) -> tuple[str | None, ...]:
# Inverse of writer's __writeZoneForms() # Inverse of writer's __writeZoneForms()
child = elt.firstChild child: minidom.Element = elt.firstChild
while child: while child:
if (cls.__isNodeNamed(child, 'zoneForms') if (cls.__isNodeNamed(child, 'zoneForms')
and child.attributes['name'].nodeValue == name): and child.attributes['name'].nodeValue == name):
@ -518,20 +546,21 @@ class QLocaleXmlReader (object):
return (None, None, None) return (None, None, None)
@classmethod @classmethod
def __scanZoneForms(cls, elt): def __scanZoneForms(cls, elt: minidom.Element) -> Iterator[str|None]:
# Read each entry in a zoneForms element, yield three forms: # Read each entry in a zoneForms element, yield three forms:
for tag in ('generic', 'standard', 'daylightSaving'): for tag in ('generic', 'standard', 'daylightSaving'):
try: try:
node = cls.__firstChildElt(elt, tag) node: minidom.Element = cls.__firstChildElt(elt, tag)
except Error: except Error:
yield None yield None
else: else:
yield ' '.join(cls.__eltWords(node)) yield ' '.join(cls.__eltWords(node))
@classmethod @classmethod
def __eachEltInGroup(cls, parent, group, key): def __eachEltInGroup(cls, parent: minidom.Element, group: str, key: str
) -> Iterator[minidom.Element]:
try: try:
element = cls.__firstChildElt(parent, group).firstChild element: minidom.Element = cls.__firstChildElt(parent, group).firstChild
except Error: except Error:
element = None element = None