summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIevgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>2021-07-09 15:34:40 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-07-19 22:08:32 +0000
commit78cb3b346a36e2b9e7dc060d530d8c0fd019e431 (patch)
tree119f5cf91ff0560dc75e9350a385d2b86af00912
parentecbebe1033e5382fcbc2a6fdfa8eb26f75e7080b (diff)
locale_database: Use pathlib to manipulate paths in Python code
pathlib's API is more modern and easier to use than os.path. It also allows to distinguish between paths and other strings in type annotations. Task-number: QTBUG-83488 Change-Id: Ie6d9b4e35596f7f6befa4c9635f4a65ea3b20025 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> (cherry picked from commit 2d0c2c9f1cb4f1637b623a80312251326740f245) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--util/locale_database/cldr.py54
-rwxr-xr-xutil/locale_database/cldr2qlocalexml.py10
-rwxr-xr-xutil/locale_database/cldr2qtimezone.py15
-rw-r--r--util/locale_database/localetools.py38
-rwxr-xr-xutil/locale_database/qlocalexml2cpp.py24
5 files changed, 76 insertions, 65 deletions
diff --git a/util/locale_database/cldr.py b/util/locale_database/cldr.py
index 9098eaf8bf..3448b89582 100644
--- a/util/locale_database/cldr.py
+++ b/util/locale_database/cldr.py
@@ -36,15 +36,16 @@ The former should normally be all you need to access.
See individual classes for further detail.
"""
+from typing import Iterable, TextIO
from xml.dom import minidom
from weakref import WeakValueDictionary as CacheDict
-import os
+from pathlib import Path
from ldml import Error, Node, XmlScanner, Supplement, LocaleScanner
from qlocalexml import Locale
class CldrReader (object):
- def __init__(self, root, grumble = lambda msg: None, whitter = lambda msg: None):
+ def __init__(self, root: Path, grumble = lambda msg: None, whitter = lambda msg: None):
"""Set up a reader object for reading CLDR data.
Single parameter, root, is the file-system path to the root of
@@ -247,7 +248,7 @@ class CldrReader (object):
# the cache. If a process were to instantiate this class with distinct
# roots, each cache would be filled by the first to need it !
class CldrAccess (object):
- def __init__(self, root):
+ def __init__(self, root: Path):
"""Set up a master object for accessing CLDR data.
Single parameter, root, is the file-system path to the root of
@@ -255,18 +256,18 @@ class CldrAccess (object):
contain dtd/, main/ and supplemental/ sub-directories."""
self.root = root
- def xml(self, *path):
+ def xml(self, relative_path: str):
"""Load a single XML file and return its root element as an XmlScanner.
The path is interpreted relative to self.root"""
- return XmlScanner(Node(self.__xml(path)))
+ return XmlScanner(Node(self.__xml(relative_path)))
def supplement(self, name):
"""Loads supplemental data as a Supplement object.
The name should be that of a file in common/supplemental/, without path.
"""
- return Supplement(Node(self.__xml(('common', 'supplemental', name))))
+ return Supplement(Node(self.__xml(f'common/supplemental/{name}')))
def locale(self, name):
"""Loads all data for a locale as a LocaleScanner object.
@@ -279,16 +280,14 @@ class CldrAccess (object):
return LocaleScanner(name, self.__localeRoots(name), self.__rootLocale)
@property
- def fileLocales(self, joinPath = os.path.join, listDirectory = os.listdir,
- splitExtension = os.path.splitext):
+ def fileLocales(self) -> Iterable[str]:
"""Generator for locale IDs seen in file-names.
All *.xml other than root.xml in common/main/ are assumed to
identify locales."""
- for name in listDirectory(joinPath(self.root, 'common', 'main')):
- stem, ext = splitExtension(name)
- if ext == '.xml' and stem != 'root':
- yield stem
+ for path in self.root.joinpath('common/main').glob('*.xml'):
+ if path.stem != 'root':
+ yield path.stem
@property
def defaultContentLocales(self):
@@ -512,20 +511,20 @@ enumdata.py (keeping the old name as an alias):
return self.__cldrVersion
# Implementation details
- def __xml(self, path, cache = CacheDict(), read = minidom.parse, joinPath = os.path.join):
+ def __xml(self, relative_path: str, cache = CacheDict(), read = minidom.parse):
try:
- doc = cache[path]
+ doc = cache[relative_path]
except KeyError:
- cache[path] = doc = read(joinPath(self.root, *path)).documentElement
+ cache[relative_path] = doc = read(str(self.root.joinpath(relative_path))).documentElement
return doc
- def __open(self, path, joinPath=os.path.join):
- return open(joinPath(self.root, *path))
+ def __open(self, relative_path: str) -> TextIO:
+ return self.root.joinpath(relative_path).open()
@property
def __rootLocale(self, cache = []):
if not cache:
- cache.append(self.xml('common', 'main', 'root.xml'))
+ cache.append(self.xml('common/main/root.xml'))
return cache[0]
@property
@@ -535,7 +534,7 @@ enumdata.py (keeping the old name as an alias):
return cache[0]
@property
- def __numberSystems(self, cache = {}, joinPath=os.path.join):
+ def __numberSystems(self, cache = {}):
if not cache:
for ignore, attrs in self.supplement('numberingSystems.xml').find('numberingSystems'):
cache[attrs['id']] = attrs
@@ -610,7 +609,7 @@ enumdata.py (keeping the old name as an alias):
return cache
@property
- def __unDistinguishedAttributes(self, cache = {}, joinPath = os.path.join):
+ def __unDistinguishedAttributes(self, cache = {}):
"""Mapping from tag names to lists of attributes.
LDML defines some attributes as 'distinguishing': if a node
@@ -630,7 +629,7 @@ enumdata.py (keeping the old name as an alias):
return cache
- def __scanLdmlDtd(self, joinPath = os.path.join):
+ def __scanLdmlDtd(self):
"""Scan the LDML DTD, record CLDR version
Yields (tag, attrs) pairs: on elements with a given tag,
@@ -640,7 +639,7 @@ enumdata.py (keeping the old name as an alias):
Sets self.__cldrVersion as a side-effect, since this
information is found in the same file."""
- with self.__open(('common', 'dtd', 'ldml.dtd')) as dtd:
+ with self.__open('common/dtd/ldml.dtd') as dtd:
tag, ignored, last = None, None, None
for line in dtd:
@@ -700,7 +699,7 @@ enumdata.py (keeping the old name as an alias):
naming = {'language': 'languages', 'script': 'scripts',
'territory': 'territories', 'variant': 'variants'}):
if not cache:
- root = self.xml('common', 'main', 'en.xml').root.findUniqueChild('localeDisplayNames')
+ root = self.xml('common/main/en.xml').root.findUniqueChild('localeDisplayNames')
for dst, src in naming.items():
cache[dst] = dict(self.__codeMapScan(root.findUniqueChild(src)))
assert cache
@@ -743,10 +742,9 @@ enumdata.py (keeping the old name as an alias):
return cache
- def __localeAsDoc(self, name, aliasFor = None,
- joinPath = os.path.join, exists = os.path.isfile):
- path = ('common', 'main', f'{name}.xml')
- if exists(joinPath(self.root, *path)):
+ def __localeAsDoc(self, name: str, aliasFor = None):
+ path = f'common/main/{name}.xml'
+ if self.root.joinpath(path).exists():
elt = self.__xml(path)
for child in Node(elt).findAllChildren('alias'):
try:
@@ -785,4 +783,4 @@ enumdata.py (keeping the old name as an alias):
return chain
# Unpolute the namespace: we don't need to export these.
-del minidom, CacheDict, os
+del minidom, CacheDict
diff --git a/util/locale_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py
index 6ebf62e95a..0232120421 100755
--- a/util/locale_database/cldr2qlocalexml.py
+++ b/util/locale_database/cldr2qlocalexml.py
@@ -56,7 +56,7 @@ All the scripts mentioned support --help to tell you how to use them.
.. _CLDR: ftp://unicode.org/Public/cldr/
"""
-import os
+from pathlib import Path
import sys
import argparse
@@ -79,10 +79,12 @@ def main(out, err):
args = parser.parse_args()
- root = args.cldr_path
- if not os.path.exists(os.path.join(root, 'common', 'main', 'root.xml')):
+ root = Path(args.cldr_path)
+ root_xml_path = 'common/main/root.xml'
+
+ if not root.joinpath(root_xml_path).exists():
parser.error('First argument is the root of the CLDR tree: '
- f'found no common/main/root.xml under {root}')
+ f'found no {root_xml_path} under {root}')
xml = args.out_file
if not xml or xml == '-':
diff --git a/util/locale_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py
index 30e351a7a4..bd9b050e1c 100755
--- a/util/locale_database/cldr2qtimezone.py
+++ b/util/locale_database/cldr2qtimezone.py
@@ -36,8 +36,8 @@ shall update qtbase's src/corelib/time/qtimezoneprivate_data_p.h ready
for use.
"""
-import os
import datetime
+from pathlib import Path
import textwrap
import argparse
@@ -341,17 +341,18 @@ def main(out, err):
args = parser.parse_args()
- cldrPath = args.cldr_path
- qtPath = args.qtbase_path
+ cldrPath = Path(args.cldr_path)
+ qtPath = Path(args.qtbase_path)
- if not os.path.isdir(qtPath):
+ if not qtPath.is_dir():
parser.error(f"No such Qt directory: {qtPath}")
- if not os.path.isdir(cldrPath):
+ if not cldrPath.is_dir():
parser.error(f"No such CLDR directory: {cldrPath}")
- dataFilePath = os.path.join(qtPath, 'src', 'corelib', 'time', 'qtimezoneprivate_data_p.h')
- if not os.path.isfile(dataFilePath):
+ dataFilePath = qtPath.joinpath('src/corelib/time/qtimezoneprivate_data_p.h')
+
+ if not dataFilePath.is_file():
parser.error(f'No such file: {dataFilePath}')
try:
diff --git a/util/locale_database/localetools.py b/util/locale_database/localetools.py
index 1f415bbdb3..82b0848f4a 100644
--- a/util/locale_database/localetools.py
+++ b/util/locale_database/localetools.py
@@ -38,6 +38,7 @@ Classes:
"""
import os
+from pathlib import Path
import tempfile
class Error (Exception):
@@ -81,29 +82,40 @@ class Transcriber (object):
Callers should call close() on success or cleanup() on failure (to
clear away the temporary file).
"""
- def __init__(self, path, temp):
+ def __init__(self, path: Path, temp_dir: Path):
# Open the old file
self.reader = open(path)
# Create a temp file to write the new data into
- temp, tempPath = tempfile.mkstemp(os.path.split(path)[1], dir = temp)
- self.__names = path, tempPath
+ temp, tempPath = tempfile.mkstemp(path.name, dir=temp_dir)
+ self.path = path
+ self.tempPath = Path(tempPath)
self.writer = os.fdopen(temp, "w")
- def close(self):
+ def close(self) -> None:
self.reader.close()
self.writer.close()
self.reader = self.writer = None
- source, temp = self.__names
- os.remove(source)
- os.rename(temp, source)
- def cleanup(self):
- if self.__names:
+ # Move the modified file to the original location
+ self.path.unlink()
+ self.tempPath.rename(self.path)
+
+ self.tempPath = None
+
+ def cleanup(self) -> None:
+ if self.reader:
self.reader.close()
+ self.reader = None
+
+ if self.writer:
self.writer.close()
+ self.writer = None
+
+ if self.tempPath:
# Remove temp-file:
- os.remove(self.__names[1])
- self.__names = ()
+ self.tempPath.unlink(missing_ok=True)
+ self.tempPath = None
+
class SourceFileEditor (Transcriber):
"""Transcriber with transcription of code around a gnerated block.
@@ -125,14 +137,14 @@ class SourceFileEditor (Transcriber):
Callers should call close() on success or cleanup() on failure (to
clear away the temporary file); see Transcriber.
"""
- def __init__(self, path, temp):
+ def __init__(self, path: Path, temp_dir: Path):
"""Set up the source file editor.
Requires two arguments: the path to the source file to be read
and, on success, replaced with a new version; and the
directory in which to store the temporary file during the
rewrite."""
- super().__init__(path, temp)
+ super().__init__(path, temp_dir)
self.__copyPrelude()
def close(self):
diff --git a/util/locale_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py
index 50a03dc9f3..9866bd6ea7 100755
--- a/util/locale_database/qlocalexml2cpp.py
+++ b/util/locale_database/qlocalexml2cpp.py
@@ -33,9 +33,9 @@ Pass the output file from that as first parameter to this script; pass
the root of the qtbase check-out as second parameter.
"""
-import os
import datetime
import argparse
+from pathlib import Path
from qlocalexml import QLocaleXmlReader
from localetools import unicode2hex, wrap_list, Error, Transcriber, SourceFileEditor
@@ -133,7 +133,7 @@ def currencyIsoCodeData(s):
return "{0,0,0}"
class LocaleSourceEditor (SourceFileEditor):
- def __init__(self, path, temp, version):
+ def __init__(self, path: Path, temp: Path, version: str):
super().__init__(path, temp)
self.writer.write(f"""
/*
@@ -522,11 +522,11 @@ def main(out, err):
args = parser.parse_args()
qlocalexml = args.input_file
- qtsrcdir = args.qtbase_path
+ qtsrcdir = Path(args.qtbase_path)
calendars = {cal: calendars_map[cal] for cal in args.calendars}
- if not (os.path.isdir(qtsrcdir)
- and all(os.path.isfile(os.path.join(qtsrcdir, 'src', 'corelib', 'text', leaf))
+ if not (qtsrcdir.is_dir()
+ and all(qtsrcdir.joinpath('src/corelib/text', leaf).is_file()
for leaf in ('qlocale_data_p.h', 'qlocale.h', 'qlocale.qdoc'))):
parser.error(f'Missing expected files under qtbase source root {qtsrcdir}')
@@ -535,8 +535,7 @@ def main(out, err):
locale_keys = sorted(locale_map.keys(), key=LocaleKeySorter(reader.defaultMap()))
try:
- writer = LocaleDataWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'text',
- 'qlocale_data_p.h'),
+ writer = LocaleDataWriter(qtsrcdir.joinpath('src/corelib/text/qlocale_data_p.h'),
qtsrcdir, reader.cldrVersion)
except IOError as e:
err.write(f'Failed to open files to transcribe locale data: {e}')
@@ -564,9 +563,9 @@ def main(out, err):
# Generate calendar data
for calendar, stem in calendars.items():
try:
- writer = CalendarDataWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'time',
- f'q{stem}calendar_data_p.h'),
- qtsrcdir, reader.cldrVersion)
+ writer = CalendarDataWriter(
+ qtsrcdir.joinpath(f'src/corelib/time/q{stem}calendar_data_p.h'),
+ qtsrcdir, reader.cldrVersion)
except IOError as e:
err.write(f'Failed to open files to transcribe {calendar} data {e}')
return 1
@@ -582,7 +581,7 @@ def main(out, err):
# qlocale.h
try:
- writer = LocaleHeaderWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'text', 'qlocale.h'),
+ writer = LocaleHeaderWriter(qtsrcdir.joinpath('src/corelib/text/qlocale.h'),
qtsrcdir, reader.dupes)
except IOError as e:
err.write(f'Failed to open files to transcribe qlocale.h: {e}')
@@ -601,8 +600,7 @@ def main(out, err):
# qlocale.qdoc
try:
- writer = Transcriber(os.path.join(qtsrcdir, 'src', 'corelib', 'text', 'qlocale.qdoc'),
- qtsrcdir)
+ writer = Transcriber(qtsrcdir.joinpath('src/corelib/text/qlocale.qdoc'), qtsrcdir)
except IOError as e:
err.write(f'Failed to open files to transcribe qlocale.qdoc: {e}')
return 1