From 337a012c1ceb49fc596851c9252bfff5c422bedf Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Tue, 18 Mar 2014 13:33:03 -0400 Subject: [PATCH] Make all i18n scripts use argparse, handle --verbose flag --- i18n/dummy.py | 9 ++++-- i18n/extract.py | 5 ++-- i18n/generate.py | 28 ++++++++++-------- i18n/segment.py | 38 +++++++++++++------------ i18n/transifex.py | 25 ++++++++-------- i18n/validate.py | 72 ++++++++++++++++++++++------------------------- 6 files changed, 93 insertions(+), 84 deletions(-) diff --git a/i18n/dummy.py b/i18n/dummy.py index 481cfc54fd..58506912f6 100755 --- a/i18n/dummy.py +++ b/i18n/dummy.py @@ -25,6 +25,7 @@ where $DUMMY_LOCALE is the dummy_locale value set in the i18n config from __future__ import print_function import re import sys +import argparse import polib from path import path @@ -204,7 +205,7 @@ def main(verbosity=1): SOURCE_MSGS_DIR = CONFIGURATION.source_messages_dir for locale, converter in zip(CONFIGURATION.dummy_locales, [Dummy(), Dummy2()]): if verbosity: - print("Processing source language files into dummy strings, locale {}:".format(locale)) + print('Processing source language files into dummy strings, locale "{}"'.format(locale)) for source_file in CONFIGURATION.source_messages_dir.walkfiles('*.po'): if verbosity: print(' ', source_file.relpath()) @@ -214,4 +215,8 @@ def main(verbosity=1): if __name__ == '__main__': - sys.exit(main()) + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--verbose", "-v", action="count", default=0) + args = parser.parse_args() + ret = main(verbosity=args.verbose) + sys.exit(ret) diff --git a/i18n/extract.py b/i18n/extract.py index b7e81d2f8d..d6225fdbc1 100755 --- a/i18n/extract.py +++ b/i18n/extract.py @@ -210,7 +210,8 @@ def is_key_string(string): if __name__ == '__main__': - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--verbose', '-v', action='count', default=0) args = parser.parse_args() - main(verbosity=args.verbose) + ret = main(verbosity=args.verbose) + sys.exit(ret) diff --git a/i18n/generate.py b/i18n/generate.py index 8880980da0..cd2fcc565d 100755 --- a/i18n/generate.py +++ b/i18n/generate.py @@ -111,23 +111,27 @@ def validate_files(dir, files_to_merge): raise Exception("I18N: Cannot generate because file not found: {0}".format(pathname)) -def main(argv=None): - logging.basicConfig(stream=sys.stdout, level=logging.INFO) - - parser = argparse.ArgumentParser(description="Generate merged and compiled message files.") - parser.add_argument("--strict", action='store_true', help="Complain about missing files.") - - args = parser.parse_args(argv or []) - +def main(strict=True, verbosity=1): for locale in CONFIGURATION.translated_locales: - merge_files(locale, fail_if_missing=args.strict) + merge_files(locale, fail_if_missing=strict) # Dummy text is not required. Don't raise exception if files are missing. for locale in CONFIGURATION.dummy_locales: merge_files(locale, fail_if_missing=False) - compile_cmd = 'django-admin.py compilemessages -v0' - execute(compile_cmd, working_directory=BASE_DIR, stderr=DEVNULL) + compile_cmd = 'django-admin.py compilemessages -v{}'.format(verbosity) + if verbosity: + stderr = None + else: + stderr = DEVNULL + execute(compile_cmd, working_directory=BASE_DIR, stderr=stderr) if __name__ == '__main__': - main(sys.argv[1:]) + logging.basicConfig(stream=sys.stdout, level=logging.INFO) + + parser = argparse.ArgumentParser(description="Generate merged and compiled message files.") + parser.add_argument("--strict", action='store_true', help="Complain about missing files.") + parser.add_argument("--verbose", "-v", action="count", default=0) + args = parser.parse_args() + + main(strict=args.strict, verbosity=args.verbose) diff --git a/i18n/segment.py b/i18n/segment.py index 7920f896c4..ded771add0 100755 --- a/i18n/segment.py +++ b/i18n/segment.py @@ -8,8 +8,9 @@ import copy import fnmatch import logging import sys - +import argparse import polib +import textwrap from i18n.config import CONFIGURATION @@ -116,27 +117,28 @@ def segment_pofile(filename, segments): return files_written -def main(argv): - """ - $ segment.py LOCALE [...] - - Segment the .po files in LOCALE(s) based on the segmenting rules in - config.yaml. - - Note that segmenting is *not* idempotent: it modifies the input file, so - be careful that you don't run it twice on the same file. - - """ +def main(locales=None, verbosity=1): # This is used as a tool only to segment translation files when adding a # new segment. In the regular workflow, the work is done by the extract # phase calling the functions above. - - logging.basicConfig(stream=sys.stdout, level=logging.INFO) - if len(argv) < 2: - sys.exit("Need a locale to segment") - for locale in argv[1:]: + locales = locales or [] + for locale in locales: segment_pofiles(locale) if __name__ == "__main__": - main(sys.argv) + logging.basicConfig(stream=sys.stdout, level=logging.INFO) + + description = textwrap.dedent(""" + Segment the .po files in LOCALE(s) based on the segmenting rules in + config.yaml. + + Note that segmenting is *not* idempotent: it modifies the input file, so + be careful that you don't run it twice on the same file. + """.strip()) + + parser = argparse.ArgumentParser(description=description) + parser.add_argument("locale", nargs="+", help="a locale to segment") + parser.add_argument("--verbose", "-v", action="count", default=0) + args = parser.parse_args() + main(locales=args.locale, verbosity=args.verbose) diff --git a/i18n/transifex.py b/i18n/transifex.py index c5df793325..5b718ed6ca 100755 --- a/i18n/transifex.py +++ b/i18n/transifex.py @@ -1,13 +1,14 @@ #!/usr/bin/env python - +from __future__ import print_function import sys from polib import pofile +import argparse from i18n.config import CONFIGURATION from i18n.execute import execute from i18n.extract import EDX_MARKER -TRANSIFEX_HEADER = 'edX community translations have been downloaded from %s' +TRANSIFEX_HEADER = 'edX community translations have been downloaded from {}' TRANSIFEX_URL = 'https://www.transifex.com/projects/p/edx-platform/' @@ -16,7 +17,7 @@ def push(): def pull(): - print "Pulling languages from transifex..." + print("Pulling languages from transifex...") execute('tx pull --mode=reviewed --all') clean_translated_locales() @@ -57,18 +58,20 @@ def clean_file(filename): def get_new_header(po): team = po.metadata.get('Language-Team', None) if not team: - return TRANSIFEX_HEADER % TRANSIFEX_URL + return TRANSIFEX_HEADER.format(TRANSIFEX_URL) else: - return TRANSIFEX_HEADER % team + return TRANSIFEX_HEADER.format(team) if __name__ == '__main__': - if len(sys.argv) < 2: - raise Exception("missing argument: push or pull") - arg = sys.argv[1] - if arg == 'push': + parser = argparse.ArgumentParser() + parser.add_argument("command", help="push or pull") + parser.add_argument("--verbose", "-v") + args = parser.parse_args() + + if args.command == "push": push() - elif arg == 'pull': + elif args.command == "pull": pull() else: - raise Exception("unknown argument: (%s)" % arg) + raise Exception("unknown command ({cmd})".format(cmd=args.command)) diff --git a/i18n/validate.py b/i18n/validate.py index 6f207ddf56..807fbfe8d6 100644 --- a/i18n/validate.py +++ b/i18n/validate.py @@ -149,20 +149,14 @@ def check_messages(filename, report_empty=False): log.info(" No problems found in {0}".format(filename)) -def parse_args(argv): +def get_parser(): """ - Parse command line arguments, returning a dict of - valid options: - - { - 'empty': BOOLEAN, - 'verbose': BOOLEAN, - 'language': str - } - - where 'language' is a language code, eg "fr" + Returns an argument parser for this script. """ - parser = argparse.ArgumentParser(description="Automatically finds translation errors in all edx-platform *.po files, for all languages, unless one or more language(s) is specified to check.") + parser = argparse.ArgumentParser(description=( + "Automatically finds translation errors in all edx-platform *.po files, " + "for all languages, unless one or more language(s) is specified to check." + )) parser.add_argument( '-l', '--language', @@ -179,39 +173,39 @@ def parse_args(argv): parser.add_argument( '-v', '--verbose', - action='store_true', + action='count', default=0, help="Turns on info-level logging." ) - return vars(parser.parse_args(argv)) + return parser -def main(): - """Main entry point for the tool.""" +def main(languages=None, empty=False, verbosity=1): + languages = languages or [] - args_dict = parse_args(sys.argv[1:]) - if args_dict['verbose']: - logging.basicConfig(stream=sys.stdout, level=logging.INFO) - else: - logging.basicConfig(stream=sys.stdout, level=logging.WARNING) - - langs = args_dict['language'] - - if langs is not None: - # lang will be a list of language codes; test each language. - for lang in langs: - root = LOCALE_DIR / lang - # Assert that a directory for this language code exists on the system - if not os.path.isdir(root): - log.error(" {0} is not a valid directory.\nSkipping language '{1}'".format(root, lang)) - continue - # If we found the language code's directory, validate the files. - validate_po_files(root, args_dict['empty']) - - else: - # If lang is None, we walk all of the .po files under root, and test each one. + if not languages: root = LOCALE_DIR - validate_po_files(root, args_dict['empty']) + validate_po_files(root, empty) + return + + # languages will be a list of language codes; test each language. + for language in languages: + root = LOCALE_DIR / language + # Assert that a directory for this language code exists on the system + if not root.isdir(): + log.error(" {0} is not a valid directory.\nSkipping language '{1}'".format(root, language)) + continue + # If we found the language code's directory, validate the files. + validate_po_files(root, empty) + if __name__ == '__main__': - main() + parser = get_parser() + args = parser.parse_args() + if args.verbose: + log_level = logging.INFO + else: + log_level = logging.WARNING + logging.basicConfig(stream=sys.stdout, level=log_level) + + main(languages=args.language, empty=args.empty, verbosity=args.verbose)