Add type annotations to QLocaleXmlWriter
Also fix the annotation of englishNaming in cldr.py. Spotted it while annotating __enumTable. Task-number: QTBUG-129564 Pick-to: 6.8 Change-Id: I93f698b4cf1b5ae90c21fe77330e4f167143a9f3 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
c0b9dc0014
commit
3045a08e5e
@ -352,7 +352,8 @@ class CldrAccess (object):
|
|||||||
inheritance, where relevant."""
|
inheritance, where relevant."""
|
||||||
return LocaleScanner(name, self.__localeRoots(name), self.__rootLocale)
|
return LocaleScanner(name, self.__localeRoots(name), self.__rootLocale)
|
||||||
|
|
||||||
def englishNaming(self, tag: str) -> Callable[[str], str]: # see QLocaleXmlWriter.enumData()
|
# see QLocaleXmlWriter.enumData()
|
||||||
|
def englishNaming(self, tag: str) -> Callable[[str, str], str]:
|
||||||
return self.__codeMap(tag).get
|
return self.__codeMap(tag).get
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -19,7 +19,7 @@ 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 Callable, Iterable, Iterator
|
from typing import Any, Callable, Iterable, Iterator, NoReturn
|
||||||
from xml.sax.saxutils import escape
|
from xml.sax.saxutils import escape
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
@ -619,7 +619,8 @@ class QLocaleXmlWriter (object):
|
|||||||
|
|
||||||
The output saved by this should conform to qlocalexml.rnc's
|
The output saved by this should conform to qlocalexml.rnc's
|
||||||
schema."""
|
schema."""
|
||||||
def __init__(self, cldrVersion, save = None, space = Spacer('\t')):
|
def __init__(self, cldrVersion: str, save: Callable[[str], int]|None = None,
|
||||||
|
space: Spacer = Spacer('\t')) -> None:
|
||||||
"""Set up to write digested CLDR data as QLocale XML.
|
"""Set up to write digested CLDR data as QLocale XML.
|
||||||
|
|
||||||
First argument is the version of CLDR whose data we'll be
|
First argument is the version of CLDR whose data we'll be
|
||||||
@ -637,7 +638,7 @@ class QLocaleXmlWriter (object):
|
|||||||
unmatched new tag and shrinks back on a close-tag (its parsing is
|
unmatched new tag and shrinks back on a close-tag (its parsing is
|
||||||
naive, but adequate to how this class uses it), while adding a newline
|
naive, but adequate to how this class uses it), while adding a newline
|
||||||
to each line."""
|
to each line."""
|
||||||
self.__rawOutput = self.__printit if save is None else save
|
self.__rawOutput: Callable[[str], int] = self.__printit if save is None else save
|
||||||
self.__wrap = space
|
self.__wrap = space
|
||||||
self.__write('<?xml version="1.0" encoding="UTF-8" ?>'
|
self.__write('<?xml version="1.0" encoding="UTF-8" ?>'
|
||||||
# A hint to emacs to make display nicer:
|
# A hint to emacs to make display nicer:
|
||||||
@ -646,7 +647,7 @@ class QLocaleXmlWriter (object):
|
|||||||
versionQt = qtVersion)
|
versionQt = qtVersion)
|
||||||
|
|
||||||
# Output of various sections, in their usual order:
|
# Output of various sections, in their usual order:
|
||||||
def enumData(self, code2name):
|
def enumData(self, code2name: Callable[[str], Callable[[str, str], str]]) -> None:
|
||||||
"""Output name/id/code tables for language, script and territory.
|
"""Output name/id/code tables for language, script and territory.
|
||||||
|
|
||||||
Parameter, code2name, is a function taking 'language',
|
Parameter, code2name, is a function taking 'language',
|
||||||
@ -662,14 +663,15 @@ class QLocaleXmlWriter (object):
|
|||||||
self.__enumTable('script', script_map, code2name)
|
self.__enumTable('script', script_map, code2name)
|
||||||
self.__enumTable('territory', territory_map, code2name)
|
self.__enumTable('territory', territory_map, code2name)
|
||||||
# Prepare to detect any unused codes (see __writeLocale(), close()):
|
# Prepare to detect any unused codes (see __writeLocale(), close()):
|
||||||
self.__languages = set(p[1] for p in language_map.values()
|
self.__languages: set[str] = set(p[1] for p in language_map.values()
|
||||||
if not p[1].isspace())
|
if not p[1].isspace())
|
||||||
self.__scripts = set(p[1] for p in script_map.values()
|
self.__scripts: set[str] = set(p[1] for p in script_map.values()
|
||||||
if p[1] != 'Zzzz')
|
if p[1] != 'Zzzz')
|
||||||
self.__territories = set(p[1] for p in territory_map.values()
|
self.__territories: set[str] = set(p[1] for p in territory_map.values()
|
||||||
if p[1] != 'ZZ')
|
if p[1] != 'ZZ')
|
||||||
|
|
||||||
def likelySubTags(self, entries):
|
def likelySubTags(self, entries: Iterator[tuple[tuple[int, int, int, int],
|
||||||
|
tuple[int, int, int, int]]]) -> None:
|
||||||
self.__openTag('likelySubtags')
|
self.__openTag('likelySubtags')
|
||||||
for have, give in entries:
|
for have, give in entries:
|
||||||
self.__openTag('likelySubtag')
|
self.__openTag('likelySubtag')
|
||||||
@ -678,8 +680,12 @@ class QLocaleXmlWriter (object):
|
|||||||
self.__closeTag('likelySubtag')
|
self.__closeTag('likelySubtag')
|
||||||
self.__closeTag('likelySubtags')
|
self.__closeTag('likelySubtags')
|
||||||
|
|
||||||
def zoneData(self, alias, defaults, windowsIds,
|
def zoneData(self, alias: dict[str, str],
|
||||||
metamap, zones, territorial):
|
defaults: dict[str, str],
|
||||||
|
windowsIds: dict[tuple[str, str], str],
|
||||||
|
metamap: dict[str, dict[str, str]],
|
||||||
|
zones: dict[str, tuple[tuple[int, int, str], ...]],
|
||||||
|
territorial: dict[str, str]) -> None:
|
||||||
self.__openTag('zoneAliases')
|
self.__openTag('zoneAliases')
|
||||||
# iana is a single IANA ID
|
# iana is a single IANA ID
|
||||||
# name has the same form, but has been made redundant
|
# name has the same form, but has been made redundant
|
||||||
@ -709,7 +715,7 @@ class QLocaleXmlWriter (object):
|
|||||||
self.inTag('landZone', iana, territory = code)
|
self.inTag('landZone', iana, territory = code)
|
||||||
self.__closeTag('landZones')
|
self.__closeTag('landZones')
|
||||||
|
|
||||||
metaKey = {m: i for i, m in enumerate(sorted(
|
metaKey: dict[str, int] = {m: i for i, m in enumerate(sorted(
|
||||||
metamap, key = lambda m: m.lower()), 1)}
|
metamap, key = lambda m: m.lower()), 1)}
|
||||||
|
|
||||||
self.__openTag('metaZones')
|
self.__openTag('metaZones')
|
||||||
@ -730,7 +736,8 @@ class QLocaleXmlWriter (object):
|
|||||||
self.__closeTag('zoneStory')
|
self.__closeTag('zoneStory')
|
||||||
self.__closeTag('zoneStories')
|
self.__closeTag('zoneStories')
|
||||||
|
|
||||||
def locales(self, locales, calendars, en_US):
|
def locales(self, locales: dict[tuple[int, int, int, int], "Locale"], calendars: list[str],
|
||||||
|
en_US: tuple[int, int, int, int]) -> None:
|
||||||
"""Write the data for each locale.
|
"""Write the data for each locale.
|
||||||
|
|
||||||
First argument, locales, is the mapping whose values are the
|
First argument, locales, is the mapping whose values are the
|
||||||
@ -740,7 +747,7 @@ class QLocaleXmlWriter (object):
|
|||||||
tuple of numeric IDs that corresponds to en_US (needed to
|
tuple of numeric IDs that corresponds to en_US (needed to
|
||||||
provide fallbacks for the C locale)."""
|
provide fallbacks for the C locale)."""
|
||||||
|
|
||||||
def writeLocale(locale, cal = calendars, this = self):
|
def writeLocale(locale: "Locale", cal = calendars, this = self) -> None:
|
||||||
this.__openTag('locale')
|
this.__openTag('locale')
|
||||||
this.__writeLocale(locale, cal)
|
this.__writeLocale(locale, cal)
|
||||||
this.__writeLocaleZones(locale)
|
this.__writeLocaleZones(locale)
|
||||||
@ -752,7 +759,7 @@ class QLocaleXmlWriter (object):
|
|||||||
writeLocale(locales[key])
|
writeLocale(locales[key])
|
||||||
self.__closeTag('localeList')
|
self.__closeTag('localeList')
|
||||||
|
|
||||||
def inTag(self, tag, text, **attrs):
|
def inTag(self, tag: str, text: str, **attrs: int|str) -> None:
|
||||||
"""Writes an XML element with the given content.
|
"""Writes an XML element with the given content.
|
||||||
|
|
||||||
First parameter, tag, is the element type; second, text, is the content
|
First parameter, tag, is the element type; second, text, is the content
|
||||||
@ -761,19 +768,19 @@ class QLocaleXmlWriter (object):
|
|||||||
include in the opening tag."""
|
include in the opening tag."""
|
||||||
self.__write(f'<{self.__attrJoin(tag, attrs)}>{text}</{tag}>')
|
self.__write(f'<{self.__attrJoin(tag, attrs)}>{text}</{tag}>')
|
||||||
|
|
||||||
def asTag(self, tag, **attrs):
|
def asTag(self, tag: str, **attrs: int|str) -> None:
|
||||||
"""Similar to inTag(), but with no content for the element."""
|
"""Similar to inTag(), but with no content for the element."""
|
||||||
assert attrs, tag # No point to this otherwise
|
assert attrs, tag # No point to this otherwise
|
||||||
self.__write(f'<{self.__attrJoin(tag, attrs)} />')
|
self.__write(f'<{self.__attrJoin(tag, attrs)} />')
|
||||||
|
|
||||||
def safeInTag(self, tag, text, **attrs):
|
def safeInTag(self, tag: str, text: str, **attrs: int|str) -> None:
|
||||||
"""Similar to inTag(), when text isn't known to be XML-safe."""
|
"""Similar to inTag(), when text isn't known to be XML-safe."""
|
||||||
if text.isascii():
|
if text.isascii():
|
||||||
self.inTag(tag, self.__xmlSafe(text), **attrs)
|
self.inTag(tag, self.__xmlSafe(text), **attrs)
|
||||||
else:
|
else:
|
||||||
self.__cdataInTag(tag, text, **attrs)
|
self.__cdataInTag(tag, text, **attrs)
|
||||||
|
|
||||||
def close(self, grumble):
|
def close(self, grumble: Callable[[str], int]) -> None:
|
||||||
"""Finish writing and grumble about any issues discovered."""
|
"""Finish writing and grumble about any issues discovered."""
|
||||||
if self.__rawOutput != self.__complain:
|
if self.__rawOutput != self.__complain:
|
||||||
self.__closeTag('localeDatabase')
|
self.__closeTag('localeDatabase')
|
||||||
@ -794,14 +801,16 @@ class QLocaleXmlWriter (object):
|
|||||||
|
|
||||||
# Implementation details
|
# Implementation details
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __printit(text):
|
def __printit(text: str) -> int:
|
||||||
print(text, end='')
|
print(text, end='')
|
||||||
|
return 0
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __complain(text):
|
def __complain(text) -> NoReturn:
|
||||||
raise Error('Attempted to write data after closing :-(')
|
raise Error('Attempted to write data after closing :-(')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __attrJoin(tag, attrs):
|
def __attrJoin(tag: str, attrs: dict[str, int|str]) -> str:
|
||||||
# Content of open-tag with given tag and attributes
|
# Content of open-tag with given tag and attributes
|
||||||
if not attrs:
|
if not attrs:
|
||||||
return tag
|
return tag
|
||||||
@ -809,13 +818,14 @@ class QLocaleXmlWriter (object):
|
|||||||
return f'{tag} {tail}'
|
return f'{tag} {tail}'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __xmlSafe(text):
|
def __xmlSafe(text: str) -> str:
|
||||||
return text.replace('&', '&').replace('<', '<').replace('>', '>')
|
return text.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||||
|
|
||||||
def __cdataInTag(self, tag, text, **attrs):
|
def __cdataInTag(self, tag: str, text: str, **attrs: int|str) -> None:
|
||||||
self.__write(f'<{self.__attrJoin(tag, attrs)}><![CDATA[{text}]]></{tag}>')
|
self.__write(f'<{self.__attrJoin(tag, attrs)}><![CDATA[{text}]]></{tag}>')
|
||||||
|
|
||||||
def __enumTable(self, tag, table, code2name):
|
def __enumTable(self, tag: str, table: dict[int, tuple[str, str]],
|
||||||
|
code2name: Callable[[str], Callable[[str, str], str]]) -> None:
|
||||||
"""Writes a table of QLocale-enum-related data.
|
"""Writes a table of QLocale-enum-related data.
|
||||||
|
|
||||||
First parameter, tag, is 'language', 'script' or 'territory',
|
First parameter, tag, is 'language', 'script' or 'territory',
|
||||||
@ -824,32 +834,34 @@ class QLocaleXmlWriter (object):
|
|||||||
type. Last is the englishNaming method of the CldrAccess being used to
|
type. Last is the englishNaming method of the CldrAccess being used to
|
||||||
read CLDR data; it is used to map ISO codes to en.xml names."""
|
read CLDR data; it is used to map ISO codes to en.xml names."""
|
||||||
self.__openTag(f'{tag}List')
|
self.__openTag(f'{tag}List')
|
||||||
enname = code2name(tag)
|
enname: Callable[[str, str], str] = code2name(tag)
|
||||||
for key, (name, code) in table.items():
|
for key, (name, code) in table.items():
|
||||||
self.safeInTag('naming', enname(code, name), id = key, code = code)
|
self.safeInTag('naming', enname(code, name), id = key, code = code)
|
||||||
self.__closeTag(f'{tag}List')
|
self.__closeTag(f'{tag}List')
|
||||||
|
|
||||||
def __likelySubTag(self, tag, likely):
|
def __likelySubTag(self, tag: str, likely: tuple[int, int, int, int]) -> None:
|
||||||
self.asTag(tag, language = likely[0], script = likely[1],
|
self.asTag(tag, language = likely[0], script = likely[1],
|
||||||
territory = likely[2]) # variant = likely[3]
|
territory = likely[2]) # variant = likely[3]
|
||||||
|
|
||||||
def __writeLocale(self, locale, calendars):
|
def __writeLocale(self, locale: "Locale", calendars: list[str]) -> None:
|
||||||
locale.toXml(self.inTag, calendars)
|
locale.toXml(self.inTag, calendars)
|
||||||
self.__languages.discard(locale.language_code)
|
self.__languages.discard(locale.language_code)
|
||||||
self.__scripts.discard(locale.script_code)
|
self.__scripts.discard(locale.script_code)
|
||||||
self.__territories.discard(locale.territory_code)
|
self.__territories.discard(locale.territory_code)
|
||||||
|
|
||||||
def __writeLocaleZones(self, locale):
|
def __writeLocaleZones(self, locale: "Locale") -> None:
|
||||||
self.__writeZoneForms('regionZoneFormats', locale.regionZoneFormats)
|
self.__writeZoneForms('regionZoneFormats', locale.regionZoneFormats)
|
||||||
self.__writeZoneNaming('zoneNaming', locale.zoneNaming)
|
self.__writeZoneNaming('zoneNaming', locale.zoneNaming)
|
||||||
self.__writeZoneNaming('metaZoneNaming', locale.metaZoneNaming)
|
self.__writeZoneNaming('metaZoneNaming', locale.metaZoneNaming)
|
||||||
|
|
||||||
def __writeZoneNaming(self, group, naming):
|
def __writeZoneNaming(self, group: str,
|
||||||
|
naming: dict[str, dict[str, str|tuple[str|None, str|None, str|None]]]
|
||||||
|
) -> None:
|
||||||
if not naming:
|
if not naming:
|
||||||
return
|
return
|
||||||
self.__openTag(group)
|
self.__openTag(group)
|
||||||
for iana in sorted(naming.keys()):
|
for iana in sorted(naming.keys()): # str
|
||||||
data = naming[iana]
|
data: dict[str, str|tuple[str|None, str|None, str|None]] = naming[iana]
|
||||||
self.__openTag('zoneNames', name=iana)
|
self.__openTag('zoneNames', name=iana)
|
||||||
if 'exemplarCity' in data:
|
if 'exemplarCity' in data:
|
||||||
self.inTag('exemplar', data['exemplarCity'])
|
self.inTag('exemplar', data['exemplarCity'])
|
||||||
@ -859,7 +871,7 @@ class QLocaleXmlWriter (object):
|
|||||||
self.__closeTag('zoneNames')
|
self.__closeTag('zoneNames')
|
||||||
self.__closeTag(group)
|
self.__closeTag(group)
|
||||||
|
|
||||||
def __writeZoneForms(self, group, forms):
|
def __writeZoneForms(self, group: str, forms: tuple[str|None, str|None, str|None]) -> None:
|
||||||
if all(x is None for x in forms):
|
if all(x is None for x in forms):
|
||||||
return
|
return
|
||||||
self.__openTag('zoneForms', name=group)
|
self.__openTag('zoneForms', name=group)
|
||||||
@ -868,13 +880,13 @@ class QLocaleXmlWriter (object):
|
|||||||
self.safeInTag(tag, forms[i])
|
self.safeInTag(tag, forms[i])
|
||||||
self.__closeTag('zoneForms')
|
self.__closeTag('zoneForms')
|
||||||
|
|
||||||
def __openTag(self, tag, **attrs):
|
def __openTag(self, tag: str, **attrs: int|str) -> None:
|
||||||
self.__write(f'<{self.__attrJoin(tag, attrs)}>')
|
self.__write(f'<{self.__attrJoin(tag, attrs)}>')
|
||||||
|
|
||||||
def __closeTag(self, tag):
|
def __closeTag(self, tag: str) -> None:
|
||||||
self.__write(f'</{tag}>')
|
self.__write(f'</{tag}>')
|
||||||
|
|
||||||
def __write(self, line):
|
def __write(self, line: str) -> None:
|
||||||
self.__rawOutput(self.__wrap(line))
|
self.__rawOutput(self.__wrap(line))
|
||||||
|
|
||||||
class Locale (object):
|
class Locale (object):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user