Skip to content

Commit

Permalink
Merge pull request #394 from akx/2.3.4
Browse files Browse the repository at this point in the history
2.3.4
  • Loading branch information
akx committed Apr 22, 2016
2 parents 3086b0c + 915236c commit 6a1491a
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 39 deletions.
11 changes: 11 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Babel Changelog
===============

Version 2.3.4
-------------

(Bugfix release, released on April 22th)

Bugfixes
~~~~~~~~

* CLDR: The lxml library is no longer used for CLDR importing, so it should not cause strange failures either. Thanks to @aronbierbaum for the bug report and @jtwang for the fix. (https://github.com/python-babel/babel/pull/393)
* CLI: Every last single CLI usage regression should now be gone, and both distutils and stand-alone CLIs should work as they have in the past. Thanks to @paxswill and @ajaeger for bug reports. (https://github.com/python-babel/babel/pull/389)

Version 2.3.3
-------------

Expand Down
2 changes: 1 addition & 1 deletion babel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
negotiate_locale, parse_locale, get_locale_identifier


__version__ = '2.3.3'
__version__ = '2.3.4'
94 changes: 76 additions & 18 deletions babel/messages/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

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
Expand All @@ -39,6 +39,48 @@
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.
Expand All @@ -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

Expand Down Expand Up @@ -110,6 +165,7 @@ def initialize_options(self):
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')
Expand All @@ -118,9 +174,7 @@ def finalize_options(self):
'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):
Expand Down Expand Up @@ -174,12 +228,12 @@ def _run_domain(self, domain):
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():
Expand All @@ -188,7 +242,7 @@ def _run_domain(self, domain):
'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:
Expand Down Expand Up @@ -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 '
Expand All @@ -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'
Expand Down Expand Up @@ -299,8 +359,7 @@ def finalize_options(self):
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

Expand All @@ -325,11 +384,13 @@ def finalize_options(self):
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")
Expand All @@ -338,11 +399,7 @@ def finalize_options(self):
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:
Expand Down Expand Up @@ -531,7 +588,7 @@ def finalize_options(self):

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')
Expand Down Expand Up @@ -662,7 +719,7 @@ def run(self):
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)
Expand Down Expand Up @@ -825,6 +882,7 @@ def _configure_command(self, cmdname, argv):
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:
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
# The short X.Y version.
version = '2.3'
# The full version, including alpha/beta/rc tags.
release = '2.3.3'
release = '2.3.4'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
7 changes: 2 additions & 5 deletions scripts/import_cldr.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@
import sys

try:
import lxml.etree as ElementTree
from xml.etree import cElementTree as ElementTree
except ImportError:
try:
from xml.etree import cElementTree as ElementTree
except ImportError:
from xml.etree import ElementTree
from xml.etree import ElementTree

# Make sure we're using Babel source, and not some previously installed version
CHECKOUT_ROOT = os.path.abspath(os.path.join(
Expand Down

0 comments on commit 6a1491a

Please sign in to comment.