locale_database: Use argparse module to parse command line arguments

arparse is the standard way to parse command line arguments in Python.
It provides help and usage information for free and is easier to extend
than a custom argument parser.

Task-number: QTBUG-83488
Pick-to: 6.2
Change-Id: I1e4c9cd914449e083d01932bc871ef10d26f0bc2
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Ievgenii Meshcheriakov 2021-07-07 12:41:10 +02:00
parent 41458fafa0
commit 5ef5dce53b
3 changed files with 69 additions and 70 deletions

View File

@ -27,7 +27,7 @@
## $QT_END_LICENSE$
##
#############################################################################
"""Convert CLDR data to qLocaleXML
"""Convert CLDR data to QLocaleXML
The CLDR data can be downloaded from CLDR_, which has a sub-directory
for each version; you need the ``core.zip`` file for your version of
@ -51,53 +51,49 @@ order.
While updating the locale data, check also for updates to MS-Win's
time zone names; see cldr2qtimezone.py for details.
All the scripts mentioned support --help to tell you how to use them.
.. _CLDR: ftp://unicode.org/Public/cldr/
"""
import os
import sys
import argparse
from cldr import CldrReader
from qlocalexml import QLocaleXmlWriter
def usage(name, err, message = ''):
err.write(f"""Usage: {name} path/to/cldr/common/main [out-file.xml]
""") # TODO: expand command-line, improve help message
if message:
err.write(f'\n{message}\n')
def main(args, out, err):
# TODO: make calendars a command-line option
calendars = ['gregorian', 'persian', 'islamic'] # 'hebrew'
def main(out, err):
all_calendars = ['gregorian', 'persian', 'islamic'] # 'hebrew'
# TODO: make argument parsing more sophisticated
name = args.pop(0)
if not args:
usage(name, err, 'Where is your CLDR data tree ?')
return 1
parser = argparse.ArgumentParser(
description='Generate QLocaleXML from CLDR data.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('cldr_path', help='path to the root of the CLDR tree')
parser.add_argument('out_file', help='output XML file name',
nargs='?', metavar='out-file.xml')
parser.add_argument('--calendars', help='select calendars to emit data for',
nargs='+', metavar='CALENDAR',
choices=all_calendars, default=all_calendars)
root = args.pop(0)
args = parser.parse_args()
root = args.cldr_path
if not os.path.exists(os.path.join(root, 'common', 'main', 'root.xml')):
usage(name, err, 'First argument is the root of the CLDR tree: '
f'found no common/main/root.xml under {root}')
return 1
parser.error('First argument is the root of the CLDR tree: '
f'found no common/main/root.xml under {root}')
xml = args.pop(0) if args else None
xml = args.out_file
if not xml or xml == '-':
emit = out
elif not xml.endswith('.xml'):
usage(name, err, f'Please use a .xml extension on your output file name, not {xml}')
return 1
parser.error(f'Please use a .xml extension on your output file name, not {xml}')
else:
try:
emit = open(xml, 'w')
except IOError as e:
usage(name, err, f'Failed to open "{xml}" to write output to it\n')
return 1
if args:
usage(name, err, 'Too many arguments - excess: ' + ' '.join(args))
return 1
parser.error(f'Failed to open "{xml}" to write output to it')
# TODO - command line options to tune choice of grumble and whitter:
reader = CldrReader(root, err.write, err.write)
@ -106,10 +102,10 @@ def main(args, out, err):
writer.version(reader.root.cldrVersion)
writer.enumData()
writer.likelySubTags(reader.likelySubTags())
writer.locales(reader.readLocales(calendars), calendars)
writer.locales(reader.readLocales(args.calendars), args.calendars)
writer.close(err.write)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv, sys.stdout, sys.stderr))
sys.exit(main(sys.stdout, sys.stderr))

View File

@ -39,6 +39,7 @@ for use.
import os
import datetime
import textwrap
import argparse
from localetools import unicode2hex, wrap_list, Error, SourceFileEditor
from cldr import CldrAccess
@ -324,46 +325,41 @@ class ZoneIdWriter (SourceFileEditor):
return windowsIdData, ianaIdData
def usage(err, name, message=''):
err.write(f"""Usage: {name} path/to/cldr/root path/to/qtbase
""") # TODO: more interesting message
if message:
err.write(f'\n{message}\n')
def main(args, out, err):
def main(out, err):
"""Parses CLDR's data and updates Qt's representation of it.
Takes sys.argv, sys.stdout, sys.stderr (or equivalents) as
Takes sys.stdout, sys.stderr (or equivalents) as
arguments. Expects two command-line options: the root of the
unpacked CLDR data-file tree and the root of the qtbase module's
checkout. Updates QTimeZone's private data about Windows time-zone
IDs."""
name = args.pop(0)
if len(args) != 2:
usage(err, name, "Expected two arguments")
return 1
parser = argparse.ArgumentParser(
description="Update Qt's CLDR-derived timezone data.")
parser.add_argument('cldr_path', help='path to the root of the CLDR tree')
parser.add_argument('qtbase_path', help='path to the root of the qtbase source tree')
cldrPath = args.pop(0)
qtPath = args.pop(0)
args = parser.parse_args()
cldrPath = args.cldr_path
qtPath = args.qtbase_path
if not os.path.isdir(qtPath):
usage(err, name, f"No such Qt directory: {qtPath}")
return 1
parser.error(f"No such Qt directory: {qtPath}")
if not os.path.isdir(cldrPath):
usage(err, name, f"No such CLDR directory: {cldrPath}")
return 1
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):
usage(err, name, f'No such file: {dataFilePath}')
return 1
parser.error(f'No such file: {dataFilePath}')
try:
version, defaults, winIds = CldrAccess(cldrPath).readWindowsTimeZones(
dict((name, ind) for ind, name in enumerate((x[0] for x in windowsIdList), 1)))
except IOError as e:
usage(err, name,
f'Failed to open common/supplemental/windowsZones.xml: {e}')
parser.error(
f'Failed to open common/supplemental/windowsZones.xml: {e}')
return 1
except Error as e:
err.write('\n'.join(textwrap.wrap(
@ -391,4 +387,4 @@ def main(args, out, err):
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv, sys.stdout, sys.stderr))
sys.exit(main(sys.stdout, sys.stderr))

View File

@ -26,15 +26,16 @@
## $QT_END_LICENSE$
##
#############################################################################
"""Script to generate C++ code from CLDR data in qLocaleXML form
"""Script to generate C++ code from CLDR data in QLocaleXML form
See ``cldr2qlocalexml.py`` for how to generate the qLocaleXML data itself.
See ``cldr2qlocalexml.py`` for how to generate the QLocaleXML data itself.
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 qlocalexml import QLocaleXmlReader
from localetools import unicode2hex, wrap_list, Error, Transcriber, SourceFileEditor
@ -498,30 +499,36 @@ class LocaleHeaderWriter (SourceFileEditor):
out('\n };\n')
def usage(name, err, message = ''):
err.write(f"""Usage: {name} path/to/qlocale.xml root/of/qtbase
""") # TODO: elaborate
if message:
err.write('\n' + message + '\n')
def main(args, out, err):
# TODO: Make calendars a command-line parameter
def main(out, err):
# map { CLDR name: Qt file name }
calendars = {'gregorian': 'roman', 'persian': 'jalali', 'islamic': 'hijri',} # 'hebrew': 'hebrew',
calendars_map = {
'gregorian': 'roman',
'persian': 'jalali',
'islamic': 'hijri',
# 'hebrew': 'hebrew'
}
all_calendars = list(calendars_map.keys())
name = args.pop(0)
if len(args) != 2:
usage(name, err, 'I expect two arguments')
return 1
parser = argparse.ArgumentParser(
description='Generate C++ code from CLDR data in QLocaleXML form.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('input_file', help='input XML file name',
metavar='input-file.xml')
parser.add_argument('qtbase_path', help='path to the root of the qtbase source tree')
parser.add_argument('--calendars', help='select calendars to emit data for',
nargs='+', metavar='CALENDAR',
choices=all_calendars, default=all_calendars)
args = parser.parse_args()
qlocalexml = args.pop(0)
qtsrcdir = args.pop(0)
qlocalexml = args.input_file
qtsrcdir = 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))
for leaf in ('qlocale_data_p.h', 'qlocale.h', 'qlocale.qdoc'))):
usage(name, err, f'Missing expected files under qtbase source root {qtsrcdir}')
return 1
parser.error(f'Missing expected files under qtbase source root {qtsrcdir}')
reader = QLocaleXmlReader(qlocalexml)
locale_map = dict(reader.loadLocaleMap(calendars, err.write))
@ -617,4 +624,4 @@ def main(args, out, err):
if __name__ == "__main__":
import sys
sys.exit(main(sys.argv, sys.stdout, sys.stderr))
sys.exit(main(sys.stdout, sys.stderr))