diff options
Diffstat (limited to 'babel/messages/frontend.py')
-rw-r--r-- | babel/messages/frontend.py | 94 |
1 files changed, 76 insertions, 18 deletions
diff --git a/babel/messages/frontend.py b/babel/messages/frontend.py index 62e7c03..d190a2c 100644 --- a/babel/messages/frontend.py +++ b/babel/messages/frontend.py @@ -22,7 +22,7 @@ from locale import getpreferredencoding from babel import __version__ as VERSION from babel import Locale, localedata -from babel._compat import StringIO, string_types +from babel._compat import StringIO, string_types, text_type from babel.core import UnknownLocaleError from babel.messages.catalog import Catalog from babel.messages.extract import DEFAULT_KEYWORDS, DEFAULT_MAPPING, check_and_call_extract_file, extract_from_dir @@ -39,6 +39,48 @@ except ImportError: from configparser import RawConfigParser +def listify_value(arg, split=None): + """ + Make a list out of an argument. + + Values from `distutils` argument parsing are always single strings; + values from `optparse` parsing may be lists of strings that may need + to be further split. + + No matter the input, this function returns a flat list of whitespace-trimmed + strings, with `None` values filtered out. + + >>> listify_value("foo bar") + ['foo', 'bar'] + >>> listify_value(["foo bar"]) + ['foo', 'bar'] + >>> listify_value([["foo"], "bar"]) + ['foo', 'bar'] + >>> listify_value([["foo"], ["bar", None, "foo"]]) + ['foo', 'bar', 'foo'] + >>> listify_value("foo, bar, quux", ",") + ['foo', 'bar', 'quux'] + + :param arg: A string or a list of strings + :param split: The argument to pass to `str.split()`. + :return: + """ + out = [] + + if not isinstance(arg, (list, tuple)): + arg = [arg] + + for val in arg: + if val is None: + continue + if isinstance(val, (list, tuple)): + out.extend(listify_value(val, split=split)) + continue + out.extend(s.strip() for s in text_type(val).split(split)) + assert all(isinstance(val, string_types) for val in out) + return out + + class Command(_Command): # This class is a small shim between Distutils commands and # optparse option parsing in the frontend command line. @@ -47,8 +89,21 @@ class Command(_Command): as_args = None #: Options which allow multiple values. + #: This is used by the `optparse` transmogrification code. multiple_value_options = () + #: Options which are booleans. + #: This is used by the `optparse` transmogrification code. + # (This is actually used by distutils code too, but is never + # declared in the base class.) + boolean_options = () + + #: Option aliases, to retain standalone command compatibility. + #: Distutils does not support option aliases, but optparse does. + #: This maps the distutils argument name to an iterable of aliases + #: that are usable with optparse. + option_aliases = {} + #: Log object. To allow replacement in the script command line runner. log = distutils_log @@ -110,6 +165,7 @@ class compile_catalog(Command): self.statistics = False def finalize_options(self): + self.domain = listify_value(self.domain) if not self.input_file and not self.directory: raise DistutilsOptionError('you must specify either the input file ' 'or the base directory') @@ -118,9 +174,7 @@ class compile_catalog(Command): 'or the base directory') def run(self): - domains = self.domain.split() - - for domain in domains: + for domain in self.domain: self._run_domain(domain) def _run_domain(self, domain): @@ -174,12 +228,12 @@ class compile_catalog(Command): if len(catalog): percentage = translated * 100 // len(catalog) self.log.info( - '%d of %d messages (%d%%) translated in %r', + '%d of %d messages (%d%%) translated in %s', translated, len(catalog), percentage, po_file ) if catalog.fuzzy and not self.use_fuzzy: - self.log.info('catalog %r is marked as fuzzy, skipping', po_file) + self.log.info('catalog %s is marked as fuzzy, skipping', po_file) continue for message, errors in catalog.check(): @@ -188,7 +242,7 @@ class compile_catalog(Command): 'error: %s:%d: %s', po_file, message.lineno, error ) - self.log.info('compiling catalog %r to %r', po_file, mo_file) + self.log.info('compiling catalog %s to %s', po_file, mo_file) outfile = open(mo_file, 'wb') try: @@ -249,7 +303,7 @@ class extract_messages(Command): ('add-comments=', 'c', 'place comment block with TAG (or those preceding keyword lines) in ' 'output file. Separate multiple TAGs with commas(,)'), # TODO: Support repetition of this argument - ('strip-comments', None, + ('strip-comments', 's', 'strip the comment TAGs from the comments.'), ('input-paths=', None, 'files or directories that should be scanned for messages. Separate multiple ' @@ -263,6 +317,12 @@ class extract_messages(Command): ] as_args = 'input-paths' multiple_value_options = ('add-comments', 'keywords') + option_aliases = { + 'keywords': ('--keyword',), + 'mapping-file': ('--mapping',), + 'output-file': ('--output',), + 'strip-comments': ('--strip-comment-tags',), + } def initialize_options(self): self.charset = 'utf-8' @@ -299,8 +359,7 @@ class extract_messages(Command): else: keywords = DEFAULT_KEYWORDS.copy() - for kwarg in (self.keywords or ()): - keywords.update(parse_keywords(kwarg.split())) + keywords.update(parse_keywords(listify_value(self.keywords))) self.keywords = keywords @@ -325,11 +384,13 @@ class extract_messages(Command): if self.input_paths: if isinstance(self.input_paths, string_types): self.input_paths = re.split(',\s*', self.input_paths) - else: + elif self.distribution is not None: self.input_paths = dict.fromkeys([ k.split('.', 1)[0] for k in (self.distribution.packages or ()) ]).keys() + else: + self.input_paths = [] if not self.input_paths: raise DistutilsOptionError("no input files or directories specified") @@ -338,11 +399,7 @@ class extract_messages(Command): if not os.path.exists(path): raise DistutilsOptionError("Input path: %s does not exist" % path) - if self.add_comments: - if isinstance(self.add_comments, string_types): - self.add_comments = self.add_comments.split(',') - else: - self.add_comments = [] + self.add_comments = listify_value(self.add_comments or (), ",") if self.distribution: if not self.project: @@ -531,7 +588,7 @@ class init_catalog(Command): def run(self): self.log.info( - 'creating catalog %r based on %r', self.output_file, self.input_file + 'creating catalog %s based on %s', self.output_file, self.input_file ) infile = open(self.input_file, 'rb') @@ -662,7 +719,7 @@ class update_catalog(Command): raise DistutilsOptionError('no message catalogs found') for locale, filename in po_files: - self.log.info('updating catalog %r based on %r', filename, self.input_file) + self.log.info('updating catalog %s based on %s', filename, self.input_file) infile = open(filename, 'rb') try: catalog = read_po(infile, locale=locale, domain=domain) @@ -825,6 +882,7 @@ class CommandLineInterface(object): strs = ["--%s" % name] if short: strs.append("-%s" % short) + strs.extend(cmdclass.option_aliases.get(name, ())) if name == as_args: parser.usage += "<%s>" % name elif name in cmdclass.boolean_options: |